Loading core/java/android/app/backup/BackupAgent.java +80 −20 Original line number Diff line number Diff line Loading @@ -29,18 +29,57 @@ 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 android.app.backup.BackupAgent} is the central interface between an * application and Android's data backup infrastructure. An application that wishes * to participate in the backup and restore mechanism will declare a subclass of * {@link android.app.backup.BackupAgent}, implement the * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor)} * respectively. * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor)} methods, * and provide the name of its agent class in the AndroidManifest.xml file via * the <application> tag's android:backupAgent attribute. * <p> * A backup agent based on convenient helper classes is available in * {@link android.app.backup.BackupAgentHelper} for less complex implementation * requirements. * <b>Basic Operation</b> * <p> * STOPSHIP write more documentation about the backup process here. * When the application makes changes to data that it wishes to keep backed up, * it should call the * {@link android.app.backup.BackupManager#dataChanged() BackupManager.dataChanged()} method. * This notifies the Android backup manager that the application needs an opportunity * to update its backup image. The backup manager, in turn, will then schedule a * backup pass to be performed at an opportune time. * <p> * Restore operations are typically only performed when applications are first * installed on a device. At that time, the operating system checks to see whether * there is a previously-saved data set available for the application, and if so, * begins an immediate restore pass to deliver that data as part of the installation * process. * <p> * When a backup or restore pass is run, the application's process will be launched * (if not already running), the manifest-declared agent class instantiated within * that process, and the agent's {@link #onCreate()} method invoked. This prepares the * agent instance to run the actual backup or restore logic. At this point the * agent's * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup()} or * {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()} method will be * invoked as appropriate for the operation being performed. * <p> * A backup data set consists of one or more "entities," flattened binary data records * that are each identified with a key string unique within the data set. Adding a * record to the active data set, or updating an existing record, are done by simply * writing new entity data under the desired key. Deleting an entity from the data set * is done by writing an entity under that key with header specifying a negative data * size, and no actual entity data. * <p> * <b>Helper Classes</b> * <p> * An extensible agent based on convenient helper classes is available in * {@link android.app.backup.BackupAgentHelper}. That class is particularly * suited to handling of simple file or {@link android.content.SharedPreferences} * backup and restore. * * @see android.app.backup.BackupManager * @see android.app.backup.BackupAgentHelper * @see android.app.backup.BackupDataInput * @see android.app.backup.BackupDataOutput */ public abstract class BackupAgent extends ContextWrapper { private static final String TAG = "BackupAgent"; Loading @@ -50,9 +89,22 @@ public abstract class BackupAgent extends ContextWrapper { super(null); } /** * Provided as a convenience for agent implementations that need an opportunity * to do one-time initialization before the actual backup or restore operation * is begun. * <p> * Agents do not need to override this method. */ public void onCreate() { } /** * Provided as a convenience for agent implementations that need to do some * sort of shutdown process after backup or restore is completed. * <p> * Agents do not need to override this method. */ public void onDestroy() { } Loading @@ -65,18 +117,26 @@ public abstract class BackupAgent extends ContextWrapper { * 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 * <code>newState</code>. * <p> * Each entity written to the {@link android.app.backup.BackupDataOutput} * <code>data</code> stream will be transmitted * over the current backup transport and stored in the remote data set under * the key supplied as part of the entity. Writing an entity with a negative * data size instructs the transport to delete whatever entity currently exists * under that key from the remote data set. * * @param oldState An open, read-only ParcelFileDescriptor pointing to the * last backup state provided by the application. May be * <code>null</code>, 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. * file descriptor 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. * state here after writing the requested data to the <code>data</code> * output stream. */ public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException; Loading @@ -84,8 +144,7 @@ public abstract class BackupAgent extends ContextWrapper { /** * 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 <code>data</code>. Once * provided through the <code>data</code> parameter. Once * the restore is finished, the application should write a representation of * the final state to the <code>newState</code> file descriptor. * <p> Loading @@ -98,17 +157,18 @@ public abstract class BackupAgent extends ContextWrapper { * 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 * file descriptor pointing to a full snapshot of the * application's data. The application should consume every * entity represented in this data stream. * @param appVersionCode The * {@link android.R.styleable#AndroidManifest_versionCode android:versionCode} * value of the application that backed up this particular data set. This * makes it possible for an application's agent to distinguish among any * 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. * state here after restoring its data from the <code>data</code> stream. */ public abstract void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) Loading core/java/android/app/backup/BackupAgentHelper.java +4 −1 Original line number Diff line number Diff line /* * Copyright (C) 2007 The Android Open Source Project * 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. Loading Loading @@ -30,6 +30,9 @@ import java.io.IOException; * have the BackupAgentHelper implementation process the data. * <p> * STOPSHIP: document! * * @see FileBackupHelper * @see SharedPreferencesBackupHelper */ public class BackupAgentHelper extends BackupAgent { static final String TAG = "BackupAgentHelper"; Loading core/java/android/app/backup/BackupDataInput.java +55 −17 Original line number Diff line number Diff line Loading @@ -20,7 +20,41 @@ import java.io.FileDescriptor; import java.io.IOException; /** * STOPSHIP: document! * BackupDataInput is the structured interface used for passing the contents of * a backup data set to an application's {@link BackupAgent} class in its * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor)} * method. The data is presented as a set of "entities," each * representing one named record as previously stored by the agent's * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor)} * implementation. An entity is composed of a descriptive header plus a * byte array that holds its raw data. * <p> * The agent must consume every entity in the data stream, otherwise the * restored state of the application will be incomplete. * <p> * <b>Example</b> * <p> * A typical * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) BackupAgent.onRestore(data, appVersionCode, newState)} * implementation might be structured something like this: * <pre> * while (data.readNextHeader()) { * String key = data.getKey(); * int dataSize = data.getDataSize(); * * if (key.equals(MY_BACKUP_KEY_ONE)) { * // process this kind of record here * byte[] buffer = new byte[dataSize]; * data.readEntityData(buffer, 0, dataSize); // reads the entire entity at once * * // now 'buffer' holds the raw data and can be processed however * // the agent wishes * processBackupKeyOne(buffer); * } else if (key.equals(MY_BACKUP_KEY_TO_IGNORE) { * // a key we recognize but wish to discard * data.skipEntityData(); * } // ... etc. * }</pre> */ public class BackupDataInput { int mBackupReader; Loading Loading @@ -52,10 +86,12 @@ public class BackupDataInput { } /** * Consumes the next header from the restore stream. * Extract the next entity header from the restore stream. After this method * return success, the {@link #getKey()} and {@link #getDataSize()} methods can * be used to inspect the entity that is now available for processing. * * @return true when there is an entity ready for consumption from the restore stream, * false if the restore stream has been fully consumed. * @return <code>true</code> when there is an entity ready for consumption from the * restore stream, <code>false</code> if the restore stream has been fully consumed. * @throws IOException if an error occurred while reading the restore stream */ public boolean readNextHeader() throws IOException { Loading @@ -71,25 +107,25 @@ public class BackupDataInput { } else { // error mHeaderReady = false; throw new IOException("result=0x" + Integer.toHexString(result)); throw new IOException("failed: 0x" + Integer.toHexString(result)); } } /** * Report the key associated with the current record in the restore stream * @return the current record's key string * Report the key associated with the current entity in the restore stream * @return the current entity'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"); throw new IllegalStateException("Entity header not read"); } } /** * Report the size in bytes of the data associated with the current record in the * Report the size in bytes of the data associated with the current entity in the * restore stream. * * @return The size of the record's raw data, in bytes Loading @@ -99,7 +135,7 @@ public class BackupDataInput { if (mHeaderReady) { return mHeader.dataSize; } else { throw new IllegalStateException("mHeaderReady=false"); throw new IllegalStateException("Entity header not read"); } } Loading @@ -107,13 +143,15 @@ public class BackupDataInput { * 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. * must be read in a single call. Once all of the raw data for the current entity * has been read, further calls to this method will simply return zero. * * @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 * when read from the stream * @param size The number of bytes to read in this pass * @return The number of bytes of data read. Once all of the data for this entity * has been read, further calls to this method will return zero. * @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 { Loading @@ -125,12 +163,12 @@ public class BackupDataInput { throw new IOException("result=0x" + Integer.toHexString(result)); } } else { throw new IllegalStateException("mHeaderReady=false"); throw new IllegalStateException("Entity header not read"); } } /** * Consume the current record's data without actually reading it into a buffer * Consume the current entity's data without extracting 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. Loading @@ -141,7 +179,7 @@ public class BackupDataInput { if (mHeaderReady) { skipEntityData_native(mBackupReader); } else { throw new IllegalStateException("mHeaderReady=false"); throw new IllegalStateException("Entity header not read"); } } Loading core/java/android/app/backup/BackupDataOutput.java +39 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,49 @@ package android.app.backup; import android.os.ParcelFileDescriptor; import java.io.FileDescriptor; import java.io.IOException; /** * STOPSHIP: document * This class is the structured conduit through which a {@link BackupAgent} commits * information to the current backup data set. Data written for backup is presented * as a set of "entities," key/value pairs in which each binary data record "value" is * named with a string "key." * <p> * To commit a data record to the backup transport, the agent's * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor)} * method first writes an "entity header" that supplies the key string for the record * and the total size of the binary value for the record. After the header has been * written the agent then writes the binary entity value itself. The entity value can * be written in multiple chunks if desired, as long as the total count of bytes written * matches what was supplied to {@link #writeEntityHeader(String, int)}. * <p> * Entity key strings are considered to be unique within a given application's backup * data set. If a new entity is written under an existing key string, its value will * replace any previous value in the transport's remote data store. A record can be * removed entirely from the remote data set by writing a new entity header using the * existing record's key, but supplying a negative <code>dataSize</code> parameter. * When doing this the agent does not need to call {@link #writeEntityData(byte[], int)}. * <p> * <b>Example</b> * <p> * Here is an example illustrating a way to back up the value of a String variable * called <code>mStringToBackUp</code>: * <pre> * static final String MY_STRING_KEY = "storedstring"; * * public void {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)} * throws IOException { * ... * byte[] stringBytes = mStringToBackUp.getBytes(); * data.writeEntityHeader(MY_STRING_KEY, stringBytes.length); * data.writeEntityData(stringBytes, stringBytes.length); * ... * }</pre> * * @see BackupAgent */ public class BackupDataOutput { int mBackupWriter; Loading core/java/android/app/backup/BackupHelper.java +4 −5 Original line number Diff line number Diff line Loading @@ -20,10 +20,10 @@ import android.os.ParcelFileDescriptor; /** * A convenient interface to be used with the * {@link android.app.backup.BackupAgentHelper} to implement backup and restore of * {@link android.app.backup.BackupAgentHelper} class to implement backup and restore of * arbitrary data types. * <p> * STOPSHOP: document! * STOPSHIP: document! */ public interface BackupHelper { /** Loading @@ -46,9 +46,8 @@ public interface BackupHelper { /** * Called by {@link android.app.backup.BackupAgentHelper BackupAgentHelper} * 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. * after a restore operation to write the backup state file corresponding to * the data as processed by the helper. */ public void writeNewStateDescription(ParcelFileDescriptor fd); } Loading Loading
core/java/android/app/backup/BackupAgent.java +80 −20 Original line number Diff line number Diff line Loading @@ -29,18 +29,57 @@ 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 android.app.backup.BackupAgent} is the central interface between an * application and Android's data backup infrastructure. An application that wishes * to participate in the backup and restore mechanism will declare a subclass of * {@link android.app.backup.BackupAgent}, implement the * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor)} * respectively. * and {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor)} methods, * and provide the name of its agent class in the AndroidManifest.xml file via * the <application> tag's android:backupAgent attribute. * <p> * A backup agent based on convenient helper classes is available in * {@link android.app.backup.BackupAgentHelper} for less complex implementation * requirements. * <b>Basic Operation</b> * <p> * STOPSHIP write more documentation about the backup process here. * When the application makes changes to data that it wishes to keep backed up, * it should call the * {@link android.app.backup.BackupManager#dataChanged() BackupManager.dataChanged()} method. * This notifies the Android backup manager that the application needs an opportunity * to update its backup image. The backup manager, in turn, will then schedule a * backup pass to be performed at an opportune time. * <p> * Restore operations are typically only performed when applications are first * installed on a device. At that time, the operating system checks to see whether * there is a previously-saved data set available for the application, and if so, * begins an immediate restore pass to deliver that data as part of the installation * process. * <p> * When a backup or restore pass is run, the application's process will be launched * (if not already running), the manifest-declared agent class instantiated within * that process, and the agent's {@link #onCreate()} method invoked. This prepares the * agent instance to run the actual backup or restore logic. At this point the * agent's * {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup()} or * {@link #onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()} method will be * invoked as appropriate for the operation being performed. * <p> * A backup data set consists of one or more "entities," flattened binary data records * that are each identified with a key string unique within the data set. Adding a * record to the active data set, or updating an existing record, are done by simply * writing new entity data under the desired key. Deleting an entity from the data set * is done by writing an entity under that key with header specifying a negative data * size, and no actual entity data. * <p> * <b>Helper Classes</b> * <p> * An extensible agent based on convenient helper classes is available in * {@link android.app.backup.BackupAgentHelper}. That class is particularly * suited to handling of simple file or {@link android.content.SharedPreferences} * backup and restore. * * @see android.app.backup.BackupManager * @see android.app.backup.BackupAgentHelper * @see android.app.backup.BackupDataInput * @see android.app.backup.BackupDataOutput */ public abstract class BackupAgent extends ContextWrapper { private static final String TAG = "BackupAgent"; Loading @@ -50,9 +89,22 @@ public abstract class BackupAgent extends ContextWrapper { super(null); } /** * Provided as a convenience for agent implementations that need an opportunity * to do one-time initialization before the actual backup or restore operation * is begun. * <p> * Agents do not need to override this method. */ public void onCreate() { } /** * Provided as a convenience for agent implementations that need to do some * sort of shutdown process after backup or restore is completed. * <p> * Agents do not need to override this method. */ public void onDestroy() { } Loading @@ -65,18 +117,26 @@ public abstract class BackupAgent extends ContextWrapper { * 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 * <code>newState</code>. * <p> * Each entity written to the {@link android.app.backup.BackupDataOutput} * <code>data</code> stream will be transmitted * over the current backup transport and stored in the remote data set under * the key supplied as part of the entity. Writing an entity with a negative * data size instructs the transport to delete whatever entity currently exists * under that key from the remote data set. * * @param oldState An open, read-only ParcelFileDescriptor pointing to the * last backup state provided by the application. May be * <code>null</code>, 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. * file descriptor 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. * state here after writing the requested data to the <code>data</code> * output stream. */ public abstract void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException; Loading @@ -84,8 +144,7 @@ public abstract class BackupAgent extends ContextWrapper { /** * 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 <code>data</code>. Once * provided through the <code>data</code> parameter. Once * the restore is finished, the application should write a representation of * the final state to the <code>newState</code> file descriptor. * <p> Loading @@ -98,17 +157,18 @@ public abstract class BackupAgent extends ContextWrapper { * 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 * file descriptor pointing to a full snapshot of the * application's data. The application should consume every * entity represented in this data stream. * @param appVersionCode The * {@link android.R.styleable#AndroidManifest_versionCode android:versionCode} * value of the application that backed up this particular data set. This * makes it possible for an application's agent to distinguish among any * 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. * state here after restoring its data from the <code>data</code> stream. */ public abstract void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) Loading
core/java/android/app/backup/BackupAgentHelper.java +4 −1 Original line number Diff line number Diff line /* * Copyright (C) 2007 The Android Open Source Project * 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. Loading Loading @@ -30,6 +30,9 @@ import java.io.IOException; * have the BackupAgentHelper implementation process the data. * <p> * STOPSHIP: document! * * @see FileBackupHelper * @see SharedPreferencesBackupHelper */ public class BackupAgentHelper extends BackupAgent { static final String TAG = "BackupAgentHelper"; Loading
core/java/android/app/backup/BackupDataInput.java +55 −17 Original line number Diff line number Diff line Loading @@ -20,7 +20,41 @@ import java.io.FileDescriptor; import java.io.IOException; /** * STOPSHIP: document! * BackupDataInput is the structured interface used for passing the contents of * a backup data set to an application's {@link BackupAgent} class in its * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor)} * method. The data is presented as a set of "entities," each * representing one named record as previously stored by the agent's * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor)} * implementation. An entity is composed of a descriptive header plus a * byte array that holds its raw data. * <p> * The agent must consume every entity in the data stream, otherwise the * restored state of the application will be incomplete. * <p> * <b>Example</b> * <p> * A typical * {@link BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) BackupAgent.onRestore(data, appVersionCode, newState)} * implementation might be structured something like this: * <pre> * while (data.readNextHeader()) { * String key = data.getKey(); * int dataSize = data.getDataSize(); * * if (key.equals(MY_BACKUP_KEY_ONE)) { * // process this kind of record here * byte[] buffer = new byte[dataSize]; * data.readEntityData(buffer, 0, dataSize); // reads the entire entity at once * * // now 'buffer' holds the raw data and can be processed however * // the agent wishes * processBackupKeyOne(buffer); * } else if (key.equals(MY_BACKUP_KEY_TO_IGNORE) { * // a key we recognize but wish to discard * data.skipEntityData(); * } // ... etc. * }</pre> */ public class BackupDataInput { int mBackupReader; Loading Loading @@ -52,10 +86,12 @@ public class BackupDataInput { } /** * Consumes the next header from the restore stream. * Extract the next entity header from the restore stream. After this method * return success, the {@link #getKey()} and {@link #getDataSize()} methods can * be used to inspect the entity that is now available for processing. * * @return true when there is an entity ready for consumption from the restore stream, * false if the restore stream has been fully consumed. * @return <code>true</code> when there is an entity ready for consumption from the * restore stream, <code>false</code> if the restore stream has been fully consumed. * @throws IOException if an error occurred while reading the restore stream */ public boolean readNextHeader() throws IOException { Loading @@ -71,25 +107,25 @@ public class BackupDataInput { } else { // error mHeaderReady = false; throw new IOException("result=0x" + Integer.toHexString(result)); throw new IOException("failed: 0x" + Integer.toHexString(result)); } } /** * Report the key associated with the current record in the restore stream * @return the current record's key string * Report the key associated with the current entity in the restore stream * @return the current entity'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"); throw new IllegalStateException("Entity header not read"); } } /** * Report the size in bytes of the data associated with the current record in the * Report the size in bytes of the data associated with the current entity in the * restore stream. * * @return The size of the record's raw data, in bytes Loading @@ -99,7 +135,7 @@ public class BackupDataInput { if (mHeaderReady) { return mHeader.dataSize; } else { throw new IllegalStateException("mHeaderReady=false"); throw new IllegalStateException("Entity header not read"); } } Loading @@ -107,13 +143,15 @@ public class BackupDataInput { * 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. * must be read in a single call. Once all of the raw data for the current entity * has been read, further calls to this method will simply return zero. * * @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 * when read from the stream * @param size The number of bytes to read in this pass * @return The number of bytes of data read. Once all of the data for this entity * has been read, further calls to this method will return zero. * @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 { Loading @@ -125,12 +163,12 @@ public class BackupDataInput { throw new IOException("result=0x" + Integer.toHexString(result)); } } else { throw new IllegalStateException("mHeaderReady=false"); throw new IllegalStateException("Entity header not read"); } } /** * Consume the current record's data without actually reading it into a buffer * Consume the current entity's data without extracting 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. Loading @@ -141,7 +179,7 @@ public class BackupDataInput { if (mHeaderReady) { skipEntityData_native(mBackupReader); } else { throw new IllegalStateException("mHeaderReady=false"); throw new IllegalStateException("Entity header not read"); } } Loading
core/java/android/app/backup/BackupDataOutput.java +39 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,49 @@ package android.app.backup; import android.os.ParcelFileDescriptor; import java.io.FileDescriptor; import java.io.IOException; /** * STOPSHIP: document * This class is the structured conduit through which a {@link BackupAgent} commits * information to the current backup data set. Data written for backup is presented * as a set of "entities," key/value pairs in which each binary data record "value" is * named with a string "key." * <p> * To commit a data record to the backup transport, the agent's * {@link BackupAgent#onBackup(android.os.ParcelFileDescriptor, BackupDataOutput, android.os.ParcelFileDescriptor)} * method first writes an "entity header" that supplies the key string for the record * and the total size of the binary value for the record. After the header has been * written the agent then writes the binary entity value itself. The entity value can * be written in multiple chunks if desired, as long as the total count of bytes written * matches what was supplied to {@link #writeEntityHeader(String, int)}. * <p> * Entity key strings are considered to be unique within a given application's backup * data set. If a new entity is written under an existing key string, its value will * replace any previous value in the transport's remote data store. A record can be * removed entirely from the remote data set by writing a new entity header using the * existing record's key, but supplying a negative <code>dataSize</code> parameter. * When doing this the agent does not need to call {@link #writeEntityData(byte[], int)}. * <p> * <b>Example</b> * <p> * Here is an example illustrating a way to back up the value of a String variable * called <code>mStringToBackUp</code>: * <pre> * static final String MY_STRING_KEY = "storedstring"; * * public void {@link BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)} * throws IOException { * ... * byte[] stringBytes = mStringToBackUp.getBytes(); * data.writeEntityHeader(MY_STRING_KEY, stringBytes.length); * data.writeEntityData(stringBytes, stringBytes.length); * ... * }</pre> * * @see BackupAgent */ public class BackupDataOutput { int mBackupWriter; Loading
core/java/android/app/backup/BackupHelper.java +4 −5 Original line number Diff line number Diff line Loading @@ -20,10 +20,10 @@ import android.os.ParcelFileDescriptor; /** * A convenient interface to be used with the * {@link android.app.backup.BackupAgentHelper} to implement backup and restore of * {@link android.app.backup.BackupAgentHelper} class to implement backup and restore of * arbitrary data types. * <p> * STOPSHOP: document! * STOPSHIP: document! */ public interface BackupHelper { /** Loading @@ -46,9 +46,8 @@ public interface BackupHelper { /** * Called by {@link android.app.backup.BackupAgentHelper BackupAgentHelper} * 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. * after a restore operation to write the backup state file corresponding to * the data as processed by the helper. */ public void writeNewStateDescription(ParcelFileDescriptor fd); } Loading