Refactor android.backup => android.app.backup
Change-Id: I0b21316ff890d7f3c7d4b82837bb60670724c2e8
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.app;
|
||||
|
||||
import android.app.backup.BackupAgent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentCallbacks;
|
||||
import android.content.ComponentName;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
*/
|
||||
|
||||
75
core/java/android/app/backup/AbsoluteFileBackupHelper.java
Normal file
75
core/java/android/app/backup/AbsoluteFileBackupHelper.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app;
|
||||
package android.app.backup;
|
||||
|
||||
import android.app.IBackupAgent;
|
||||
import android.backup.BackupDataInput;
|
||||
import android.backup.BackupDataOutput;
|
||||
import android.backup.IBackupManager;
|
||||
import android.app.backup.IBackupManager;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.os.Binder;
|
||||
@@ -39,7 +37,7 @@ import java.io.IOException;
|
||||
* respectively.
|
||||
* <p>
|
||||
* A backup agent based on convenient helper classes is available in
|
||||
* {@link android.backup.BackupHelperAgent} for less complex implementation
|
||||
* {@link android.app.backup.BackupHelperAgent} for less complex implementation
|
||||
* requirements.
|
||||
* <p>
|
||||
* STOPSHIP write more documentation about the backup process here.
|
||||
@@ -87,7 +85,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.backup.BackupDataInput} instance <code>data</code>. Once
|
||||
* {@link android.app.backup.BackupDataInput} instance <code>data</code>. Once
|
||||
* the restore is finished, the application should write a representation of
|
||||
* the final state to the <code>newState</code> file descriptor.
|
||||
* <p>
|
||||
154
core/java/android/app/backup/BackupDataInput.java
Normal file
154
core/java/android/app/backup/BackupDataInput.java
Normal file
@@ -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);
|
||||
}
|
||||
63
core/java/android/app/backup/BackupDataInputStream.java
Normal file
63
core/java/android/app/backup/BackupDataInputStream.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
94
core/java/android/app/backup/BackupDataOutput.java
Normal file
94
core/java/android/app/backup/BackupDataOutput.java
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
53
core/java/android/app/backup/BackupHelper.java
Normal file
53
core/java/android/app/backup/BackupHelper.java
Normal file
@@ -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.
|
||||
* <p>
|
||||
* STOPSHOP: document!
|
||||
*/
|
||||
public interface BackupHelper {
|
||||
/**
|
||||
* Based on <code>oldState</code>, determine which of the files from the
|
||||
* application's data directory need to be backed up, write them to
|
||||
* <code>data</code>, and fill in <code>newState</code> 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.
|
||||
* <p class=note>
|
||||
* Do not close the <code>data</code> stream. Do not read more than
|
||||
* <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 writeNewStateDescription(ParcelFileDescriptor fd);
|
||||
}
|
||||
|
||||
76
core/java/android/app/backup/BackupHelperAgent.java
Normal file
76
core/java/android/app/backup/BackupHelperAgent.java
Normal file
@@ -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.
|
||||
* <p>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
149
core/java/android/app/backup/BackupHelperDispatcher.java
Normal file
149
core/java/android/app/backup/BackupHelperDispatcher.java
Normal file
@@ -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<String,BackupHelper> mHelpers = new TreeMap<String,BackupHelper>();
|
||||
|
||||
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<String,BackupHelper> helpers = (TreeMap<String,BackupHelper>)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<String,BackupHelper> 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);
|
||||
}
|
||||
|
||||
137
core/java/android/app/backup/BackupManager.java
Normal file
137
core/java/android/app/backup/BackupManager.java
Normal file
@@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* A simple implementation of a BackupAgent useful for backing up Preferences
|
||||
* and files is available by using {@link android.app.backup.BackupHelperAgent}.
|
||||
* <p>
|
||||
* STOPSHIP: more documentation!
|
||||
* <p>
|
||||
* <b>XML attributes</b>
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
104
core/java/android/app/backup/FileBackupHelper.java
Normal file
104
core/java/android/app/backup/FileBackupHelper.java
Normal file
@@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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 <code>oldState</code>, 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 <code>newState</code> with the state as it exists
|
||||
* now. When <code>oldState</code> is <code>null</code>, all the files will
|
||||
* be backed up.
|
||||
* <p>
|
||||
* 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; i<N; i++) {
|
||||
fullPaths[i] = (new File(base, files[i])).getAbsolutePath();
|
||||
}
|
||||
|
||||
// go
|
||||
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();
|
||||
if (isKeyInList(key, mFiles)) {
|
||||
File f = new File(mFilesDir, key);
|
||||
writeFile(f, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
127
core/java/android/app/backup/FileBackupHelperBase.java
Normal file
127
core/java/android/app/backup/FileBackupHelperBase.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
/**
|
||||
* Base class for the {@link android.app.backup.FileBackupHelper} implementation.
|
||||
*/
|
||||
class FileBackupHelperBase {
|
||||
private static final String TAG = "FileBackupHelperBase";
|
||||
|
||||
int mPtr;
|
||||
Context mContext;
|
||||
boolean mExceptionLogged;
|
||||
|
||||
FileBackupHelperBase(Context context) {
|
||||
mPtr = ctor();
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
dtor(mPtr);
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the parameters so the native code doesn't have to throw all the exceptions
|
||||
* since it's easier to do that from Java.
|
||||
*/
|
||||
static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState, String[] files, String[] keys) {
|
||||
if (files.length == 0) {
|
||||
return;
|
||||
}
|
||||
// files must be all absolute paths
|
||||
for (String f: files) {
|
||||
if (f.charAt(0) != '/') {
|
||||
throw new RuntimeException("files must have all absolute paths: " + f);
|
||||
}
|
||||
}
|
||||
// the length of files and keys must be the same
|
||||
if (files.length != keys.length) {
|
||||
throw new RuntimeException("files.length=" + files.length
|
||||
+ " keys.length=" + keys.length);
|
||||
}
|
||||
// oldStateFd can be null
|
||||
FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
|
||||
FileDescriptor newStateFd = newState.getFileDescriptor();
|
||||
if (newStateFd == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
|
||||
|
||||
if (err != 0) {
|
||||
// TODO: more here
|
||||
throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
|
||||
}
|
||||
}
|
||||
|
||||
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(), in.mData.mBackupReader);
|
||||
if (result != 0) {
|
||||
// Bail on this entity. Only log one failure per helper object.
|
||||
if (!mExceptionLogged) {
|
||||
Log.e(TAG, "Failed restoring file '" + f + "' for app '"
|
||||
+ mContext.getPackageName() + "\' result=0x"
|
||||
+ Integer.toHexString(result));
|
||||
mExceptionLogged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeNewStateDescription(ParcelFileDescriptor fd) {
|
||||
int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
|
||||
// TODO: Do something with the error.
|
||||
}
|
||||
|
||||
boolean isKeyInList(String key, String[] list) {
|
||||
for (String s: list) {
|
||||
if (s.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static native int ctor();
|
||||
private static native void dtor(int ptr);
|
||||
|
||||
native private static int performBackup_native(FileDescriptor oldState,
|
||||
int data, FileDescriptor newState, String[] files, String[] keys);
|
||||
|
||||
private static native int writeFile_native(int ptr, String filename, int backupReader);
|
||||
private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
|
||||
}
|
||||
|
||||
|
||||
164
core/java/android/app/backup/IBackupManager.aidl
Normal file
164
core/java/android/app/backup/IBackupManager.aidl
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.IRestoreSession;
|
||||
|
||||
/**
|
||||
* Direct interface to the Backup Manager Service that applications invoke on. The only
|
||||
* operation currently needed is a simple notification that the app has made changes to
|
||||
* data it wishes to back up, so the system should run a backup pass.
|
||||
*
|
||||
* Apps will use the {@link android.app.backup.BackupManager} class rather than going through
|
||||
* this Binder interface directly.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IBackupManager {
|
||||
/**
|
||||
* Tell the system service that the caller has made changes to its
|
||||
* data, and therefore needs to undergo an incremental backup pass.
|
||||
*
|
||||
* Any application can invoke this method for its own package, but
|
||||
* only callers who hold the android.permission.BACKUP permission
|
||||
* may invoke it for arbitrary packages.
|
||||
*/
|
||||
void dataChanged(String packageName);
|
||||
|
||||
/**
|
||||
* Erase all backed-up data for the given package from the storage
|
||||
* destination.
|
||||
*
|
||||
* Any application can invoke this method for its own package, but
|
||||
* only callers who hold the android.permission.BACKUP permission
|
||||
* may invoke it for arbitrary packages.
|
||||
*/
|
||||
void clearBackupData(String packageName);
|
||||
|
||||
/**
|
||||
* Notifies the Backup Manager Service that an agent has become available. This
|
||||
* method is only invoked by the Activity Manager.
|
||||
*/
|
||||
void agentConnected(String packageName, IBinder agent);
|
||||
|
||||
/**
|
||||
* Notify the Backup Manager Service that an agent has unexpectedly gone away.
|
||||
* This method is only invoked by the Activity Manager.
|
||||
*/
|
||||
void agentDisconnected(String packageName);
|
||||
|
||||
/**
|
||||
* Notify the Backup Manager Service that an application being installed will
|
||||
* need a data-restore pass. This method is only invoked by the Package Manager.
|
||||
*/
|
||||
void restoreAtInstall(String packageName, int token);
|
||||
|
||||
/**
|
||||
* Enable/disable the backup service entirely. When disabled, no backup
|
||||
* or restore operations will take place. Data-changed notifications will
|
||||
* still be observed and collected, however, so that changes made while the
|
||||
* mechanism was disabled will still be backed up properly if it is enabled
|
||||
* at some point in the future.
|
||||
*
|
||||
* <p>Callers 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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||
*/
|
||||
void setBackupProvisioned(boolean isProvisioned);
|
||||
|
||||
/**
|
||||
* Report whether the backup mechanism is currently enabled.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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);
|
||||
}
|
||||
50
core/java/android/app/backup/IRestoreObserver.aidl
Normal file
50
core/java/android/app/backup/IRestoreObserver.aidl
Normal file
@@ -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);
|
||||
}
|
||||
79
core/java/android/app/backup/IRestoreSession.aidl
Normal file
79
core/java/android/app/backup/IRestoreSession.aidl
Normal file
@@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session,
|
||||
* even if {@link getAvailableRestoreSets} or {@link performRestore} failed.
|
||||
*/
|
||||
void endRestoreSession();
|
||||
}
|
||||
52
core/java/android/app/backup/RestoreObserver.java
Normal file
52
core/java/android/app/backup/RestoreObserver.java
Normal file
@@ -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) {
|
||||
}
|
||||
}
|
||||
194
core/java/android/app/backup/RestoreSession.java
Normal file
194
core/java/android/app/backup/RestoreSession.java
Normal file
@@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p><b>Note:</b> The caller <i>must</i> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
19
core/java/android/app/backup/RestoreSet.aidl
Normal file
19
core/java/android/app/backup/RestoreSet.aidl
Normal file
@@ -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;
|
||||
87
core/java/android/app/backup/RestoreSet.java
Normal file
87
core/java/android/app/backup/RestoreSet.java
Normal file
@@ -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<RestoreSet> CREATOR
|
||||
= new Parcelable.Creator<RestoreSet>() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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; i<N; i++) {
|
||||
files[i] = context.getSharedPrefsFile(prefGroups[i]).getAbsolutePath();
|
||||
}
|
||||
|
||||
// go
|
||||
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;
|
||||
|
||||
String key = data.getKey();
|
||||
if (DEBUG) Log.d(TAG, "got entity '" + key + "' size=" + data.size());
|
||||
|
||||
if (isKeyInList(key, mPrefGroups)) {
|
||||
File f = context.getSharedPrefsFile(key).getAbsoluteFile();
|
||||
writeFile(f, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
core/java/android/app/backup/package.html
Normal file
22
core/java/android/app/backup/package.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
<p>Package containing the backup and restore functionality available to
|
||||
applications. All backup management is controlled through
|
||||
{@link android.backup.BackupManager}. Individual backup functionality is
|
||||
implemented through a subclass {@link android.app.BackupAgent} and a
|
||||
simple and easy-to-use implementation is provided in
|
||||
{@link android.backup.BackupHelperAgent}.</p>
|
||||
|
||||
<p>STOPSHIP: add more documenation and remove Dev Guide link if not written!</p>
|
||||
|
||||
<p>The backup APIs let applications:</p>
|
||||
<ul>
|
||||
<li>Perform backup of arbitrary data</li>
|
||||
<li>Easily perform backup of Preferences and files</li>
|
||||
<li>Handle restore of data</li>
|
||||
</ul>
|
||||
|
||||
<p>For a detailed guide to using the backup APIs, see the <a
|
||||
href="{@docRoot}guide/topics/backup.html">Backup Dev Guide topic</a>.</p>
|
||||
</BODY>
|
||||
</HTML>
|
||||
Reference in New Issue
Block a user