From 4528186e0d65fc68ef0dd1941aa2ac8aefcd55a3 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Fri, 5 Mar 2010 15:46:30 -0800 Subject: Refactor android.backup => android.app.backup Change-Id: I0b21316ff890d7f3c7d4b82837bb60670724c2e8 --- core/java/android/app/ActivityThread.java | 1 + core/java/android/app/BackupAgent.java | 191 -------------------- core/java/android/app/FullBackupAgent.java | 7 +- core/java/android/app/IBackupAgent.aidl | 6 +- .../app/backup/AbsoluteFileBackupHelper.java | 75 ++++++++ core/java/android/app/backup/BackupAgent.java | 189 ++++++++++++++++++++ core/java/android/app/backup/BackupDataInput.java | 154 ++++++++++++++++ .../android/app/backup/BackupDataInputStream.java | 63 +++++++ core/java/android/app/backup/BackupDataOutput.java | 94 ++++++++++ core/java/android/app/backup/BackupHelper.java | 53 ++++++ .../java/android/app/backup/BackupHelperAgent.java | 76 ++++++++ .../android/app/backup/BackupHelperDispatcher.java | 149 ++++++++++++++++ core/java/android/app/backup/BackupManager.java | 137 +++++++++++++++ core/java/android/app/backup/FileBackupHelper.java | 104 +++++++++++ .../android/app/backup/FileBackupHelperBase.java | 127 ++++++++++++++ core/java/android/app/backup/IBackupManager.aidl | 164 +++++++++++++++++ core/java/android/app/backup/IRestoreObserver.aidl | 50 ++++++ core/java/android/app/backup/IRestoreSession.aidl | 79 +++++++++ core/java/android/app/backup/RestoreObserver.java | 52 ++++++ core/java/android/app/backup/RestoreSession.java | 194 +++++++++++++++++++++ core/java/android/app/backup/RestoreSet.aidl | 19 ++ core/java/android/app/backup/RestoreSet.java | 87 +++++++++ .../app/backup/SharedPreferencesBackupHelper.java | 91 ++++++++++ core/java/android/app/backup/package.html | 22 +++ .../android/backup/AbsoluteFileBackupHelper.java | 75 -------- core/java/android/backup/BackupDataInput.java | 154 ---------------- .../java/android/backup/BackupDataInputStream.java | 63 ------- core/java/android/backup/BackupDataOutput.java | 94 ---------- core/java/android/backup/BackupHelper.java | 53 ------ core/java/android/backup/BackupHelperAgent.java | 77 -------- .../android/backup/BackupHelperDispatcher.java | 149 ---------------- core/java/android/backup/BackupManager.java | 135 -------------- core/java/android/backup/FileBackupHelper.java | 104 ----------- core/java/android/backup/FileBackupHelperBase.java | 127 -------------- core/java/android/backup/IBackupManager.aidl | 164 ----------------- core/java/android/backup/IRestoreObserver.aidl | 50 ------ core/java/android/backup/IRestoreSession.aidl | 79 --------- core/java/android/backup/RestoreObserver.java | 52 ------ core/java/android/backup/RestoreSession.java | 193 -------------------- core/java/android/backup/RestoreSet.aidl | 19 -- core/java/android/backup/RestoreSet.java | 87 --------- .../backup/SharedPreferencesBackupHelper.java | 91 ---------- core/java/android/backup/package.html | 22 --- core/java/android/content/Context.java | 2 +- 44 files changed, 1988 insertions(+), 1986 deletions(-) delete mode 100644 core/java/android/app/BackupAgent.java create mode 100644 core/java/android/app/backup/AbsoluteFileBackupHelper.java create mode 100644 core/java/android/app/backup/BackupAgent.java create mode 100644 core/java/android/app/backup/BackupDataInput.java create mode 100644 core/java/android/app/backup/BackupDataInputStream.java create mode 100644 core/java/android/app/backup/BackupDataOutput.java create mode 100644 core/java/android/app/backup/BackupHelper.java create mode 100644 core/java/android/app/backup/BackupHelperAgent.java create mode 100644 core/java/android/app/backup/BackupHelperDispatcher.java create mode 100644 core/java/android/app/backup/BackupManager.java create mode 100644 core/java/android/app/backup/FileBackupHelper.java create mode 100644 core/java/android/app/backup/FileBackupHelperBase.java create mode 100644 core/java/android/app/backup/IBackupManager.aidl create mode 100644 core/java/android/app/backup/IRestoreObserver.aidl create mode 100644 core/java/android/app/backup/IRestoreSession.aidl create mode 100644 core/java/android/app/backup/RestoreObserver.java create mode 100644 core/java/android/app/backup/RestoreSession.java create mode 100644 core/java/android/app/backup/RestoreSet.aidl create mode 100644 core/java/android/app/backup/RestoreSet.java create mode 100644 core/java/android/app/backup/SharedPreferencesBackupHelper.java create mode 100644 core/java/android/app/backup/package.html delete mode 100644 core/java/android/backup/AbsoluteFileBackupHelper.java delete mode 100644 core/java/android/backup/BackupDataInput.java delete mode 100644 core/java/android/backup/BackupDataInputStream.java delete mode 100644 core/java/android/backup/BackupDataOutput.java delete mode 100644 core/java/android/backup/BackupHelper.java delete mode 100644 core/java/android/backup/BackupHelperAgent.java delete mode 100644 core/java/android/backup/BackupHelperDispatcher.java delete mode 100644 core/java/android/backup/BackupManager.java delete mode 100644 core/java/android/backup/FileBackupHelper.java delete mode 100644 core/java/android/backup/FileBackupHelperBase.java delete mode 100644 core/java/android/backup/IBackupManager.aidl delete mode 100644 core/java/android/backup/IRestoreObserver.aidl delete mode 100644 core/java/android/backup/IRestoreSession.aidl delete mode 100644 core/java/android/backup/RestoreObserver.java delete mode 100644 core/java/android/backup/RestoreSession.java delete mode 100644 core/java/android/backup/RestoreSet.aidl delete mode 100644 core/java/android/backup/RestoreSet.java delete mode 100644 core/java/android/backup/SharedPreferencesBackupHelper.java delete mode 100644 core/java/android/backup/package.html (limited to 'core/java/android') diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 0756c716d494..7c49bb778486 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -16,6 +16,7 @@ package android.app; +import android.app.backup.BackupAgent; import android.content.BroadcastReceiver; import android.content.ComponentCallbacks; import android.content.ComponentName; diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java deleted file mode 100644 index 4695c21dd49b..000000000000 --- a/core/java/android/app/BackupAgent.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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 android.app; - -import android.app.IBackupAgent; -import android.backup.BackupDataInput; -import android.backup.BackupDataOutput; -import android.backup.IBackupManager; -import android.content.Context; -import android.content.ContextWrapper; -import android.os.Binder; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.Log; - -import java.io.IOException; - -/** - * This is the central interface between an application and Android's settings - * backup mechanism. Any implementation of a backup agent should perform backup - * and restore actions in - * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} - * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor)} - * respectively. - *

- * A backup agent based on convenient helper classes is available in - * {@link android.backup.BackupHelperAgent} for less complex implementation - * requirements. - *

- * STOPSHIP write more documentation about the backup process here. - */ -public abstract class BackupAgent extends ContextWrapper { - private static final String TAG = "BackupAgent"; - private static final boolean DEBUG = false; - - public BackupAgent() { - super(null); - } - - public void onCreate() { - } - - public void onDestroy() { - } - - /** - * The application is being asked to write any data changed since the last - * time it performed a backup operation. The state data recorded during the - * last backup pass is provided in the oldState file - * descriptor. If oldState is null, no old state - * is available and the application should perform a full backup. In both - * cases, a representation of the final backup state after this pass should - * be written to the file pointed to by the file descriptor wrapped in - * newState. - * - * @param oldState An open, read-only ParcelFileDescriptor pointing to the - * last backup state provided by the application. May be - * null, in which case no prior state is being - * provided and the application should perform a full backup. - * @param data A structured wrapper around an open, read/write - * ParcelFileDescriptor pointing to the backup data destination. - * Typically the application will use backup helper classes to - * write to this file. - * @param newState An open, read/write ParcelFileDescriptor pointing to an - * empty file. The application should record the final backup - * state here after writing the requested data to dataFd. - */ - public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException; - - /** - * The application is being restored from backup and should replace any - * existing data with the contents of the backup. The backup data is - * provided in the file descriptor pointed to by the - * {@link android.backup.BackupDataInput} instance data. Once - * the restore is finished, the application should write a representation of - * the final state to the newState file descriptor. - *

- * The application is responsible for properly erasing its old data and - * replacing it with the data supplied to this method. No "clear user data" - * operation will be performed automatically by the operating system. The - * exception to this is in the case of a failed restore attempt: if - * onRestore() throws an exception, the OS will assume that the - * application's data may now be in an incoherent state, and will clear it - * before proceeding. - * - * @param data A structured wrapper around an open, read-only - * ParcelFileDescriptor pointing to a full snapshot of the - * application's data. Typically the application will use helper - * classes to read this data. - * @param appVersionCode The android:versionCode value of the application - * that backed up this particular data set. This makes it easier - * for an application's agent to distinguish among several - * possible older data versions when asked to perform the restore - * operation. - * @param newState An open, read/write ParcelFileDescriptor pointing to an - * empty file. The application should record the final backup - * state here after restoring its data from dataFd. - */ - public abstract void onRestore(BackupDataInput data, int appVersionCode, - ParcelFileDescriptor newState) - throws IOException; - - - // ----- Core implementation ----- - - /** @hide */ - public final IBinder onBind() { - return mBinder; - } - - private final IBinder mBinder = new BackupServiceBinder().asBinder(); - - /** @hide */ - public void attach(Context context) { - attachBaseContext(context); - } - - // ----- IBackupService binder interface ----- - private class BackupServiceBinder extends IBackupAgent.Stub { - private static final String TAG = "BackupServiceBinder"; - - public void doBackup(ParcelFileDescriptor oldState, - ParcelFileDescriptor data, - ParcelFileDescriptor newState, - int token, IBackupManager callbackBinder) throws RemoteException { - // Ensure that we're running with the app's normal permission level - long ident = Binder.clearCallingIdentity(); - - if (DEBUG) Log.v(TAG, "doBackup() invoked"); - BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor()); - try { - BackupAgent.this.onBackup(oldState, output, newState); - } catch (IOException ex) { - Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); - throw new RuntimeException(ex); - } catch (RuntimeException ex) { - Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); - throw ex; - } finally { - Binder.restoreCallingIdentity(ident); - try { - callbackBinder.opComplete(token); - } catch (RemoteException e) { - // we'll time out anyway, so we're safe - } - } - } - - public void doRestore(ParcelFileDescriptor data, int appVersionCode, - ParcelFileDescriptor newState, - int token, IBackupManager callbackBinder) throws RemoteException { - // Ensure that we're running with the app's normal permission level - long ident = Binder.clearCallingIdentity(); - - if (DEBUG) Log.v(TAG, "doRestore() invoked"); - BackupDataInput input = new BackupDataInput(data.getFileDescriptor()); - try { - BackupAgent.this.onRestore(input, appVersionCode, newState); - } catch (IOException ex) { - Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex); - throw new RuntimeException(ex); - } catch (RuntimeException ex) { - Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex); - throw ex; - } finally { - Binder.restoreCallingIdentity(ident); - try { - callbackBinder.opComplete(token); - } catch (RemoteException e) { - // we'll time out anyway, so we're safe - } - } - } - } -} diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java index db198ad17bc5..dcfa63f6d316 100644 --- a/core/java/android/app/FullBackupAgent.java +++ b/core/java/android/app/FullBackupAgent.java @@ -1,8 +1,9 @@ package android.app; -import android.backup.BackupDataInput; -import android.backup.BackupDataOutput; -import android.backup.FileBackupHelper; +import android.app.backup.BackupAgent; +import android.app.backup.BackupDataInput; +import android.app.backup.BackupDataOutput; +import android.app.backup.FileBackupHelper; import android.os.ParcelFileDescriptor; import android.util.Log; diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl index 0de6ad9a83e2..fed2bc552926 100644 --- a/core/java/android/app/IBackupAgent.aidl +++ b/core/java/android/app/IBackupAgent.aidl @@ -16,13 +16,13 @@ package android.app; -import android.backup.IBackupManager; +import android.app.backup.IBackupManager; import android.os.ParcelFileDescriptor; /** * Interface presented by applications being asked to participate in the - * backup & restore mechanism. End user code does not typically implement - * this interface; they subclass BackupAgent instead. + * backup & restore mechanism. End user code will not typically implement + * this interface directly; they subclass BackupAgent instead. * * {@hide} */ diff --git a/core/java/android/app/backup/AbsoluteFileBackupHelper.java b/core/java/android/app/backup/AbsoluteFileBackupHelper.java new file mode 100644 index 000000000000..677224ca526c --- /dev/null +++ b/core/java/android/app/backup/AbsoluteFileBackupHelper.java @@ -0,0 +1,75 @@ +/* + * 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 android.app.backup; + +import android.content.Context; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; + +/** + * Like FileBackupHelper, but takes absolute paths for the files instead of + * subpaths of getFilesDir() + * + * STOPSHIP: document! + */ +public class AbsoluteFileBackupHelper extends FileBackupHelperBase implements BackupHelper { + private static final String TAG = "AbsoluteFileBackupHelper"; + private static final boolean DEBUG = false; + + Context mContext; + String[] mFiles; + + /** + * Construct a helper for backing up / restoring the files at the given absolute locations + * within the file system. + * + * @param context + * @param files + */ + public AbsoluteFileBackupHelper(Context context, String... files) { + super(context); + + mContext = context; + mFiles = files; + } + + /** + * Based on oldState, determine which of the files from the application's data directory + * need to be backed up, write them to the data stream, and fill in newState with the + * state as it exists now. + */ + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) { + // use the file paths as the keys, too + performBackup_checked(oldState, data, newState, mFiles, mFiles); + } + + /** + * Restore one absolute file entity from the restore stream + */ + public void restoreEntity(BackupDataInputStream data) { + if (DEBUG) Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); + String key = data.getKey(); + if (isKeyInList(key, mFiles)) { + File f = new File(key); + writeFile(f, data); + } + } +} + diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java new file mode 100644 index 000000000000..d0cb148201ae --- /dev/null +++ b/core/java/android/app/backup/BackupAgent.java @@ -0,0 +1,189 @@ +/* + * 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 android.app.backup; + +import android.app.IBackupAgent; +import android.app.backup.IBackupManager; +import android.content.Context; +import android.content.ContextWrapper; +import android.os.Binder; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import java.io.IOException; + +/** + * This is the central interface between an application and Android's settings + * backup mechanism. Any implementation of a backup agent should perform backup + * and restore actions in + * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} + * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor)} + * respectively. + *

+ * A backup agent based on convenient helper classes is available in + * {@link android.app.backup.BackupHelperAgent} for less complex implementation + * requirements. + *

+ * STOPSHIP write more documentation about the backup process here. + */ +public abstract class BackupAgent extends ContextWrapper { + private static final String TAG = "BackupAgent"; + private static final boolean DEBUG = false; + + public BackupAgent() { + super(null); + } + + public void onCreate() { + } + + public void onDestroy() { + } + + /** + * The application is being asked to write any data changed since the last + * time it performed a backup operation. The state data recorded during the + * last backup pass is provided in the oldState file + * descriptor. If oldState is null, no old state + * is available and the application should perform a full backup. In both + * cases, a representation of the final backup state after this pass should + * be written to the file pointed to by the file descriptor wrapped in + * newState. + * + * @param oldState An open, read-only ParcelFileDescriptor pointing to the + * last backup state provided by the application. May be + * null, in which case no prior state is being + * provided and the application should perform a full backup. + * @param data A structured wrapper around an open, read/write + * ParcelFileDescriptor pointing to the backup data destination. + * Typically the application will use backup helper classes to + * write to this file. + * @param newState An open, read/write ParcelFileDescriptor pointing to an + * empty file. The application should record the final backup + * state here after writing the requested data to dataFd. + */ + public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException; + + /** + * The application is being restored from backup and should replace any + * existing data with the contents of the backup. The backup data is + * provided in the file descriptor pointed to by the + * {@link android.app.backup.BackupDataInput} instance data. Once + * the restore is finished, the application should write a representation of + * the final state to the newState file descriptor. + *

+ * The application is responsible for properly erasing its old data and + * replacing it with the data supplied to this method. No "clear user data" + * operation will be performed automatically by the operating system. The + * exception to this is in the case of a failed restore attempt: if + * onRestore() throws an exception, the OS will assume that the + * application's data may now be in an incoherent state, and will clear it + * before proceeding. + * + * @param data A structured wrapper around an open, read-only + * ParcelFileDescriptor pointing to a full snapshot of the + * application's data. Typically the application will use helper + * classes to read this data. + * @param appVersionCode The android:versionCode value of the application + * that backed up this particular data set. This makes it easier + * for an application's agent to distinguish among several + * possible older data versions when asked to perform the restore + * operation. + * @param newState An open, read/write ParcelFileDescriptor pointing to an + * empty file. The application should record the final backup + * state here after restoring its data from dataFd. + */ + public abstract void onRestore(BackupDataInput data, int appVersionCode, + ParcelFileDescriptor newState) + throws IOException; + + + // ----- Core implementation ----- + + /** @hide */ + public final IBinder onBind() { + return mBinder; + } + + private final IBinder mBinder = new BackupServiceBinder().asBinder(); + + /** @hide */ + public void attach(Context context) { + attachBaseContext(context); + } + + // ----- IBackupService binder interface ----- + private class BackupServiceBinder extends IBackupAgent.Stub { + private static final String TAG = "BackupServiceBinder"; + + public void doBackup(ParcelFileDescriptor oldState, + ParcelFileDescriptor data, + ParcelFileDescriptor newState, + int token, IBackupManager callbackBinder) throws RemoteException { + // Ensure that we're running with the app's normal permission level + long ident = Binder.clearCallingIdentity(); + + if (DEBUG) Log.v(TAG, "doBackup() invoked"); + BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor()); + try { + BackupAgent.this.onBackup(oldState, output, newState); + } catch (IOException ex) { + Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw new RuntimeException(ex); + } catch (RuntimeException ex) { + Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw ex; + } finally { + Binder.restoreCallingIdentity(ident); + try { + callbackBinder.opComplete(token); + } catch (RemoteException e) { + // we'll time out anyway, so we're safe + } + } + } + + public void doRestore(ParcelFileDescriptor data, int appVersionCode, + ParcelFileDescriptor newState, + int token, IBackupManager callbackBinder) throws RemoteException { + // Ensure that we're running with the app's normal permission level + long ident = Binder.clearCallingIdentity(); + + if (DEBUG) Log.v(TAG, "doRestore() invoked"); + BackupDataInput input = new BackupDataInput(data.getFileDescriptor()); + try { + BackupAgent.this.onRestore(input, appVersionCode, newState); + } catch (IOException ex) { + Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw new RuntimeException(ex); + } catch (RuntimeException ex) { + Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw ex; + } finally { + Binder.restoreCallingIdentity(ident); + try { + callbackBinder.opComplete(token); + } catch (RemoteException e) { + // we'll time out anyway, so we're safe + } + } + } + } +} diff --git a/core/java/android/app/backup/BackupDataInput.java b/core/java/android/app/backup/BackupDataInput.java new file mode 100644 index 000000000000..2da0c11182b8 --- /dev/null +++ b/core/java/android/app/backup/BackupDataInput.java @@ -0,0 +1,154 @@ +/* + * 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 android.app.backup; + +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * STOPSHIP: document! + */ +public class BackupDataInput { + int mBackupReader; + + private EntityHeader mHeader = new EntityHeader(); + private boolean mHeaderReady; + + private static class EntityHeader { + String key; + int dataSize; + } + + /** @hide */ + public BackupDataInput(FileDescriptor fd) { + if (fd == null) throw new NullPointerException(); + mBackupReader = ctor(fd); + if (mBackupReader == 0) { + throw new RuntimeException("Native initialization failed with fd=" + fd); + } + } + + /** @hide */ + protected void finalize() throws Throwable { + try { + dtor(mBackupReader); + } finally { + super.finalize(); + } + } + + /** + * Consumes the next header from the restore stream. + * + * @return true when there is an entity ready for consumption from the restore stream, + * false if the restore stream has been fully consumed. + * @throws IOException if an error occurred while reading the restore stream + */ + public boolean readNextHeader() throws IOException { + int result = readNextHeader_native(mBackupReader, mHeader); + if (result == 0) { + // read successfully + mHeaderReady = true; + return true; + } else if (result > 0) { + // done + mHeaderReady = false; + return false; + } else { + // error + mHeaderReady = false; + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } + + /** + * Report the key associated with the current record in the restore stream + * @return the current record's key string + * @throws IllegalStateException if the next record header has not yet been read + */ + public String getKey() { + if (mHeaderReady) { + return mHeader.key; + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + /** + * Report the size in bytes of the data associated with the current record in the + * restore stream. + * + * @return The size of the record's raw data, in bytes + * @throws IllegalStateException if the next record header has not yet been read + */ + public int getDataSize() { + if (mHeaderReady) { + return mHeader.dataSize; + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + /** + * Read a record's raw data from the restore stream. The record's header must first + * have been processed by the {@link #readNextHeader()} method. Multiple calls to + * this method may be made in order to process the data in chunks; not all of it + * must be read in a single call. + * + * @param data An allocated byte array of at least 'size' bytes + * @param offset Offset within the 'data' array at which the data will be placed + * when read from the stream. + * @param size The number of bytes to read in this pass. + * @return The number of bytes of data read + * @throws IOException if an error occurred when trying to read the restore data stream + */ + public int readEntityData(byte[] data, int offset, int size) throws IOException { + if (mHeaderReady) { + int result = readEntityData_native(mBackupReader, data, offset, size); + if (result >= 0) { + return result; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + /** + * Consume the current record's data without actually reading it into a buffer + * for further processing. This allows a {@link android.app.backup.BackupAgent} to + * efficiently discard obsolete or otherwise uninteresting records during the + * restore operation. + * + * @throws IOException if an error occurred when trying to read the restore data stream + */ + public void skipEntityData() throws IOException { + if (mHeaderReady) { + skipEntityData_native(mBackupReader); + } else { + throw new IllegalStateException("mHeaderReady=false"); + } + } + + private native static int ctor(FileDescriptor fd); + private native static void dtor(int mBackupReader); + + private native int readNextHeader_native(int mBackupReader, EntityHeader entity); + private native int readEntityData_native(int mBackupReader, byte[] data, int offset, int size); + private native int skipEntityData_native(int mBackupReader); +} diff --git a/core/java/android/app/backup/BackupDataInputStream.java b/core/java/android/app/backup/BackupDataInputStream.java new file mode 100644 index 000000000000..a7f4ba6388fb --- /dev/null +++ b/core/java/android/app/backup/BackupDataInputStream.java @@ -0,0 +1,63 @@ +/* + * 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 android.app.backup; + +import java.io.InputStream; +import java.io.IOException; + +/** + * STOPSHIP: document */ +public class BackupDataInputStream extends InputStream { + + String key; + int dataSize; + + BackupDataInput mData; + byte[] mOneByte; + + /** @hide */ + BackupDataInputStream(BackupDataInput data) { + mData = data; + } + + public int read() throws IOException { + byte[] one = mOneByte; + if (mOneByte == null) { + one = mOneByte = new byte[1]; + } + mData.readEntityData(one, 0, 1); + return one[0]; + } + + public int read(byte[] b, int offset, int size) throws IOException { + return mData.readEntityData(b, offset, size); + } + + public int read(byte[] b) throws IOException { + return mData.readEntityData(b, 0, b.length); + } + + public String getKey() { + return this.key; + } + + public int size() { + return this.dataSize; + } +} + + diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java new file mode 100644 index 000000000000..53b1d46f227a --- /dev/null +++ b/core/java/android/app/backup/BackupDataOutput.java @@ -0,0 +1,94 @@ +/* + * 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 android.app.backup; + +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * STOPSHIP: document + */ +public class BackupDataOutput { + int mBackupWriter; + + public static final int OP_UPDATE = 1; + public static final int OP_DELETE = 2; + + /** @hide */ + public BackupDataOutput(FileDescriptor fd) { + if (fd == null) throw new NullPointerException(); + mBackupWriter = ctor(fd); + if (mBackupWriter == 0) { + throw new RuntimeException("Native initialization failed with fd=" + fd); + } + } + + /** + * Mark the beginning of one record in the backup data stream. + * + * @param key + * @param dataSize The size in bytes of this record's data. Passing a dataSize + * of -1 indicates that the record under this key should be deleted. + * @return The number of bytes written to the backup stream + * @throws IOException if the write failed + */ + public int writeEntityHeader(String key, int dataSize) throws IOException { + int result = writeEntityHeader_native(mBackupWriter, key, dataSize); + if (result >= 0) { + return result; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } + + /** + * Write a chunk of data under the current entity to the backup transport. + * @param data A raw data buffer to send + * @param size The number of bytes to be sent in this chunk + * @return the number of bytes written + * @throws IOException if the write failed + */ + public int writeEntityData(byte[] data, int size) throws IOException { + int result = writeEntityData_native(mBackupWriter, data, size); + if (result >= 0) { + return result; + } else { + throw new IOException("result=0x" + Integer.toHexString(result)); + } + } + + public void setKeyPrefix(String keyPrefix) { + setKeyPrefix_native(mBackupWriter, keyPrefix); + } + + /** @hide */ + protected void finalize() throws Throwable { + try { + dtor(mBackupWriter); + } finally { + super.finalize(); + } + } + + private native static int ctor(FileDescriptor fd); + private native static void dtor(int mBackupWriter); + + private native static int writeEntityHeader_native(int mBackupWriter, String key, int dataSize); + private native static int writeEntityData_native(int mBackupWriter, byte[] data, int size); + private native static void setKeyPrefix_native(int mBackupWriter, String keyPrefix); +} + diff --git a/core/java/android/app/backup/BackupHelper.java b/core/java/android/app/backup/BackupHelper.java new file mode 100644 index 000000000000..dca23881a8fc --- /dev/null +++ b/core/java/android/app/backup/BackupHelper.java @@ -0,0 +1,53 @@ +/* + * 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 android.app.backup; + +import android.os.ParcelFileDescriptor; + +/** + * A convenient interface to be used with the + * {@link android.app.backup.BackupHelperAgent} to implement backup and restore of + * arbitrary data types. + *

+ * STOPSHOP: document! + */ +public interface BackupHelper { + /** + * Based on oldState, determine which of the files from the + * application's data directory need to be backed up, write them to + * data, and fill in newState with the state as it + * exists now. + */ + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState); + + /** + * Called by BackupHelperAgent to restore one entity from the restore dataset. + *

+ * Do not close the data stream. Do not read more than + * data.size() bytes from data. + */ + public void restoreEntity(BackupDataInputStream data); + + /** + * Called by BackupHelperAgent to write the new backup state file corresponding to + * the current state of the app's data at the time the backup operation was + * performed. + */ + public void writeNewStateDescription(ParcelFileDescriptor fd); +} + diff --git a/core/java/android/app/backup/BackupHelperAgent.java b/core/java/android/app/backup/BackupHelperAgent.java new file mode 100644 index 000000000000..6f4a0316c141 --- /dev/null +++ b/core/java/android/app/backup/BackupHelperAgent.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 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.ParcelFileDescriptor; + +import java.io.IOException; + +/** + * A convenient BackupAgent wrapper class that automatically manages + * heterogeneous data sets within the backup data, each identified by a unique + * key prefix. An application will typically extend this class in their own + * backup agent. Then, within the agent's onBackup() and onRestore() methods, it + * will call {@link #addHelper(String, BackupHelper)} one or more times to + * specify the data sets, then invoke super.onBackup() or super.onRestore() to + * have the BackupHelperAgent implementation process the data. + *

+ * STOPSHIP: document! + */ +public class BackupHelperAgent extends BackupAgent { + static final String TAG = "BackupHelperAgent"; + + BackupHelperDispatcher mDispatcher = new BackupHelperDispatcher(); + + /** + * Run the backup process on each of the configured handlers. + */ + @Override + public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + mDispatcher.performBackup(oldState, data, newState); + } + + /** + * Run the restore process on each of the configured handlers. + */ + @Override + public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) + throws IOException { + mDispatcher.performRestore(data, appVersionCode, newState); + } + + /** @hide */ + public BackupHelperDispatcher getDispatcher() { + return mDispatcher; + } + + /** + * Add a helper for a given data subset to the agent's configuration. Each helper + * must have a prefix string that is unique within this backup agent's set of + * helpers. + * + * @param keyPrefix A string used to disambiguate the various helpers within this agent + * @param helper A backup/restore helper object to be invoked during backup and restore + * operations. + */ + public void addHelper(String keyPrefix, BackupHelper helper) { + mDispatcher.addHelper(keyPrefix, helper); + } +} + + diff --git a/core/java/android/app/backup/BackupHelperDispatcher.java b/core/java/android/app/backup/BackupHelperDispatcher.java new file mode 100644 index 000000000000..5466db561576 --- /dev/null +++ b/core/java/android/app/backup/BackupHelperDispatcher.java @@ -0,0 +1,149 @@ +/* + * 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 android.app.backup; + +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.Map; +import java.util.TreeMap; + +/** @hide */ +public class BackupHelperDispatcher { + private static final String TAG = "BackupHelperDispatcher"; + + private static class Header { + int chunkSize; // not including the header + String keyPrefix; + } + + TreeMap mHelpers = new TreeMap(); + + public BackupHelperDispatcher() { + } + + public void addHelper(String keyPrefix, BackupHelper helper) { + mHelpers.put(keyPrefix, helper); + } + + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + // First, do the helpers that we've already done, since they're already in the state + // file. + int err; + Header header = new Header(); + TreeMap helpers = (TreeMap)mHelpers.clone(); + FileDescriptor oldStateFD = null; + FileDescriptor newStateFD = newState.getFileDescriptor(); + + if (oldState != null) { + oldStateFD = oldState.getFileDescriptor(); + while ((err = readHeader_native(header, oldStateFD)) >= 0) { + if (err == 0) { + BackupHelper helper = helpers.get(header.keyPrefix); + Log.d(TAG, "handling existing helper '" + header.keyPrefix + "' " + helper); + if (helper != null) { + doOneBackup(oldState, data, newState, header, helper); + helpers.remove(header.keyPrefix); + } else { + skipChunk_native(oldStateFD, header.chunkSize); + } + } + } + } + + // Then go through and do the rest that we haven't done. + for (Map.Entry entry: helpers.entrySet()) { + header.keyPrefix = entry.getKey(); + Log.d(TAG, "handling new helper '" + header.keyPrefix + "'"); + BackupHelper helper = entry.getValue(); + doOneBackup(oldState, data, newState, header, helper); + } + } + + private void doOneBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState, Header header, BackupHelper helper) + throws IOException { + int err; + FileDescriptor newStateFD = newState.getFileDescriptor(); + + // allocate space for the header in the file + int pos = allocateHeader_native(header, newStateFD); + if (pos < 0) { + throw new IOException("allocateHeader_native failed (error " + pos + ")"); + } + + data.setKeyPrefix(header.keyPrefix); + + // do the backup + helper.performBackup(oldState, data, newState); + + // fill in the header (seeking back to pos). The file pointer will be returned to + // where it was at the end of performBackup. Header.chunkSize will not be filled in. + err = writeHeader_native(header, newStateFD, pos); + if (err != 0) { + throw new IOException("writeHeader_native failed (error " + err + ")"); + } + } + + public void performRestore(BackupDataInput input, int appVersionCode, + ParcelFileDescriptor newState) + throws IOException { + boolean alreadyComplained = false; + + BackupDataInputStream stream = new BackupDataInputStream(input); + while (input.readNextHeader()) { + + String rawKey = input.getKey(); + int pos = rawKey.indexOf(':'); + if (pos > 0) { + String prefix = rawKey.substring(0, pos); + BackupHelper helper = mHelpers.get(prefix); + if (helper != null) { + stream.dataSize = input.getDataSize(); + stream.key = rawKey.substring(pos+1); + helper.restoreEntity(stream); + } else { + if (!alreadyComplained) { + Log.w(TAG, "Couldn't find helper for: '" + rawKey + "'"); + alreadyComplained = true; + } + } + } else { + if (!alreadyComplained) { + Log.w(TAG, "Entity with no prefix: '" + rawKey + "'"); + alreadyComplained = true; + } + } + input.skipEntityData(); // In case they didn't consume the data. + } + + // Write out the state files -- mHelpers is a TreeMap, so the order is well defined. + for (BackupHelper helper: mHelpers.values()) { + helper.writeNewStateDescription(newState); + } + } + + private static native int readHeader_native(Header h, FileDescriptor fd); + private static native int skipChunk_native(FileDescriptor fd, int bytesToSkip); + + private static native int allocateHeader_native(Header h, FileDescriptor fd); + private static native int writeHeader_native(Header h, FileDescriptor fd, int pos); +} + diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java new file mode 100644 index 000000000000..12d4daf09900 --- /dev/null +++ b/core/java/android/app/backup/BackupManager.java @@ -0,0 +1,137 @@ +/* + * 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 android.app.backup; + +import android.app.backup.RestoreSession; +import android.app.backup.IBackupManager; +import android.app.backup.IRestoreSession; +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +/** + * BackupManager is the interface to the system's backup service. Applications + * simply instantiate one, and then use that instance to communicate with the + * backup infrastructure. + *

+ * When an application has made changes to data which should be backed up, a + * call to {@link #dataChanged()} will notify the backup service. The system + * will then schedule a backup operation to occur in the near future. Repeated + * calls to {@link #dataChanged()} have no further effect until the backup + * operation actually occurs. + *

+ * The backup operation itself begins with the system launching the + * {@link android.app.backup.BackupAgent} subclass declared in your manifest. See the + * documentation for {@link android.app.backup.BackupAgent} for a detailed description + * of how the backup then proceeds. + *

+ * A simple implementation of a BackupAgent useful for backing up Preferences + * and files is available by using {@link android.app.backup.BackupHelperAgent}. + *

+ * STOPSHIP: more documentation! + *

+ * XML attributes + *

+ * See {@link android.R.styleable#AndroidManifestApplication + * AndroidManifest.xml's application attributes} + * + * @attr ref android.R.styleable#AndroidManifestApplication_allowBackup + * @attr ref android.R.styleable#AndroidManifestApplication_backupAgent + * @attr ref + * android.R.styleable#AndroidManifestApplication_restoreNeedsApplication + * @attr ref android.R.styleable#AndroidManifestApplication_killAfterRestore + */ +public class BackupManager { + private static final String TAG = "BackupManager"; + + private Context mContext; + private static IBackupManager sService; + + private static void checkServiceBinder() { + if (sService == null) { + sService = IBackupManager.Stub.asInterface( + ServiceManager.getService(Context.BACKUP_SERVICE)); + } + } + + /** + * Constructs a BackupManager object through which the application can + * communicate with the Android backup system. + * + * @param context The {@link android.content.Context} that was provided when + * one of your application's {@link android.app.Activity Activities} + * was created. + */ + public BackupManager(Context context) { + mContext = context; + } + + /** + * Notifies the Android backup system that your application wishes to back up + * new changes to its data. A backup operation using your application's + * {@link android.app.backup.BackupAgent} subclass will be scheduled when you call this method. + */ + public void dataChanged() { + checkServiceBinder(); + if (sService != null) { + try { + sService.dataChanged(mContext.getPackageName()); + } catch (RemoteException e) { + Log.d(TAG, "dataChanged() couldn't connect"); + } + } + } + + /** + * Convenience method for callers who need to indicate that some other package + * needs a backup pass. This can be relevant in the case of groups of packages + * that share a uid, for example. + * + * This method requires that the application hold the "android.permission.BACKUP" + * permission if the package named in the argument is not the caller's own. + */ + public static void dataChanged(String packageName) { + checkServiceBinder(); + if (sService != null) { + try { + sService.dataChanged(packageName); + } catch (RemoteException e) { + Log.d(TAG, "dataChanged(pkg) couldn't connect"); + } + } + } + + /** + * Begin the process of restoring data from backup. See the + * {@link android.app.backup.RestoreSession} class for documentation on that process. + */ + public RestoreSession beginRestoreSession() { + RestoreSession session = null; + checkServiceBinder(); + if (sService != null) { + try { + String transport = sService.getCurrentTransport(); + IRestoreSession binder = sService.beginRestoreSession(transport); + session = new RestoreSession(mContext, binder); + } catch (RemoteException e) { + Log.w(TAG, "beginRestoreSession() couldn't connect"); + } + } + return session; + } +} diff --git a/core/java/android/app/backup/FileBackupHelper.java b/core/java/android/app/backup/FileBackupHelper.java new file mode 100644 index 000000000000..b42049eb91b9 --- /dev/null +++ b/core/java/android/app/backup/FileBackupHelper.java @@ -0,0 +1,104 @@ +/* + * 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 android.app.backup; + +import android.content.Context; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; + +/** + * A helper class which can be used in conjunction with + * {@link android.app.backup.BackupHelperAgent} to manage the backup of a set of + * files. Whenever backup is performed, all files changed since the last backup + * will be saved in their entirety. During the first time the backup happens, + * all the files in the list will be backed up. Note that this should only be + * used with small configuration files and not with large binary files. + *

+ * Any files not present in the list of files during the restore procedure will + * be ignored. If files present in a previous version of an application are + * removed in subsequent versions, it is the responsibility of the developer to + * design a mechanism to remove those files. Otherwise files no longer needed + * will linger and consume space on the device. + *

+ * STOPSHIP: document! [manages backup of a set of files; restore is totally + * opaque] + */ +public class FileBackupHelper extends FileBackupHelperBase implements BackupHelper { + private static final String TAG = "FileBackupHelper"; + private static final boolean DEBUG = false; + + Context mContext; + File mFilesDir; + String[] mFiles; + + /** + * Construct a helper to manage backup/restore of entire files within the + * application's data directory hierarchy. + * + * @param context The backup agent's Context object + * @param files A list of the files to be backed up or restored. + */ + public FileBackupHelper(Context context, String... files) { + super(context); + + mContext = context; + mFilesDir = context.getFilesDir(); + mFiles = files; + } + + /** + * Based on oldState, determine which of the files from the + * application's data directory need to be backed up, write them to the data + * stream, and fill in newState with the state as it exists + * now. When oldState is null, all the files will + * be backed up. + *

+ * This should be called from {@link android.app.backup.BackupHelperAgent} + * directly. See + * {@link android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} + * for a description of parameter meanings. + */ + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) { + // file names + String[] files = mFiles; + File base = mContext.getFilesDir(); + final int N = files.length; + String[] fullPaths = new String[N]; + for (int i=0; iCallers must hold the android.permission.BACKUP permission to use this method. + */ + void setBackupEnabled(boolean isEnabled); + + /** + * Enable/disable automatic restore of application data at install time. When + * enabled, installation of any package will involve the Backup Manager. If data + * exists for the newly-installed package, either from the device's current [enabled] + * backup dataset or from the restore set used in the last wholesale restore operation, + * that data will be supplied to the new package's restore agent before the package + * is made generally available for launch. + * + *

Callers must hold the android.permission.BACKUP permission to use this method. + * + * @param doAutoRestore When true, enables the automatic app-data restore facility. When + * false, this facility will be disabled. + */ + void setAutoRestore(boolean doAutoRestore); + + /** + * Indicate that any necessary one-time provisioning has occurred. + * + *

Callers must hold the android.permission.BACKUP permission to use this method. + */ + void setBackupProvisioned(boolean isProvisioned); + + /** + * Report whether the backup mechanism is currently enabled. + * + *

Callers must hold the android.permission.BACKUP permission to use this method. + */ + boolean isBackupEnabled(); + + /** + * Schedule an immediate backup attempt for all pending updates. This is + * primarily intended for transports to use when they detect a suitable + * opportunity for doing a backup pass. If there are no pending updates to + * be sent, no action will be taken. Even if some updates are pending, the + * transport will still be asked to confirm via the usual requestBackupTime() + * method. + * + *

Callers must hold the android.permission.BACKUP permission to use this method. + */ + void backupNow(); + + /** + * Identify the currently selected transport. Callers must hold the + * android.permission.BACKUP permission to use this method. + */ + String getCurrentTransport(); + + /** + * Request a list of all available backup transports' names. Callers must + * hold the android.permission.BACKUP permission to use this method. + */ + String[] listAllTransports(); + + /** + * Specify the current backup transport. Callers must hold the + * android.permission.BACKUP permission to use this method. + * + * @param transport The name of the transport to select. This should be one + * of {@link BackupManager.TRANSPORT_GOOGLE} or {@link BackupManager.TRANSPORT_ADB}. + * @return The name of the previously selected transport. If the given transport + * name is not one of the currently available transports, no change is made to + * the current transport setting and the method returns null. + */ + String selectBackupTransport(String transport); + + /** + * Begin a restore session with the given transport (which may differ from the + * currently-active backup transport). + * + * @param transport The name of the transport to use for the restore operation. + * @return An interface to the restore session, or null on error. + */ + IRestoreSession beginRestoreSession(String transportID); + + /** + * Notify the backup manager that a BackupAgent has completed the operation + * corresponding to the given token. + * + * @param token The transaction token passed to a BackupAgent's doBackup() or + * doRestore() method. + * {@hide} + */ + void opComplete(int token); +} diff --git a/core/java/android/app/backup/IRestoreObserver.aidl b/core/java/android/app/backup/IRestoreObserver.aidl new file mode 100644 index 000000000000..75d0d175fdfc --- /dev/null +++ b/core/java/android/app/backup/IRestoreObserver.aidl @@ -0,0 +1,50 @@ +/* + * 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 android.app.backup; + +/** + * Callback class for receiving progress reports during a restore operation. + * + * @hide + */ +interface IRestoreObserver { + /** + * The restore operation has begun. + * + * @param numPackages The total number of packages being processed in + * this restore operation. + */ + void restoreStarting(int numPackages); + + /** + * An indication of which package is being restored currently, out of the + * total number provided in the restoreStarting() callback. This method + * is not guaranteed to be called. + * + * @param nowBeingRestored The index, between 1 and the numPackages parameter + * to the restoreStarting() callback, of the package now being restored. + */ + void onUpdate(int nowBeingRestored); + + /** + * The restore operation has completed. + * + * @param error Zero on success; a nonzero error code if the restore operation + * as a whole failed. + */ + void restoreFinished(int error); +} diff --git a/core/java/android/app/backup/IRestoreSession.aidl b/core/java/android/app/backup/IRestoreSession.aidl new file mode 100644 index 000000000000..58c21fea40a8 --- /dev/null +++ b/core/java/android/app/backup/IRestoreSession.aidl @@ -0,0 +1,79 @@ +/* + * 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 android.app.backup; + +import android.app.backup.RestoreSet; +import android.app.backup.IRestoreObserver; + +/** + * Binder interface used by clients who wish to manage a restore operation. Every + * method in this interface requires the android.permission.BACKUP permission. + * + * {@hide} + */ +interface IRestoreSession { + /** + * Ask the current transport what the available restore sets are. + * + * @return A bundle containing two elements: an int array under the key + * "tokens" whose entries are a transport-private identifier for each backup set; + * and a String array under the key "names" whose entries are the user-meaningful + * text corresponding to the backup sets at each index in the tokens array. + */ + RestoreSet[] getAvailableRestoreSets(); + + /** + * Restore the given set onto the device, replacing the current data of any app + * contained in the restore set with the data previously backed up. + * + *

Callers must hold the android.permission.BACKUP permission to use this method. + * + * @return Zero on success; nonzero on error. The observer will only receive + * progress callbacks if this method returned zero. + * @param token The token from {@link getAvailableRestoreSets()} corresponding to + * the restore set that should be used. + * @param observer If non-null, this binder points to an object that will receive + * progress callbacks during the restore operation. + */ + int restoreAll(long token, IRestoreObserver observer); + + /** + * Restore a single application from backup. The data will be restored from the + * current backup dataset if the given package has stored data there, or from + * the dataset used during the last full device setup operation if the current + * backup dataset has no matching data. If no backup data exists for this package + * in either source, a nonzero value will be returned. + * + * @return Zero on success; nonzero on error. The observer will only receive + * progress callbacks if this method returned zero. + * @param packageName The name of the package whose data to restore. If this is + * not the name of the caller's own package, then the android.permission.BACKUP + * permission must be held. + * @param observer If non-null, this binder points to an object that will receive + * progress callbacks during the restore operation. + */ + int restorePackage(in String packageName, IRestoreObserver observer); + + /** + * End this restore session. After this method is called, the IRestoreSession binder + * is no longer valid. + * + *

Note: The caller must invoke this method to end the restore session, + * even if {@link getAvailableRestoreSets} or {@link performRestore} failed. + */ + void endRestoreSession(); +} diff --git a/core/java/android/app/backup/RestoreObserver.java b/core/java/android/app/backup/RestoreObserver.java new file mode 100644 index 000000000000..7a5e10b72ea7 --- /dev/null +++ b/core/java/android/app/backup/RestoreObserver.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 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; + +/** + * Callback class for receiving progress reports during a restore operation. These + * methods will all be called on your application's main thread. + */ +public abstract class RestoreObserver { + /** + * The restore operation has begun. + * + * @param numPackages The total number of packages being processed in + * this restore operation. + */ + void restoreStarting(int numPackages) { + } + + /** + * An indication of which package is being restored currently, out of the + * total number provided in the restoreStarting() callback. This method + * is not guaranteed to be called. + * + * @param nowBeingRestored The index, between 1 and the numPackages parameter + * to the restoreStarting() callback, of the package now being restored. + */ + void onUpdate(int nowBeingRestored) { + } + + /** + * The restore operation has completed. + * + * @param error Zero on success; a nonzero error code if the restore operation + * as a whole failed. + */ + void restoreFinished(int error) { + } +} diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java new file mode 100644 index 000000000000..730a21ffcfd5 --- /dev/null +++ b/core/java/android/app/backup/RestoreSession.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2010 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.app.backup.RestoreObserver; +import android.app.backup.RestoreSet; +import android.app.backup.IRestoreObserver; +import android.app.backup.IRestoreSession; +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; + +/** + * Interface for applications to use when managing a restore session. + */ +public class RestoreSession { + static final String TAG = "RestoreSession"; + + final Context mContext; + IRestoreSession mBinder; + RestoreObserverWrapper mObserver = null; + + /** + * Ask the current transport what the available restore sets are. + * + * @return A bundle containing two elements: an int array under the key + * "tokens" whose entries are a transport-private identifier for each backup set; + * and a String array under the key "names" whose entries are the user-meaningful + * text corresponding to the backup sets at each index in the tokens array. + * On error, returns null. + * + * {@hide} + */ + public RestoreSet[] getAvailableRestoreSets() { + try { + return mBinder.getAvailableRestoreSets(); + } catch (RemoteException e) { + Log.d(TAG, "Can't contact server to get available sets"); + return null; + } + } + + /** + * Restore the given set onto the device, replacing the current data of any app + * contained in the restore set with the data previously backed up. + * + *

Callers must hold the android.permission.BACKUP permission to use this method. + * + * @return Zero on success; nonzero on error. The observer will only receive + * progress callbacks if this method returned zero. + * @param token The token from {@link #getAvailableRestoreSets()} corresponding to + * the restore set that should be used. + * @param observer If non-null, this binder points to an object that will receive + * progress callbacks during the restore operation. + * + * {@hide} + */ + public int restoreAll(long token, RestoreObserver observer) { + int err = -1; + if (mObserver != null) { + Log.d(TAG, "restoreAll() called during active restore"); + return -1; + } + mObserver = new RestoreObserverWrapper(mContext, observer); + try { + err = mBinder.restoreAll(token, mObserver); + } catch (RemoteException e) { + Log.d(TAG, "Can't contact server to restore"); + } + return err; + } + + /** + * Restore a single application from backup. The data will be restored from the + * current backup dataset if the given package has stored data there, or from + * the dataset used during the last full device setup operation if the current + * backup dataset has no matching data. If no backup data exists for this package + * in either source, a nonzero value will be returned. + * + * @return Zero on success; nonzero on error. The observer will only receive + * progress callbacks if this method returned zero. + * @param packageName The name of the package whose data to restore. If this is + * not the name of the caller's own package, then the android.permission.BACKUP + * permission must be held. + * @param observer If non-null, this binder points to an object that will receive + * progress callbacks during the restore operation. + */ + public int restorePackage(String packageName, RestoreObserver observer) { + int err = -1; + if (mObserver != null) { + Log.d(TAG, "restorePackage() called during active restore"); + return -1; + } + mObserver = new RestoreObserverWrapper(mContext, observer); + try { + err = mBinder.restorePackage(packageName, mObserver); + } catch (RemoteException e) { + Log.d(TAG, "Can't contact server to restore package"); + } + return err; + } + + /** + * End this restore session. After this method is called, the RestoreSession + * object is no longer valid. + * + *

Note: The caller must invoke this method to end the restore session, + * even if {@link #restorePackage(String, RestoreObserver)} failed. + */ + public void endRestoreSession() { + try { + mBinder.endRestoreSession(); + } catch (RemoteException e) { + Log.d(TAG, "Can't contact server to get available sets"); + } finally { + mBinder = null; + } + } + + /* + * Nonpublic implementation here + */ + + RestoreSession(Context context, IRestoreSession binder) { + mContext = context; + mBinder = binder; + } + + /* + * We wrap incoming binder calls with a private class implementation that + * redirects them into main-thread actions. This serializes the restore + * progress callbacks nicely within the usual main-thread lifecycle pattern. + */ + private class RestoreObserverWrapper extends IRestoreObserver.Stub { + final Handler mHandler; + final RestoreObserver mAppObserver; + + static final int MSG_RESTORE_STARTING = 1; + static final int MSG_UPDATE = 2; + static final int MSG_RESTORE_FINISHED = 3; + + RestoreObserverWrapper(Context context, RestoreObserver appObserver) { + mHandler = new Handler(context.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_RESTORE_STARTING: + mAppObserver.restoreStarting(msg.arg1); + break; + case MSG_UPDATE: + mAppObserver.onUpdate(msg.arg1); + break; + case MSG_RESTORE_FINISHED: + mAppObserver.restoreFinished(msg.arg1); + break; + } + } + }; + mAppObserver = appObserver; + } + + // Binder calls into this object just enqueue on the main-thread handler + public void restoreStarting(int numPackages) { + mHandler.sendMessage( + mHandler.obtainMessage(MSG_RESTORE_STARTING, numPackages, 0)); + } + + public void onUpdate(int nowBeingRestored) { + mHandler.sendMessage( + mHandler.obtainMessage(MSG_UPDATE, nowBeingRestored, 0)); + } + + public void restoreFinished(int error) { + mHandler.sendMessage( + mHandler.obtainMessage(MSG_RESTORE_FINISHED, error, 0)); + } + } +} diff --git a/core/java/android/app/backup/RestoreSet.aidl b/core/java/android/app/backup/RestoreSet.aidl new file mode 100644 index 000000000000..ab1b125991ad --- /dev/null +++ b/core/java/android/app/backup/RestoreSet.aidl @@ -0,0 +1,19 @@ +/* + * 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 android.app.backup; + +parcelable RestoreSet; \ No newline at end of file diff --git a/core/java/android/app/backup/RestoreSet.java b/core/java/android/app/backup/RestoreSet.java new file mode 100644 index 000000000000..0431977cdecd --- /dev/null +++ b/core/java/android/app/backup/RestoreSet.java @@ -0,0 +1,87 @@ +/* + * 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 android.app.backup; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Descriptive information about a set of backed-up app data available for restore. + * Used by IRestoreSession clients. + * + * @hide + */ +public class RestoreSet implements Parcelable { + /** + * Name of this restore set. May be user generated, may simply be the name + * of the handset model, e.g. "T-Mobile G1". + */ + public String name; + + /** + * Identifier of the device whose data this is. This will be as unique as + * is practically possible; for example, it might be an IMEI. + */ + public String device; + + /** + * Token that identifies this backup set unambiguously to the backup/restore + * transport. This is guaranteed to be valid for the duration of a restore + * session, but is meaningless once the session has ended. + */ + public long token; + + + public RestoreSet() { + // Leave everything zero / null + } + + public RestoreSet(String _name, String _dev, long _token) { + name = _name; + device = _dev; + token = _token; + } + + + // Parcelable implementation + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(name); + out.writeString(device); + out.writeLong(token); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public RestoreSet createFromParcel(Parcel in) { + return new RestoreSet(in); + } + + public RestoreSet[] newArray(int size) { + return new RestoreSet[size]; + } + }; + + private RestoreSet(Parcel in) { + name = in.readString(); + device = in.readString(); + token = in.readLong(); + } +} diff --git a/core/java/android/app/backup/SharedPreferencesBackupHelper.java b/core/java/android/app/backup/SharedPreferencesBackupHelper.java new file mode 100644 index 000000000000..d35b10c714f4 --- /dev/null +++ b/core/java/android/app/backup/SharedPreferencesBackupHelper.java @@ -0,0 +1,91 @@ +/* + * 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 android.app.backup; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; + +/** + * A helper class which can be used in conjunction with + * {@link android.app.backup.BackupHelperAgent} to manage the backup of + * {@link android.content.SharedPreferences}. Whenever backup is performed it + * will back up all named shared preferences which have changed since the last + * backup. + *

+ * STOPSHIP: document! + */ +public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper { + private static final String TAG = "SharedPreferencesBackupHelper"; + private static final boolean DEBUG = false; + + private Context mContext; + private String[] mPrefGroups; + + /** + * Construct a helper for backing up and restoring the + * {@link android.content.SharedPreferences} under the given names. + * + * @param context + * @param prefGroups + */ + public SharedPreferencesBackupHelper(Context context, String... prefGroups) { + super(context); + + mContext = context; + mPrefGroups = prefGroups; + } + + /** + * Backs up the configured SharedPreferences groups + */ + public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) { + Context context = mContext; + + // make filenames for the prefGroups + String[] prefGroups = mPrefGroups; + final int N = prefGroups.length; + String[] files = new String[N]; + for (int i=0; iBackup Dev Guide topic.

+ + diff --git a/core/java/android/backup/AbsoluteFileBackupHelper.java b/core/java/android/backup/AbsoluteFileBackupHelper.java deleted file mode 100644 index 5a8034bfd393..000000000000 --- a/core/java/android/backup/AbsoluteFileBackupHelper.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 android.backup; - -import android.content.Context; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import java.io.File; - -/** - * Like FileBackupHelper, but takes absolute paths for the files instead of - * subpaths of getFilesDir() - * - * STOPSHIP: document! - */ -public class AbsoluteFileBackupHelper extends FileBackupHelperBase implements BackupHelper { - private static final String TAG = "AbsoluteFileBackupHelper"; - private static final boolean DEBUG = false; - - Context mContext; - String[] mFiles; - - /** - * Construct a helper for backing up / restoring the files at the given absolute locations - * within the file system. - * - * @param context - * @param files - */ - public AbsoluteFileBackupHelper(Context context, String... files) { - super(context); - - mContext = context; - mFiles = files; - } - - /** - * Based on oldState, determine which of the files from the application's data directory - * need to be backed up, write them to the data stream, and fill in newState with the - * state as it exists now. - */ - public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) { - // use the file paths as the keys, too - performBackup_checked(oldState, data, newState, mFiles, mFiles); - } - - /** - * Restore one absolute file entity from the restore stream - */ - public void restoreEntity(BackupDataInputStream data) { - if (DEBUG) Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); - String key = data.getKey(); - if (isKeyInList(key, mFiles)) { - File f = new File(key); - writeFile(f, data); - } - } -} - diff --git a/core/java/android/backup/BackupDataInput.java b/core/java/android/backup/BackupDataInput.java deleted file mode 100644 index a08ee75861f0..000000000000 --- a/core/java/android/backup/BackupDataInput.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 android.backup; - -import java.io.FileDescriptor; -import java.io.IOException; - -/** - * STOPSHIP: document! - */ -public class BackupDataInput { - int mBackupReader; - - private EntityHeader mHeader = new EntityHeader(); - private boolean mHeaderReady; - - private static class EntityHeader { - String key; - int dataSize; - } - - /** @hide */ - public BackupDataInput(FileDescriptor fd) { - if (fd == null) throw new NullPointerException(); - mBackupReader = ctor(fd); - if (mBackupReader == 0) { - throw new RuntimeException("Native initialization failed with fd=" + fd); - } - } - - /** @hide */ - protected void finalize() throws Throwable { - try { - dtor(mBackupReader); - } finally { - super.finalize(); - } - } - - /** - * Consumes the next header from the restore stream. - * - * @return true when there is an entity ready for consumption from the restore stream, - * false if the restore stream has been fully consumed. - * @throws IOException if an error occurred while reading the restore stream - */ - public boolean readNextHeader() throws IOException { - int result = readNextHeader_native(mBackupReader, mHeader); - if (result == 0) { - // read successfully - mHeaderReady = true; - return true; - } else if (result > 0) { - // done - mHeaderReady = false; - return false; - } else { - // error - mHeaderReady = false; - throw new IOException("result=0x" + Integer.toHexString(result)); - } - } - - /** - * Report the key associated with the current record in the restore stream - * @return the current record's key string - * @throws IllegalStateException if the next record header has not yet been read - */ - public String getKey() { - if (mHeaderReady) { - return mHeader.key; - } else { - throw new IllegalStateException("mHeaderReady=false"); - } - } - - /** - * Report the size in bytes of the data associated with the current record in the - * restore stream. - * - * @return The size of the record's raw data, in bytes - * @throws IllegalStateException if the next record header has not yet been read - */ - public int getDataSize() { - if (mHeaderReady) { - return mHeader.dataSize; - } else { - throw new IllegalStateException("mHeaderReady=false"); - } - } - - /** - * Read a record's raw data from the restore stream. The record's header must first - * have been processed by the {@link #readNextHeader()} method. Multiple calls to - * this method may be made in order to process the data in chunks; not all of it - * must be read in a single call. - * - * @param data An allocated byte array of at least 'size' bytes - * @param offset Offset within the 'data' array at which the data will be placed - * when read from the stream. - * @param size The number of bytes to read in this pass. - * @return The number of bytes of data read - * @throws IOException if an error occurred when trying to read the restore data stream - */ - public int readEntityData(byte[] data, int offset, int size) throws IOException { - if (mHeaderReady) { - int result = readEntityData_native(mBackupReader, data, offset, size); - if (result >= 0) { - return result; - } else { - throw new IOException("result=0x" + Integer.toHexString(result)); - } - } else { - throw new IllegalStateException("mHeaderReady=false"); - } - } - - /** - * Consume the current record's data without actually reading it into a buffer - * for further processing. This allows a {@link android.app.BackupAgent} to - * efficiently discard obsolete or otherwise uninteresting records during the - * restore operation. - * - * @throws IOException if an error occurred when trying to read the restore data stream - */ - public void skipEntityData() throws IOException { - if (mHeaderReady) { - skipEntityData_native(mBackupReader); - } else { - throw new IllegalStateException("mHeaderReady=false"); - } - } - - private native static int ctor(FileDescriptor fd); - private native static void dtor(int mBackupReader); - - private native int readNextHeader_native(int mBackupReader, EntityHeader entity); - private native int readEntityData_native(int mBackupReader, byte[] data, int offset, int size); - private native int skipEntityData_native(int mBackupReader); -} diff --git a/core/java/android/backup/BackupDataInputStream.java b/core/java/android/backup/BackupDataInputStream.java deleted file mode 100644 index 503b3c1ba646..000000000000 --- a/core/java/android/backup/BackupDataInputStream.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 android.backup; - -import java.io.InputStream; -import java.io.IOException; - -/** - * STOPSHIP: document */ -public class BackupDataInputStream extends InputStream { - - String key; - int dataSize; - - BackupDataInput mData; - byte[] mOneByte; - - /** @hide */ - BackupDataInputStream(BackupDataInput data) { - mData = data; - } - - public int read() throws IOException { - byte[] one = mOneByte; - if (mOneByte == null) { - one = mOneByte = new byte[1]; - } - mData.readEntityData(one, 0, 1); - return one[0]; - } - - public int read(byte[] b, int offset, int size) throws IOException { - return mData.readEntityData(b, offset, size); - } - - public int read(byte[] b) throws IOException { - return mData.readEntityData(b, 0, b.length); - } - - public String getKey() { - return this.key; - } - - public int size() { - return this.dataSize; - } -} - - diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java deleted file mode 100644 index 34879d8b960c..000000000000 --- a/core/java/android/backup/BackupDataOutput.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 android.backup; - -import java.io.FileDescriptor; -import java.io.IOException; - -/** - * STOPSHIP: document - */ -public class BackupDataOutput { - int mBackupWriter; - - public static final int OP_UPDATE = 1; - public static final int OP_DELETE = 2; - - /** @hide */ - public BackupDataOutput(FileDescriptor fd) { - if (fd == null) throw new NullPointerException(); - mBackupWriter = ctor(fd); - if (mBackupWriter == 0) { - throw new RuntimeException("Native initialization failed with fd=" + fd); - } - } - - /** - * Mark the beginning of one record in the backup data stream. - * - * @param key - * @param dataSize The size in bytes of this record's data. Passing a dataSize - * of -1 indicates that the record under this key should be deleted. - * @return The number of bytes written to the backup stream - * @throws IOException if the write failed - */ - public int writeEntityHeader(String key, int dataSize) throws IOException { - int result = writeEntityHeader_native(mBackupWriter, key, dataSize); - if (result >= 0) { - return result; - } else { - throw new IOException("result=0x" + Integer.toHexString(result)); - } - } - - /** - * Write a chunk of data under the current entity to the backup transport. - * @param data A raw data buffer to send - * @param size The number of bytes to be sent in this chunk - * @return the number of bytes written - * @throws IOException if the write failed - */ - public int writeEntityData(byte[] data, int size) throws IOException { - int result = writeEntityData_native(mBackupWriter, data, size); - if (result >= 0) { - return result; - } else { - throw new IOException("result=0x" + Integer.toHexString(result)); - } - } - - public void setKeyPrefix(String keyPrefix) { - setKeyPrefix_native(mBackupWriter, keyPrefix); - } - - /** @hide */ - protected void finalize() throws Throwable { - try { - dtor(mBackupWriter); - } finally { - super.finalize(); - } - } - - private native static int ctor(FileDescriptor fd); - private native static void dtor(int mBackupWriter); - - private native static int writeEntityHeader_native(int mBackupWriter, String key, int dataSize); - private native static int writeEntityData_native(int mBackupWriter, byte[] data, int size); - private native static void setKeyPrefix_native(int mBackupWriter, String keyPrefix); -} - diff --git a/core/java/android/backup/BackupHelper.java b/core/java/android/backup/BackupHelper.java deleted file mode 100644 index 7eedd01cd2ed..000000000000 --- a/core/java/android/backup/BackupHelper.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 android.backup; - -import android.os.ParcelFileDescriptor; - -/** - * A convenient interface to be used with the - * {@link android.backup.BackupHelperAgent} to implement backup and restore of - * arbitrary data types. - *

- * STOPSHOP: document! - */ -public interface BackupHelper { - /** - * Based on oldState, determine which of the files from the - * application's data directory need to be backed up, write them to - * data, and fill in newState with the state as it - * exists now. - */ - public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState); - - /** - * Called by BackupHelperAgent to restore one entity from the restore dataset. - *

- * Do not close the data stream. Do not read more than - * data.size() bytes from data. - */ - public void restoreEntity(BackupDataInputStream data); - - /** - * Called by BackupHelperAgent to write the new backup state file corresponding to - * the current state of the app's data at the time the backup operation was - * performed. - */ - public void writeNewStateDescription(ParcelFileDescriptor fd); -} - diff --git a/core/java/android/backup/BackupHelperAgent.java b/core/java/android/backup/BackupHelperAgent.java deleted file mode 100644 index 7fb44f48c92d..000000000000 --- a/core/java/android/backup/BackupHelperAgent.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007 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.backup; - -import android.app.BackupAgent; -import android.os.ParcelFileDescriptor; - -import java.io.IOException; - -/** - * A convenient BackupAgent wrapper class that automatically manages - * heterogeneous data sets within the backup data, each identified by a unique - * key prefix. An application will typically extend this class in their own - * backup agent. Then, within the agent's onBackup() and onRestore() methods, it - * will call {@link #addHelper(String, BackupHelper)} one or more times to - * specify the data sets, then invoke super.onBackup() or super.onRestore() to - * have the BackupHelperAgent implementation process the data. - *

- * STOPSHIP: document! - */ -public class BackupHelperAgent extends BackupAgent { - static final String TAG = "BackupHelperAgent"; - - BackupHelperDispatcher mDispatcher = new BackupHelperDispatcher(); - - /** - * Run the backup process on each of the configured handlers. - */ - @Override - public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { - mDispatcher.performBackup(oldState, data, newState); - } - - /** - * Run the restore process on each of the configured handlers. - */ - @Override - public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) - throws IOException { - mDispatcher.performRestore(data, appVersionCode, newState); - } - - /** @hide */ - public BackupHelperDispatcher getDispatcher() { - return mDispatcher; - } - - /** - * Add a helper for a given data subset to the agent's configuration. Each helper - * must have a prefix string that is unique within this backup agent's set of - * helpers. - * - * @param keyPrefix A string used to disambiguate the various helpers within this agent - * @param helper A backup/restore helper object to be invoked during backup and restore - * operations. - */ - public void addHelper(String keyPrefix, BackupHelper helper) { - mDispatcher.addHelper(keyPrefix, helper); - } -} - - diff --git a/core/java/android/backup/BackupHelperDispatcher.java b/core/java/android/backup/BackupHelperDispatcher.java deleted file mode 100644 index 68076db5d0dc..000000000000 --- a/core/java/android/backup/BackupHelperDispatcher.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 android.backup; - -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.util.Map; -import java.util.TreeMap; - -/** @hide */ -public class BackupHelperDispatcher { - private static final String TAG = "BackupHelperDispatcher"; - - private static class Header { - int chunkSize; // not including the header - String keyPrefix; - } - - TreeMap mHelpers = new TreeMap(); - - public BackupHelperDispatcher() { - } - - public void addHelper(String keyPrefix, BackupHelper helper) { - mHelpers.put(keyPrefix, helper); - } - - public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { - // First, do the helpers that we've already done, since they're already in the state - // file. - int err; - Header header = new Header(); - TreeMap helpers = (TreeMap)mHelpers.clone(); - FileDescriptor oldStateFD = null; - FileDescriptor newStateFD = newState.getFileDescriptor(); - - if (oldState != null) { - oldStateFD = oldState.getFileDescriptor(); - while ((err = readHeader_native(header, oldStateFD)) >= 0) { - if (err == 0) { - BackupHelper helper = helpers.get(header.keyPrefix); - Log.d(TAG, "handling existing helper '" + header.keyPrefix + "' " + helper); - if (helper != null) { - doOneBackup(oldState, data, newState, header, helper); - helpers.remove(header.keyPrefix); - } else { - skipChunk_native(oldStateFD, header.chunkSize); - } - } - } - } - - // Then go through and do the rest that we haven't done. - for (Map.Entry entry: helpers.entrySet()) { - header.keyPrefix = entry.getKey(); - Log.d(TAG, "handling new helper '" + header.keyPrefix + "'"); - BackupHelper helper = entry.getValue(); - doOneBackup(oldState, data, newState, header, helper); - } - } - - private void doOneBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState, Header header, BackupHelper helper) - throws IOException { - int err; - FileDescriptor newStateFD = newState.getFileDescriptor(); - - // allocate space for the header in the file - int pos = allocateHeader_native(header, newStateFD); - if (pos < 0) { - throw new IOException("allocateHeader_native failed (error " + pos + ")"); - } - - data.setKeyPrefix(header.keyPrefix); - - // do the backup - helper.performBackup(oldState, data, newState); - - // fill in the header (seeking back to pos). The file pointer will be returned to - // where it was at the end of performBackup. Header.chunkSize will not be filled in. - err = writeHeader_native(header, newStateFD, pos); - if (err != 0) { - throw new IOException("writeHeader_native failed (error " + err + ")"); - } - } - - public void performRestore(BackupDataInput input, int appVersionCode, - ParcelFileDescriptor newState) - throws IOException { - boolean alreadyComplained = false; - - BackupDataInputStream stream = new BackupDataInputStream(input); - while (input.readNextHeader()) { - - String rawKey = input.getKey(); - int pos = rawKey.indexOf(':'); - if (pos > 0) { - String prefix = rawKey.substring(0, pos); - BackupHelper helper = mHelpers.get(prefix); - if (helper != null) { - stream.dataSize = input.getDataSize(); - stream.key = rawKey.substring(pos+1); - helper.restoreEntity(stream); - } else { - if (!alreadyComplained) { - Log.w(TAG, "Couldn't find helper for: '" + rawKey + "'"); - alreadyComplained = true; - } - } - } else { - if (!alreadyComplained) { - Log.w(TAG, "Entity with no prefix: '" + rawKey + "'"); - alreadyComplained = true; - } - } - input.skipEntityData(); // In case they didn't consume the data. - } - - // Write out the state files -- mHelpers is a TreeMap, so the order is well defined. - for (BackupHelper helper: mHelpers.values()) { - helper.writeNewStateDescription(newState); - } - } - - private static native int readHeader_native(Header h, FileDescriptor fd); - private static native int skipChunk_native(FileDescriptor fd, int bytesToSkip); - - private static native int allocateHeader_native(Header h, FileDescriptor fd); - private static native int writeHeader_native(Header h, FileDescriptor fd, int pos); -} - diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java deleted file mode 100644 index 2dff975fc0fc..000000000000 --- a/core/java/android/backup/BackupManager.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 android.backup; - -import android.backup.RestoreSession; -import android.content.Context; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Log; - -/** - * BackupManager is the interface to the system's backup service. Applications - * simply instantiate one, and then use that instance to communicate with the - * backup infrastructure. - *

- * When an application has made changes to data which should be backed up, a - * call to {@link #dataChanged()} will notify the backup service. The system - * will then schedule a backup operation to occur in the near future. Repeated - * calls to {@link #dataChanged()} have no further effect until the backup - * operation actually occurs. - *

- * The backup operation itself begins with the system launching the - * {@link android.app.BackupAgent} subclass declared in your manifest. See the - * documentation for {@link android.app.BackupAgent} for a detailed description - * of how the backup then proceeds. - *

- * A simple implementation of a BackupAgent useful for backing up Preferences - * and files is available by using {@link android.backup.BackupHelperAgent}. - *

- * STOPSHIP: more documentation! - *

- * XML attributes - *

- * See {@link android.R.styleable#AndroidManifestApplication - * AndroidManifest.xml's application attributes} - * - * @attr ref android.R.styleable#AndroidManifestApplication_allowBackup - * @attr ref android.R.styleable#AndroidManifestApplication_backupAgent - * @attr ref - * android.R.styleable#AndroidManifestApplication_restoreNeedsApplication - * @attr ref android.R.styleable#AndroidManifestApplication_killAfterRestore - */ -public class BackupManager { - private static final String TAG = "BackupManager"; - - private Context mContext; - private static IBackupManager sService; - - private static void checkServiceBinder() { - if (sService == null) { - sService = IBackupManager.Stub.asInterface( - ServiceManager.getService(Context.BACKUP_SERVICE)); - } - } - - /** - * Constructs a BackupManager object through which the application can - * communicate with the Android backup system. - * - * @param context The {@link android.content.Context} that was provided when - * one of your application's {@link android.app.Activity Activities} - * was created. - */ - public BackupManager(Context context) { - mContext = context; - } - - /** - * Notifies the Android backup system that your application wishes to back up - * new changes to its data. A backup operation using your application's - * {@link android.app.BackupAgent} subclass will be scheduled when you call this method. - */ - public void dataChanged() { - checkServiceBinder(); - if (sService != null) { - try { - sService.dataChanged(mContext.getPackageName()); - } catch (RemoteException e) { - Log.d(TAG, "dataChanged() couldn't connect"); - } - } - } - - /** - * Convenience method for callers who need to indicate that some other package - * needs a backup pass. This can be relevant in the case of groups of packages - * that share a uid, for example. - * - * This method requires that the application hold the "android.permission.BACKUP" - * permission if the package named in the argument is not the caller's own. - */ - public static void dataChanged(String packageName) { - checkServiceBinder(); - if (sService != null) { - try { - sService.dataChanged(packageName); - } catch (RemoteException e) { - Log.d(TAG, "dataChanged(pkg) couldn't connect"); - } - } - } - - /** - * Begin the process of restoring data from backup. See the - * {@link android.backup.RestoreSession} class for documentation on that process. - */ - public RestoreSession beginRestoreSession() { - RestoreSession session = null; - checkServiceBinder(); - if (sService != null) { - try { - String transport = sService.getCurrentTransport(); - IRestoreSession binder = sService.beginRestoreSession(transport); - session = new RestoreSession(mContext, binder); - } catch (RemoteException e) { - Log.w(TAG, "beginRestoreSession() couldn't connect"); - } - } - return session; - } -} diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java deleted file mode 100644 index cc859e24df61..000000000000 --- a/core/java/android/backup/FileBackupHelper.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 android.backup; - -import android.content.Context; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import java.io.File; - -/** - * A helper class which can be used in conjunction with - * {@link android.backup.BackupHelperAgent} to manage the backup of a set of - * files. Whenever backup is performed, all files changed since the last backup - * will be saved in their entirety. During the first time the backup happens, - * all the files in the list will be backed up. Note that this should only be - * used with small configuration files and not with large binary files. - *

- * Any files not present in the list of files during the restore procedure will - * be ignored. If files present in a previous version of an application are - * removed in subsequent versions, it is the responsibility of the developer to - * design a mechanism to remove those files. Otherwise files no longer needed - * will linger and consume space on the device. - *

- * STOPSHIP: document! [manages backup of a set of files; restore is totally - * opaque] - */ -public class FileBackupHelper extends FileBackupHelperBase implements BackupHelper { - private static final String TAG = "FileBackupHelper"; - private static final boolean DEBUG = false; - - Context mContext; - File mFilesDir; - String[] mFiles; - - /** - * Construct a helper to manage backup/restore of entire files within the - * application's data directory hierarchy. - * - * @param context The backup agent's Context object - * @param files A list of the files to be backed up or restored. - */ - public FileBackupHelper(Context context, String... files) { - super(context); - - mContext = context; - mFilesDir = context.getFilesDir(); - mFiles = files; - } - - /** - * Based on oldState, determine which of the files from the - * application's data directory need to be backed up, write them to the data - * stream, and fill in newState with the state as it exists - * now. When oldState is null, all the files will - * be backed up. - *

- * This should be called from {@link android.backup.BackupHelperAgent} - * directly. See - * {@link android.app.BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} - * for a description of parameter meanings. - */ - public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) { - // file names - String[] files = mFiles; - File base = mContext.getFilesDir(); - final int N = files.length; - String[] fullPaths = new String[N]; - for (int i=0; iCallers must hold the android.permission.BACKUP permission to use this method. - */ - void setBackupEnabled(boolean isEnabled); - - /** - * Enable/disable automatic restore of application data at install time. When - * enabled, installation of any package will involve the Backup Manager. If data - * exists for the newly-installed package, either from the device's current [enabled] - * backup dataset or from the restore set used in the last wholesale restore operation, - * that data will be supplied to the new package's restore agent before the package - * is made generally available for launch. - * - *

Callers must hold the android.permission.BACKUP permission to use this method. - * - * @param doAutoRestore When true, enables the automatic app-data restore facility. When - * false, this facility will be disabled. - */ - void setAutoRestore(boolean doAutoRestore); - - /** - * Indicate that any necessary one-time provisioning has occurred. - * - *

Callers must hold the android.permission.BACKUP permission to use this method. - */ - void setBackupProvisioned(boolean isProvisioned); - - /** - * Report whether the backup mechanism is currently enabled. - * - *

Callers must hold the android.permission.BACKUP permission to use this method. - */ - boolean isBackupEnabled(); - - /** - * Schedule an immediate backup attempt for all pending updates. This is - * primarily intended for transports to use when they detect a suitable - * opportunity for doing a backup pass. If there are no pending updates to - * be sent, no action will be taken. Even if some updates are pending, the - * transport will still be asked to confirm via the usual requestBackupTime() - * method. - * - *

Callers must hold the android.permission.BACKUP permission to use this method. - */ - void backupNow(); - - /** - * Identify the currently selected transport. Callers must hold the - * android.permission.BACKUP permission to use this method. - */ - String getCurrentTransport(); - - /** - * Request a list of all available backup transports' names. Callers must - * hold the android.permission.BACKUP permission to use this method. - */ - String[] listAllTransports(); - - /** - * Specify the current backup transport. Callers must hold the - * android.permission.BACKUP permission to use this method. - * - * @param transport The name of the transport to select. This should be one - * of {@link BackupManager.TRANSPORT_GOOGLE} or {@link BackupManager.TRANSPORT_ADB}. - * @return The name of the previously selected transport. If the given transport - * name is not one of the currently available transports, no change is made to - * the current transport setting and the method returns null. - */ - String selectBackupTransport(String transport); - - /** - * Begin a restore session with the given transport (which may differ from the - * currently-active backup transport). - * - * @param transport The name of the transport to use for the restore operation. - * @return An interface to the restore session, or null on error. - */ - IRestoreSession beginRestoreSession(String transportID); - - /** - * Notify the backup manager that a BackupAgent has completed the operation - * corresponding to the given token. - * - * @param token The transaction token passed to a BackupAgent's doBackup() or - * doRestore() method. - * {@hide} - */ - void opComplete(int token); -} diff --git a/core/java/android/backup/IRestoreObserver.aidl b/core/java/android/backup/IRestoreObserver.aidl deleted file mode 100644 index 59e59fc1f70a..000000000000 --- a/core/java/android/backup/IRestoreObserver.aidl +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 android.backup; - -/** - * Callback class for receiving progress reports during a restore operation. - * - * @hide - */ -interface IRestoreObserver { - /** - * The restore operation has begun. - * - * @param numPackages The total number of packages being processed in - * this restore operation. - */ - void restoreStarting(int numPackages); - - /** - * An indication of which package is being restored currently, out of the - * total number provided in the restoreStarting() callback. This method - * is not guaranteed to be called. - * - * @param nowBeingRestored The index, between 1 and the numPackages parameter - * to the restoreStarting() callback, of the package now being restored. - */ - void onUpdate(int nowBeingRestored); - - /** - * The restore operation has completed. - * - * @param error Zero on success; a nonzero error code if the restore operation - * as a whole failed. - */ - void restoreFinished(int error); -} diff --git a/core/java/android/backup/IRestoreSession.aidl b/core/java/android/backup/IRestoreSession.aidl deleted file mode 100644 index bead395a752c..000000000000 --- a/core/java/android/backup/IRestoreSession.aidl +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 android.backup; - -import android.backup.RestoreSet; -import android.backup.IRestoreObserver; - -/** - * Binder interface used by clients who wish to manage a restore operation. Every - * method in this interface requires the android.permission.BACKUP permission. - * - * {@hide} - */ -interface IRestoreSession { - /** - * Ask the current transport what the available restore sets are. - * - * @return A bundle containing two elements: an int array under the key - * "tokens" whose entries are a transport-private identifier for each backup set; - * and a String array under the key "names" whose entries are the user-meaningful - * text corresponding to the backup sets at each index in the tokens array. - */ - RestoreSet[] getAvailableRestoreSets(); - - /** - * Restore the given set onto the device, replacing the current data of any app - * contained in the restore set with the data previously backed up. - * - *

Callers must hold the android.permission.BACKUP permission to use this method. - * - * @return Zero on success; nonzero on error. The observer will only receive - * progress callbacks if this method returned zero. - * @param token The token from {@link getAvailableRestoreSets()} corresponding to - * the restore set that should be used. - * @param observer If non-null, this binder points to an object that will receive - * progress callbacks during the restore operation. - */ - int restoreAll(long token, IRestoreObserver observer); - - /** - * Restore a single application from backup. The data will be restored from the - * current backup dataset if the given package has stored data there, or from - * the dataset used during the last full device setup operation if the current - * backup dataset has no matching data. If no backup data exists for this package - * in either source, a nonzero value will be returned. - * - * @return Zero on success; nonzero on error. The observer will only receive - * progress callbacks if this method returned zero. - * @param packageName The name of the package whose data to restore. If this is - * not the name of the caller's own package, then the android.permission.BACKUP - * permission must be held. - * @param observer If non-null, this binder points to an object that will receive - * progress callbacks during the restore operation. - */ - int restorePackage(in String packageName, IRestoreObserver observer); - - /** - * End this restore session. After this method is called, the IRestoreSession binder - * is no longer valid. - * - *

Note: The caller must invoke this method to end the restore session, - * even if {@link getAvailableRestoreSets} or {@link performRestore} failed. - */ - void endRestoreSession(); -} diff --git a/core/java/android/backup/RestoreObserver.java b/core/java/android/backup/RestoreObserver.java deleted file mode 100644 index e41827503f44..000000000000 --- a/core/java/android/backup/RestoreObserver.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2010 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.backup; - -/** - * Callback class for receiving progress reports during a restore operation. These - * methods will all be called on your application's main thread. - */ -public abstract class RestoreObserver { - /** - * The restore operation has begun. - * - * @param numPackages The total number of packages being processed in - * this restore operation. - */ - void restoreStarting(int numPackages) { - } - - /** - * An indication of which package is being restored currently, out of the - * total number provided in the restoreStarting() callback. This method - * is not guaranteed to be called. - * - * @param nowBeingRestored The index, between 1 and the numPackages parameter - * to the restoreStarting() callback, of the package now being restored. - */ - void onUpdate(int nowBeingRestored) { - } - - /** - * The restore operation has completed. - * - * @param error Zero on success; a nonzero error code if the restore operation - * as a whole failed. - */ - void restoreFinished(int error) { - } -} diff --git a/core/java/android/backup/RestoreSession.java b/core/java/android/backup/RestoreSession.java deleted file mode 100644 index bc410c49d967..000000000000 --- a/core/java/android/backup/RestoreSession.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2010 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.backup; - -import android.backup.IRestoreSession; -import android.backup.RestoreObserver; -import android.backup.RestoreSet; -import android.content.Context; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.util.Log; - -/** - * Interface for applications to use when managing a restore session. - */ -public class RestoreSession { - static final String TAG = "RestoreSession"; - - final Context mContext; - IRestoreSession mBinder; - RestoreObserverWrapper mObserver = null; - - /** - * Ask the current transport what the available restore sets are. - * - * @return A bundle containing two elements: an int array under the key - * "tokens" whose entries are a transport-private identifier for each backup set; - * and a String array under the key "names" whose entries are the user-meaningful - * text corresponding to the backup sets at each index in the tokens array. - * On error, returns null. - * - * {@hide} - */ - public RestoreSet[] getAvailableRestoreSets() { - try { - return mBinder.getAvailableRestoreSets(); - } catch (RemoteException e) { - Log.d(TAG, "Can't contact server to get available sets"); - return null; - } - } - - /** - * Restore the given set onto the device, replacing the current data of any app - * contained in the restore set with the data previously backed up. - * - *

Callers must hold the android.permission.BACKUP permission to use this method. - * - * @return Zero on success; nonzero on error. The observer will only receive - * progress callbacks if this method returned zero. - * @param token The token from {@link #getAvailableRestoreSets()} corresponding to - * the restore set that should be used. - * @param observer If non-null, this binder points to an object that will receive - * progress callbacks during the restore operation. - * - * {@hide} - */ - public int restoreAll(long token, RestoreObserver observer) { - int err = -1; - if (mObserver != null) { - Log.d(TAG, "restoreAll() called during active restore"); - return -1; - } - mObserver = new RestoreObserverWrapper(mContext, observer); - try { - err = mBinder.restoreAll(token, mObserver); - } catch (RemoteException e) { - Log.d(TAG, "Can't contact server to restore"); - } - return err; - } - - /** - * Restore a single application from backup. The data will be restored from the - * current backup dataset if the given package has stored data there, or from - * the dataset used during the last full device setup operation if the current - * backup dataset has no matching data. If no backup data exists for this package - * in either source, a nonzero value will be returned. - * - * @return Zero on success; nonzero on error. The observer will only receive - * progress callbacks if this method returned zero. - * @param packageName The name of the package whose data to restore. If this is - * not the name of the caller's own package, then the android.permission.BACKUP - * permission must be held. - * @param observer If non-null, this binder points to an object that will receive - * progress callbacks during the restore operation. - */ - public int restorePackage(String packageName, RestoreObserver observer) { - int err = -1; - if (mObserver != null) { - Log.d(TAG, "restorePackage() called during active restore"); - return -1; - } - mObserver = new RestoreObserverWrapper(mContext, observer); - try { - err = mBinder.restorePackage(packageName, mObserver); - } catch (RemoteException e) { - Log.d(TAG, "Can't contact server to restore package"); - } - return err; - } - - /** - * End this restore session. After this method is called, the RestoreSession - * object is no longer valid. - * - *

Note: The caller must invoke this method to end the restore session, - * even if {@link #restorePackage(String, RestoreObserver)} failed. - */ - public void endRestoreSession() { - try { - mBinder.endRestoreSession(); - } catch (RemoteException e) { - Log.d(TAG, "Can't contact server to get available sets"); - } finally { - mBinder = null; - } - } - - /* - * Nonpublic implementation here - */ - - RestoreSession(Context context, IRestoreSession binder) { - mContext = context; - mBinder = binder; - } - - /* - * We wrap incoming binder calls with a private class implementation that - * redirects them into main-thread actions. This serializes the restore - * progress callbacks nicely within the usual main-thread lifecycle pattern. - */ - private class RestoreObserverWrapper extends IRestoreObserver.Stub { - final Handler mHandler; - final RestoreObserver mAppObserver; - - static final int MSG_RESTORE_STARTING = 1; - static final int MSG_UPDATE = 2; - static final int MSG_RESTORE_FINISHED = 3; - - RestoreObserverWrapper(Context context, RestoreObserver appObserver) { - mHandler = new Handler(context.getMainLooper()) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_RESTORE_STARTING: - mAppObserver.restoreStarting(msg.arg1); - break; - case MSG_UPDATE: - mAppObserver.onUpdate(msg.arg1); - break; - case MSG_RESTORE_FINISHED: - mAppObserver.restoreFinished(msg.arg1); - break; - } - } - }; - mAppObserver = appObserver; - } - - // Binder calls into this object just enqueue on the main-thread handler - public void restoreStarting(int numPackages) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_RESTORE_STARTING, numPackages, 0)); - } - - public void onUpdate(int nowBeingRestored) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_UPDATE, nowBeingRestored, 0)); - } - - public void restoreFinished(int error) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_RESTORE_FINISHED, error, 0)); - } - } -} diff --git a/core/java/android/backup/RestoreSet.aidl b/core/java/android/backup/RestoreSet.aidl deleted file mode 100644 index 42e77bfe5990..000000000000 --- a/core/java/android/backup/RestoreSet.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 android.backup; - -parcelable RestoreSet; \ No newline at end of file diff --git a/core/java/android/backup/RestoreSet.java b/core/java/android/backup/RestoreSet.java deleted file mode 100644 index eeca148667f3..000000000000 --- a/core/java/android/backup/RestoreSet.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 android.backup; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Descriptive information about a set of backed-up app data available for restore. - * Used by IRestoreSession clients. - * - * @hide - */ -public class RestoreSet implements Parcelable { - /** - * Name of this restore set. May be user generated, may simply be the name - * of the handset model, e.g. "T-Mobile G1". - */ - public String name; - - /** - * Identifier of the device whose data this is. This will be as unique as - * is practically possible; for example, it might be an IMEI. - */ - public String device; - - /** - * Token that identifies this backup set unambiguously to the backup/restore - * transport. This is guaranteed to be valid for the duration of a restore - * session, but is meaningless once the session has ended. - */ - public long token; - - - public RestoreSet() { - // Leave everything zero / null - } - - public RestoreSet(String _name, String _dev, long _token) { - name = _name; - device = _dev; - token = _token; - } - - - // Parcelable implementation - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(name); - out.writeString(device); - out.writeLong(token); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public RestoreSet createFromParcel(Parcel in) { - return new RestoreSet(in); - } - - public RestoreSet[] newArray(int size) { - return new RestoreSet[size]; - } - }; - - private RestoreSet(Parcel in) { - name = in.readString(); - device = in.readString(); - token = in.readLong(); - } -} diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java deleted file mode 100644 index 7ba80db3c1ca..000000000000 --- a/core/java/android/backup/SharedPreferencesBackupHelper.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 android.backup; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import java.io.File; - -/** - * A helper class which can be used in conjunction with - * {@link android.backup.BackupHelperAgent} to manage the backup of - * {@link android.content.SharedPreferences}. Whenever backup is performed it - * will back up all named shared preferences which have changed since the last - * backup. - *

- * STOPSHIP: document! - */ -public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper { - private static final String TAG = "SharedPreferencesBackupHelper"; - private static final boolean DEBUG = false; - - private Context mContext; - private String[] mPrefGroups; - - /** - * Construct a helper for backing up and restoring the - * {@link android.content.SharedPreferences} under the given names. - * - * @param context - * @param prefGroups - */ - public SharedPreferencesBackupHelper(Context context, String... prefGroups) { - super(context); - - mContext = context; - mPrefGroups = prefGroups; - } - - /** - * Backs up the configured SharedPreferences groups - */ - public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) { - Context context = mContext; - - // make filenames for the prefGroups - String[] prefGroups = mPrefGroups; - final int N = prefGroups.length; - String[] files = new String[N]; - for (int i=0; iBackup Dev Guide topic.

- - diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 8d136f1f312c..2b0e7e7456d8 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1489,7 +1489,7 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve an - * {@link android.backup.IBackupManager IBackupManager} for communicating + * {@link android.app.backup.IBackupManager IBackupManager} for communicating * with the backup mechanism. * @hide * -- cgit v1.2.3