Merge change 4524 into donut

* changes:
  FileRestoreHelper and RestoreHelperDispatcher work.
This commit is contained in:
Android (Google) Code Review
2009-06-17 16:34:41 -07:00
8 changed files with 193 additions and 11 deletions

View File

@ -16,6 +16,8 @@
package android.backup; package android.backup;
import android.util.Log;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.backup;
import android.content.Context;
import android.util.Log;
import java.io.File;
/** @hide */
public class FileRestoreHelper extends RestoreHelperBase implements RestoreHelper {
private static final String TAG = "FileRestoreHelper";
File mFilesDir;
public FileRestoreHelper(Context context) {
super(context);
mFilesDir = context.getFilesDir();
}
public void restoreEntity(BackupDataInputStream data) {
Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); // TODO: turn this off before ship
File f = new File(mFilesDir, data.getKey());
writeFile(f, data);
}
}

View File

@ -26,6 +26,6 @@ public interface RestoreHelper {
* Do not close the <code>data</code> stream. Do not read more than * Do not close the <code>data</code> stream. Do not read more than
* <code>dataSize</code> bytes from <code>data</code>. * <code>dataSize</code> bytes from <code>data</code>.
*/ */
public void performRestore(BackupDataInputStream data); public void restoreEntity(BackupDataInputStream data);
} }

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.backup;
import android.content.Context;
import android.util.Log;
import java.io.InputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
class RestoreHelperBase {
private static final String TAG = "RestoreHelperBase";
private static final int BUF_SIZE = 8 * 1024;
Context mContext;
byte[] mBuf = new byte[BUF_SIZE];
boolean mExceptionLogged;
RestoreHelperBase(Context context) {
mContext = context;
}
void writeFile(File f, InputStream in) {
boolean success = false;
FileOutputStream out = null;
try {
// Create the enclosing directory.
File parent = f.getParentFile();
parent.mkdirs();
// Copy the file.
int sum = 0;
out = new FileOutputStream(f);
byte[] buf = mBuf;
int amt;
while ((amt = in.read(buf)) > 0) {
out.write(buf, 0, amt);
sum += amt;
}
// TODO: Set the permissions of the file.
// We're done
success = true;
out = null;
} catch (IOException ex) {
// Bail on this entity. Only log one exception per helper object.
if (!mExceptionLogged) {
Log.e(TAG, "Failed restoring file '" + f + "' for app '"
+ mContext.getPackageName() + '\'', ex);
mExceptionLogged = true;
}
}
finally {
if (out != null) {
try {
out.close();
} catch (IOException ex) {
}
}
if (!success) {
// Something didn't work out, delete the file
f.delete();
}
}
}
}

View File

@ -21,7 +21,7 @@ import java.util.HashMap;
/** @hide */ /** @hide */
public class RestoreHelperDispatcher { public class RestoreHelperDispatcher {
HashMap<String,RestoreHelper> mHelpers; HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
public void addHelper(String keyPrefix, RestoreHelper helper) { public void addHelper(String keyPrefix, RestoreHelper helper) {
mHelpers.put(keyPrefix, helper); mHelpers.put(keyPrefix, helper);
@ -38,7 +38,7 @@ public class RestoreHelperDispatcher {
if (helper != null) { if (helper != null) {
stream.dataSize = input.getDataSize(); stream.dataSize = input.getDataSize();
stream.key = rawKey.substring(pos+1); stream.key = rawKey.substring(pos+1);
helper.performRestore(stream); helper.restoreEntity(stream);
} }
} }
input.skipEntityData(); // In case they didn't consume the data. input.skipEntityData(); // In case they didn't consume the data.

View File

@ -78,7 +78,7 @@ public:
bool HasEntities(); bool HasEntities();
status_t ReadEntityHeader(String8* key, size_t* dataSize); status_t ReadEntityHeader(String8* key, size_t* dataSize);
status_t SkipEntityData(); // must be called with the pointer at the begining of the data. status_t SkipEntityData(); // must be called with the pointer at the begining of the data.
status_t ReadEntityData(void* data, size_t size); ssize_t ReadEntityData(void* data, size_t size);
private: private:
explicit BackupDataReader(); explicit BackupDataReader();

View File

@ -281,16 +281,16 @@ BackupDataReader::SkipEntityData()
} }
} }
status_t ssize_t
BackupDataReader::ReadEntityData(void* data, size_t size) BackupDataReader::ReadEntityData(void* data, size_t size)
{ {
if (m_status != NO_ERROR) { if (m_status != NO_ERROR) {
return m_status; return m_status;
} }
int remaining = m_dataEndPos - m_pos; int remaining = m_dataEndPos - m_pos;
//LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
// size, m_pos, m_dataEndPos, remaining);
if (size > remaining) { if (size > remaining) {
printf("size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
size, m_pos, m_dataEndPos, remaining);
size = remaining; size = remaining;
} }
if (remaining <= 0) { if (remaining <= 0) {
@ -299,7 +299,7 @@ BackupDataReader::ReadEntityData(void* data, size_t size)
int amt = read(m_fd, data, size); int amt = read(m_fd, data, size);
CHECK_SIZE(amt, (int)size); CHECK_SIZE(amt, (int)size);
m_pos += size; m_pos += size;
return NO_ERROR; return amt;
} }
status_t status_t

View File

@ -17,14 +17,17 @@
package com.android.backuptest; package com.android.backuptest;
import android.app.ListActivity; import android.app.ListActivity;
import android.backup.BackupDataInput;
import android.backup.BackupDataOutput;
import android.backup.BackupManager; import android.backup.BackupManager;
import android.backup.FileBackupHelper;
import android.backup.FileRestoreHelper;
import android.backup.RestoreHelperDispatcher;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.PowerManager; import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -32,6 +35,10 @@ import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
@ -123,6 +130,44 @@ public class BackupTestActivity extends ListActivity
BackupManager bm = new BackupManager(BackupTestActivity.this); BackupManager bm = new BackupManager(BackupTestActivity.this);
bm.dataChanged(); bm.dataChanged();
} }
},
new Test("Backup Helpers") {
void run() {
try {
writeFile("a", "a\naa", MODE_PRIVATE);
writeFile("empty", "", MODE_PRIVATE);
ParcelFileDescriptor state = ParcelFileDescriptor.open(
new File(getFilesDir(), "state"),
ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
ParcelFileDescriptor.MODE_TRUNCATE);
FileBackupHelper h = new FileBackupHelper(BackupTestActivity.this,
"FileBackupHelper");
FileOutputStream dataFile = openFileOutput("backup_test", MODE_WORLD_READABLE);
BackupDataOutput data = new BackupDataOutput(BackupTestActivity.this,
dataFile.getFD());
h.performBackup(null, data, state, new String[] { "a", "empty" });
dataFile.close();
state.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
},
new Test("Restore Helpers") {
void run() {
try {
RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
dispatch.addHelper("FileBackupHelper",
new FileRestoreHelper(BackupTestActivity.this));
FileInputStream dataFile = openFileInput("backup_test");
BackupDataInput data = new BackupDataInput(dataFile.getFD());
dispatch.dispatch(data);
dataFile.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
} }
}; };
@ -154,5 +199,14 @@ public class BackupTestActivity extends ListActivity
t.run(); t.run();
} }
void writeFile(String name, String contents, int mode) {
try {
PrintStream out = new PrintStream(openFileOutput(name, mode));
out.print(contents);
out.close();
} catch (FileNotFoundException ex) {
throw new RuntimeException(ex);
}
}
} }