API CHANGE: expose backup/restore to the SDK
The core backup/restore classes [BackupManager, BackupAgent, RestoreSession, and
RestoreObserver] are now published for 3rd party developers, as well as the suite
of helper classes that exist so far to aid authorship of backup/restore agents.
In conjunction with the API change, the restore-time automatic data wipe has now
been removed: applications are responsible for managing the logic of wipe vs
merge themselves. If the app's agent onRestore() callback throws, the data
is presumed to be incoherent and a wipe is issued via the Activity Manager;
otherwise, no automatic action is ever taken.
Change-Id: I0b3418b829d4689b58b88be3d9c4ace37a8583a9
diff --git a/api/current.xml b/api/current.xml
index 9c663fe..b5469e7 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19850,6 +19850,83 @@
>
</method>
</class>
+<class name="BackupAgent"
+ extends="android.content.ContextWrapper"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="BackupAgent"
+ type="android.app.BackupAgent"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onBackup"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="oldState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="data" type="android.backup.BackupDataOutput">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="onCreate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDestroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onRestore"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.backup.BackupDataInput">
+</parameter>
+<parameter name="appVersionCode" type="int">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
<class name="DatePickerDialog"
extends="android.app.AlertDialog"
abstract="false"
@@ -27399,6 +27476,615 @@
</field>
</class>
</package>
+<package name="android.backup"
+>
+<class name="AbsoluteFileBackupHelper"
+ extends="android.backup.FileBackupHelperBase"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.backup.BackupHelper">
+</implements>
+<constructor name="AbsoluteFileBackupHelper"
+ type="android.backup.AbsoluteFileBackupHelper"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="files" type="java.lang.String...">
+</parameter>
+</constructor>
+<method name="performBackup"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="oldState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="data" type="android.backup.BackupDataOutput">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+</method>
+<method name="restoreEntity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.backup.BackupDataInputStream">
+</parameter>
+</method>
+</class>
+<class name="BackupDataInput"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDataSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getKey"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="readEntityData"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="readNextHeader"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="skipEntityData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="BackupDataInputStream"
+ extends="java.io.InputStream"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getKey"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="read"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="size"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="BackupDataOutput"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="setKeyPrefix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyPrefix" type="java.lang.String">
+</parameter>
+</method>
+<method name="writeEntityData"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeEntityHeader"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="dataSize" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="OP_DELETE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OP_UPDATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="BackupHelper"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="performBackup"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="oldState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="data" type="android.backup.BackupDataOutput">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+</method>
+<method name="restoreEntity"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.backup.BackupDataInputStream">
+</parameter>
+</method>
+<method name="writeRestoreSnapshot"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="android.os.ParcelFileDescriptor">
+</parameter>
+</method>
+</interface>
+<class name="BackupHelperAgent"
+ extends="android.app.BackupAgent"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="BackupHelperAgent"
+ type="android.backup.BackupHelperAgent"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addHelper"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyPrefix" type="java.lang.String">
+</parameter>
+<parameter name="helper" type="android.backup.BackupHelper">
+</parameter>
+</method>
+<method name="onBackup"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="oldState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="data" type="android.backup.BackupDataOutput">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="onRestore"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.backup.BackupDataInput">
+</parameter>
+<parameter name="appVersionCode" type="int">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="BackupManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="BackupManager"
+ type="android.backup.BackupManager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<method name="beginRestoreSession"
+ return="android.backup.RestoreSession"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="dataChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="dataChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="FileBackupHelper"
+ extends="android.backup.FileBackupHelperBase"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.backup.BackupHelper">
+</implements>
+<constructor name="FileBackupHelper"
+ type="android.backup.FileBackupHelper"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="files" type="java.lang.String...">
+</parameter>
+</constructor>
+<method name="performBackup"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="oldState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="data" type="android.backup.BackupDataOutput">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+</method>
+<method name="restoreEntity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.backup.BackupDataInputStream">
+</parameter>
+</method>
+</class>
+<class name="FileBackupHelperBase"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility=""
+>
+<method name="writeRestoreSnapshot"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="android.os.ParcelFileDescriptor">
+</parameter>
+</method>
+</class>
+<class name="RestoreObserver"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RestoreObserver"
+ type="android.backup.RestoreObserver"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
+<class name="RestoreSession"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="endRestoreSession"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="restorePackage"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="observer" type="android.backup.RestoreObserver">
+</parameter>
+</method>
+</class>
+<class name="SharedPreferencesBackupHelper"
+ extends="android.backup.FileBackupHelperBase"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.backup.BackupHelper">
+</implements>
+<constructor name="SharedPreferencesBackupHelper"
+ type="android.backup.SharedPreferencesBackupHelper"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="prefGroups" type="java.lang.String...">
+</parameter>
+</constructor>
+<method name="performBackup"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="oldState" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="data" type="android.backup.BackupDataOutput">
+</parameter>
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
+</parameter>
+</method>
+<method name="restoreEntity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.backup.BackupDataInputStream">
+</parameter>
+</method>
+</class>
+</package>
<package name="android.bluetooth"
>
<class name="BluetoothAdapter"
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 35b6fed..a2bfc76 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -33,8 +33,8 @@
/**
* This is the central interface between an application and Android's
* settings backup mechanism.
- *
- * @hide pending API solidification
+ *
+ * <p>STOPSHIP write more documentation about the backup process here.
*/
public abstract class BackupAgent extends ContextWrapper {
private static final String TAG = "BackupAgent";
@@ -62,9 +62,9 @@
* 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 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 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.
@@ -77,10 +77,18 @@
* existing data with the contents of the backup. The backup data is
* provided in the file pointed to by the dataFd file descriptor. Once
* the restore is finished, the application should write a representation
- * of the final state to the newStateFd file descriptor,
+ * of the final state to the newStateFd file descriptor,
*
- * @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
- * of the application's data.
+ * <p>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
diff --git a/core/java/android/backup/AbsoluteFileBackupHelper.java b/core/java/android/backup/AbsoluteFileBackupHelper.java
index 1dbccc9..6bf848f 100644
--- a/core/java/android/backup/AbsoluteFileBackupHelper.java
+++ b/core/java/android/backup/AbsoluteFileBackupHelper.java
@@ -27,7 +27,7 @@
* Like FileBackupHelper, but takes absolute paths for the files instead of
* subpaths of getFilesDir()
*
- * @hide
+ * STOPSHIP: document!
*/
public class AbsoluteFileBackupHelper extends FileBackupHelperBase implements BackupHelper {
private static final String TAG = "AbsoluteFileBackupHelper";
@@ -36,6 +36,13 @@
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);
@@ -54,6 +61,9 @@
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();
diff --git a/core/java/android/backup/BackupDataInput.java b/core/java/android/backup/BackupDataInput.java
index e67b0be..67d51ea 100644
--- a/core/java/android/backup/BackupDataInput.java
+++ b/core/java/android/backup/BackupDataInput.java
@@ -21,7 +21,9 @@
import java.io.FileDescriptor;
import java.io.IOException;
-/** @hide */
+/**
+ * STOPSHIP: document!
+ */
public class BackupDataInput {
int mBackupReader;
@@ -33,6 +35,7 @@
int dataSize;
}
+ /** @hide */
public BackupDataInput(FileDescriptor fd) {
if (fd == null) throw new NullPointerException();
mBackupReader = ctor(fd);
@@ -41,6 +44,7 @@
}
}
+ /** @hide */
protected void finalize() throws Throwable {
try {
dtor(mBackupReader);
@@ -49,6 +53,13 @@
}
}
+ /**
+ * 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) {
@@ -66,6 +77,11 @@
}
}
+ /**
+ * 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;
@@ -74,6 +90,13 @@
}
}
+ /**
+ * 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;
@@ -82,6 +105,19 @@
}
}
+ /**
+ * 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);
@@ -95,6 +131,14 @@
}
}
+ /**
+ * Consume the current record's data without actually reading it into a buffer
+ * for further processing. This allows a {@link android.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);
diff --git a/core/java/android/backup/BackupDataInputStream.java b/core/java/android/backup/BackupDataInputStream.java
index b705c4c..503b3c1 100644
--- a/core/java/android/backup/BackupDataInputStream.java
+++ b/core/java/android/backup/BackupDataInputStream.java
@@ -16,12 +16,11 @@
package android.backup;
-import android.util.Log;
-
import java.io.InputStream;
import java.io.IOException;
-/** @hide */
+/**
+ * STOPSHIP: document */
public class BackupDataInputStream extends InputStream {
String key;
@@ -30,6 +29,7 @@
BackupDataInput mData;
byte[] mOneByte;
+ /** @hide */
BackupDataInputStream(BackupDataInput data) {
mData = data;
}
diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java
index d29c5ba..672d01f 100644
--- a/core/java/android/backup/BackupDataOutput.java
+++ b/core/java/android/backup/BackupDataOutput.java
@@ -21,13 +21,16 @@
import java.io.FileDescriptor;
import java.io.IOException;
-/** @hide */
+/**
+ * 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);
@@ -36,7 +39,15 @@
}
}
- // A dataSize of -1 indicates that the record under this key should be deleted
+ /**
+ * 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) {
@@ -46,6 +57,13 @@
}
}
+ /**
+ * 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) {
@@ -59,6 +77,7 @@
setKeyPrefix_native(mBackupWriter, keyPrefix);
}
+ /** @hide */
protected void finalize() throws Throwable {
try {
dtor(mBackupWriter);
diff --git a/core/java/android/backup/BackupHelper.java b/core/java/android/backup/BackupHelper.java
index 3983e28..fc48cf2 100644
--- a/core/java/android/backup/BackupHelper.java
+++ b/core/java/android/backup/BackupHelper.java
@@ -20,7 +20,9 @@
import java.io.InputStream;
-/** @hide */
+/**
+ * STOPSHIP: document!
+ */
public interface BackupHelper {
/**
* Based on oldState, determine which of the files from the application's data directory
@@ -31,16 +33,18 @@
ParcelFileDescriptor newState);
/**
- * Called by BackupHelperDispatcher to dispatch one entity of data.
+ * Called by BackupHelperAgent to restore one entity from the restore dataset.
* <p class=note>
* Do not close the <code>data</code> stream. Do not read more than
- * <code>dataSize</code> bytes from <code>data</code>.
+ * <code>data.size()</code> bytes from <code>data</code>.
*/
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 writeRestoreSnapshot(ParcelFileDescriptor fd);
+ public void writeNewStateDescription(ParcelFileDescriptor fd);
}
diff --git a/core/java/android/backup/BackupHelperAgent.java b/core/java/android/backup/BackupHelperAgent.java
index 5d0c4a2..dc17154f 100644
--- a/core/java/android/backup/BackupHelperAgent.java
+++ b/core/java/android/backup/BackupHelperAgent.java
@@ -26,28 +26,54 @@
import java.io.IOException;
-/** @hide */
+/**
+ * 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
index 6ccb83e..bf2c44d 100644
--- a/core/java/android/backup/BackupHelperDispatcher.java
+++ b/core/java/android/backup/BackupHelperDispatcher.java
@@ -138,7 +138,7 @@
// Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
for (BackupHelper helper: mHelpers.values()) {
- helper.writeRestoreSnapshot(newState);
+ helper.writeNewStateDescription(newState);
}
}
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index 0b27117..4bf59eb 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -38,7 +38,11 @@
* documentation for {@link android.app.BackupAgent} for a detailed description
* of how the backup then proceeds.
*
- * @hide pending API solidification
+ * <p>STOPSHIP more documentation here! Include the attributes:
+ * android:backupAgent
+ * android:allowBackup
+ * android:restoreNeedsApplication
+ * android:killAfterRestore
*/
public class BackupManager {
private static final String TAG = "BackupManager";
@@ -110,11 +114,8 @@
}
/**
- * Begin the process of restoring system data from backup. This method requires
- * that the application hold the "android.permission.BACKUP" permission, and is
- * not public.
- *
- * {@hide}
+ * Begin the process of restoring data from backup. See the
+ * {@link android.backup.RestoreSession} class for documentation on that process.
*/
public RestoreSession beginRestoreSession() {
if (!EVEN_THINK_ABOUT_DOING_RESTORE) {
@@ -128,7 +129,7 @@
IRestoreSession binder = sService.beginRestoreSession(transport);
session = new RestoreSession(mContext, binder);
} catch (RemoteException e) {
- Log.d(TAG, "beginRestoreSession() couldn't connect");
+ 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
index dacfc8f..68b4d42 100644
--- a/core/java/android/backup/FileBackupHelper.java
+++ b/core/java/android/backup/FileBackupHelper.java
@@ -23,7 +23,9 @@
import java.io.File;
import java.io.FileDescriptor;
-/** @hide */
+/**
+ * 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;
@@ -32,6 +34,13 @@
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);
@@ -60,6 +69,9 @@
performBackup_checked(oldState, data, newState, fullPaths, files);
}
+ /**
+ * Restore one record [representing a single file] from the restore dataset.
+ */
public void restoreEntity(BackupDataInputStream data) {
if (DEBUG) Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
String key = data.getKey();
diff --git a/core/java/android/backup/FileBackupHelperBase.java b/core/java/android/backup/FileBackupHelperBase.java
index 03ae476..a0ff38b 100644
--- a/core/java/android/backup/FileBackupHelperBase.java
+++ b/core/java/android/backup/FileBackupHelperBase.java
@@ -20,7 +20,6 @@
import android.os.ParcelFileDescriptor;
import android.util.Log;
-import java.io.InputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -80,18 +79,14 @@
}
}
- void writeFile(File f, InputStream in) {
- if (!(in instanceof BackupDataInputStream)) {
- throw new IllegalStateException("input stream must be a BackupDataInputStream");
- }
+ void writeFile(File f, BackupDataInputStream in) {
int result = -1;
// Create the enclosing directory.
File parent = f.getParentFile();
parent.mkdirs();
- result = writeFile_native(mPtr, f.getAbsolutePath(),
- ((BackupDataInputStream)in).mData.mBackupReader);
+ result = writeFile_native(mPtr, f.getAbsolutePath(), in.mData.mBackupReader);
if (result != 0) {
// Bail on this entity. Only log one failure per helper object.
if (!mExceptionLogged) {
@@ -103,7 +98,7 @@
}
}
- public void writeRestoreSnapshot(ParcelFileDescriptor fd) {
+ public void writeNewStateDescription(ParcelFileDescriptor fd) {
int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
// TODO: Do something with the error.
}
diff --git a/core/java/android/backup/RestoreObserver.java b/core/java/android/backup/RestoreObserver.java
index 3be8c08..e4182750 100644
--- a/core/java/android/backup/RestoreObserver.java
+++ b/core/java/android/backup/RestoreObserver.java
@@ -19,7 +19,6 @@
/**
* Callback class for receiving progress reports during a restore operation. These
* methods will all be called on your application's main thread.
- * @hide
*/
public abstract class RestoreObserver {
/**
diff --git a/core/java/android/backup/RestoreSession.java b/core/java/android/backup/RestoreSession.java
index d10831e..fc53854 100644
--- a/core/java/android/backup/RestoreSession.java
+++ b/core/java/android/backup/RestoreSession.java
@@ -27,7 +27,6 @@
/**
* Interface for applications to use when managing a restore session.
- * @hide
*/
public class RestoreSession {
static final String TAG = "RestoreSession";
@@ -44,6 +43,8 @@
* 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 {
@@ -66,6 +67,8 @@
* 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;
diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java
index 6a0bc96..f9c97a3 100644
--- a/core/java/android/backup/SharedPreferencesBackupHelper.java
+++ b/core/java/android/backup/SharedPreferencesBackupHelper.java
@@ -23,7 +23,9 @@
import java.io.File;
import java.io.FileDescriptor;
-/** @hide */
+/**
+ * STOPSHIP: document!
+ */
public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper {
private static final String TAG = "SharedPreferencesBackupHelper";
private static final boolean DEBUG = false;
@@ -31,6 +33,13 @@
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);
@@ -38,6 +47,9 @@
mPrefGroups = prefGroups;
}
+ /**
+ * Backs up the configured SharedPreferences groups
+ */
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
Context context = mContext;
@@ -54,6 +66,10 @@
performBackup_checked(oldState, data, newState, files, prefGroups);
}
+ /**
+ * Restores one entity from the restore data stream to its proper shared
+ * preferences file store.
+ */
public void restoreEntity(BackupDataInputStream data) {
Context context = mContext;
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index a7a6df5..d43039d 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1083,15 +1083,11 @@
synchronized(mClearDataLock) {
mClearingData = true;
- /* This is causing some critical processes to be killed during setup.
- Temporarily revert this change until we find a better solution.
try {
mActivityManager.clearApplicationUserData(packageName, observer);
} catch (RemoteException e) {
// can't happen because the activity manager is in this process
}
- */
- mPackageManager.clearApplicationUserData(packageName, observer);
// only wait 10 seconds for the clear data to happen
long timeoutMark = System.currentTimeMillis() + TIMEOUT_INTERVAL;
@@ -1660,10 +1656,6 @@
+ "] is compatible with installed version ["
+ packageInfo.versionCode + "]");
- // Now perform the actual restore: first clear the app's data
- // if appropriate
- clearApplicationDataSynchronous(packageName);
-
// Then set up and bind the agent (with a restricted Application object
// unless the application says otherwise)
boolean useRealApp = (packageInfo.applicationInfo.flags