summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2009-06-26 21:07:13 -0700
committerChristopher Tate <ctate@google.com>2009-06-26 21:14:41 -0700
commit9171749700853305f3e6abbcdbd9e02f3a71d459 (patch)
tree7aaa1fada6783a588d1662165730e8d3f4ef591c
parent4cb1276e143e175590c69ceefa58eb721aa52846 (diff)
downloadframeworks_base-9171749700853305f3e6abbcdbd9e02f3a71d459.zip
frameworks_base-9171749700853305f3e6abbcdbd9e02f3a71d459.tar.gz
frameworks_base-9171749700853305f3e6abbcdbd9e02f3a71d459.tar.bz2
Use system properties to track the current transport
This change retools the transport selection mechanism a fair bit. Transports are now specified by name rather than by numeric ID, and the name of the currently selected transport is stored in a persistent system property under the name "persist.service.bkup.trans". The name -> IBackupTransport translation is now handled by maintaining a map from the names to the live IBackupTransport objects that correspond. The Google transport service observer now registers and unregisters the transport as the service goes up and down. The bmgr command has been expanded to include real transport interrogation and selection by name, and some documentation has been written for it.
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java65
-rw-r--r--core/java/android/backup/BackupManager.java4
-rw-r--r--core/java/android/backup/IBackupManager.aidl21
-rw-r--r--services/java/com/android/server/BackupManagerService.java118
4 files changed, 154 insertions, 54 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index c299bff..c3ddd20 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -124,11 +124,14 @@ public final class Bmgr {
private void doTransport() {
try {
- int which = Integer.parseInt(nextArg());
- int old = mBmgr.selectBackupTransport(which);
- System.out.println("Selected transport " + which + " (formerly " + old + ")");
- } catch (NumberFormatException e) {
- showUsage();
+ String which = nextArg();
+ String old = mBmgr.selectBackupTransport(which);
+ if (old == null) {
+ System.out.println("Unknown transport '" + which
+ + "' specified; no changes made.");
+ } else {
+ System.out.println("Selected transport " + which + " (formerly " + old + ")");
+ }
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(BMGR_NOT_RUNNING_ERR);
@@ -144,7 +147,7 @@ public final class Bmgr {
// The rest of the 'list' options work with a restore session on the current transport
try {
- int curTransport = mBmgr.getCurrentTransport();
+ String curTransport = mBmgr.getCurrentTransport();
mRestore = mBmgr.beginRestoreSession(curTransport);
if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR);
@@ -153,6 +156,8 @@ public final class Bmgr {
if ("sets".equals(arg)) {
doListRestoreSets();
+ } else if ("transports".equals(arg)) {
+ doListTransports();
}
mRestore.endRestoreSession();
@@ -163,6 +168,22 @@ public final class Bmgr {
}
private void doListTransports() {
+ try {
+ String current = mBmgr.getCurrentTransport();
+ String[] transports = mBmgr.listAllTransports();
+ if (transports == null || transports.length == 0) {
+ System.out.println("No transports available.");
+ return;
+ }
+
+ for (String t : transports) {
+ String pad = (t.equals(current)) ? " * " : " ";
+ System.out.println(pad + t);
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(BMGR_NOT_RUNNING_ERR);
+ }
}
private void doListRestoreSets() {
@@ -217,7 +238,7 @@ public final class Bmgr {
try {
boolean didRestore = false;
- int curTransport = mBmgr.getCurrentTransport();
+ String curTransport = mBmgr.getCurrentTransport();
mRestore = mBmgr.beginRestoreSession(curTransport);
if (mRestore == null) {
System.err.println(BMGR_NOT_RUNNING_ERR);
@@ -269,11 +290,33 @@ public final class Bmgr {
private static void showUsage() {
System.err.println("usage: bmgr [backup|restore|list|transport|run]");
- System.err.println(" bmgr backup [-f] package");
+ System.err.println(" bmgr backup PACKAGE");
+ System.err.println(" bmgr list transports");
System.err.println(" bmgr list sets");
- System.err.println(" #bmgr list transports");
- System.err.println(" #bmgr transport which#");
- System.err.println(" bmgr restore token#");
+ System.err.println(" bmgr transport WHICH");
+ System.err.println(" bmgr restore TOKEN");
System.err.println(" bmgr run");
+ System.err.println("");
+ System.err.println("The 'backup' command schedules a backup pass for the named package.");
+ System.err.println("Note that the backup pass will effectively be a no-op if the package");
+ System.err.println("does not actually have changed data to store.");
+ System.err.println("");
+ System.err.println("The 'list transports' command reports the names of the backup transports");
+ System.err.println("currently available on the device. These names can be passed as arguments");
+ System.err.println("to the 'transport' command. The currently selected transport is indicated");
+ System.err.println("with a '*' character.");
+ System.err.println("");
+ System.err.println("The 'list sets' command reports the token and name of each restore set");
+ System.err.println("available to the device via the current transport.");
+ System.err.println("");
+ System.err.println("The 'transport' command designates the named transport as the currently");
+ System.err.println("active one. This setting is persistent across reboots.");
+ System.err.println("");
+ System.err.println("The 'restore' command initiates a restore operation, using the restore set");
+ System.err.println("from the current transport whose token matches the argument.");
+ System.err.println("");
+ System.err.println("The 'run' command causes any scheduled backup operation to be initiated");
+ System.err.println("immediately, without the usual waiting period for batching together");
+ System.err.println("data changes.");
}
}
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index 79e2c03..5b4ac0d 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -83,11 +83,11 @@ public class BackupManager {
*
* {@hide}
*/
- public IRestoreSession beginRestoreSession(int transportID) {
+ public IRestoreSession beginRestoreSession(String transport) {
IRestoreSession binder = null;
if (mService != null) {
try {
- binder = mService.beginRestoreSession(transportID);
+ binder = mService.beginRestoreSession(transport);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index d6283d0..39e160b 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -63,23 +63,32 @@ interface IBackupManager {
* Identify the currently selected transport. Callers must hold the
* android.permission.BACKUP permission to use this method.
*/
- int getCurrentTransport();
+ String getCurrentTransport();
/**
- * Specify a default backup transport. Callers must hold the
+ * 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 transportID The ID of the transport to select. This should be one
+ * @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 ID of the previously selected transport.
+ * @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.
*/
- int selectBackupTransport(int transportID);
+ 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(int transportID);
+ IRestoreSession beginRestoreSession(String transportID);
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index c0f0d74..2b9ac4d 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -42,13 +42,13 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.SparseArray;
import android.backup.IBackupManager;
import android.backup.IRestoreObserver;
import android.backup.IRestoreSession;
-import android.backup.BackupManager;
import android.backup.RestoreSet;
import com.android.internal.backup.LocalTransport;
@@ -68,6 +68,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
class BackupManagerService extends IBackupManager.Stub {
private static final String TAG = "BackupManagerService";
@@ -79,7 +80,6 @@ class BackupManagerService extends IBackupManager.Stub {
private static final int MSG_RUN_BACKUP = 1;
private static final int MSG_RUN_FULL_BACKUP = 2;
private static final int MSG_RUN_RESTORE = 3;
- private static final String RESTORE_OBSERVER_KEY = "_resOb";
// Timeout interval for deciding that a bind or clear-data has taken too long
static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -127,8 +127,11 @@ class BackupManagerService extends IBackupManager.Stub {
private final Object mClearDataLock = new Object();
private volatile boolean mClearingData;
- // Current active transport & restore session
- private int mTransportId;
+ // Transport bookkeeping
+ static private final String BACKUP_TRANSPORT_PROPERTY = "persist.service.bkup.trans";
+ private final HashMap<String,IBackupTransport> mTransports
+ = new HashMap<String,IBackupTransport>();
+ private String mCurrentTransport;
private IBackupTransport mLocalTransport, mGoogleTransport;
private RestoreSession mActiveRestoreSession;
@@ -175,11 +178,19 @@ class BackupManagerService extends IBackupManager.Stub {
// Set up our transport options and initialize the default transport
// TODO: Have transports register themselves somehow?
// TODO: Don't create transports that we don't need to?
- mTransportId = BackupManager.TRANSPORT_GOOGLE;
mLocalTransport = new LocalTransport(context); // This is actually pretty cheap
- mGoogleTransport = null;
+ ComponentName localName = new ComponentName(context, LocalTransport.class);
+ registerTransport(localName.flattenToShortString(), mLocalTransport);
- // Attach to the Google backup transport.
+ mGoogleTransport = null;
+ // !!! TODO: set up the default transport name "the right way"
+ mCurrentTransport = SystemProperties.get(BACKUP_TRANSPORT_PROPERTY,
+ "com.google.android.backup/.BackupTransportService");
+ if (DEBUG) Log.v(TAG, "Starting with transport " + mCurrentTransport);
+
+ // Attach to the Google backup transport. When this comes up, it will set
+ // itself as the current transport because we explicitly reset mCurrentTransport
+ // to null.
Intent intent = new Intent().setComponent(new ComponentName(
"com.google.android.backup",
"com.google.android.backup.BackupTransportService"));
@@ -238,6 +249,13 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
+ // Add a transport to our set of available backends
+ private void registerTransport(String name, IBackupTransport transport) {
+ synchronized (mTransports) {
+ mTransports.put(name, transport);
+ }
+ }
+
// ----- Track installation/removal of packages -----
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
@@ -283,11 +301,13 @@ class BackupManagerService extends IBackupManager.Stub {
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "Connected to Google transport");
mGoogleTransport = IBackupTransport.Stub.asInterface(service);
+ registerTransport(name.flattenToShortString(), mGoogleTransport);
}
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "Disconnected from Google transport");
mGoogleTransport = null;
+ registerTransport(name.flattenToShortString(), null);
}
};
@@ -299,7 +319,7 @@ class BackupManagerService extends IBackupManager.Stub {
switch (msg.what) {
case MSG_RUN_BACKUP:
{
- IBackupTransport transport = getTransport(mTransportId);
+ IBackupTransport transport = getTransport(mCurrentTransport);
if (transport == null) {
Log.v(TAG, "Backup requested but no transport available");
break;
@@ -474,19 +494,13 @@ class BackupManagerService extends IBackupManager.Stub {
}
// Return the given transport
- private IBackupTransport getTransport(int transportID) {
- switch (transportID) {
- case BackupManager.TRANSPORT_LOCAL:
- Log.v(TAG, "Supplying local transport");
- return mLocalTransport;
-
- case BackupManager.TRANSPORT_GOOGLE:
- Log.v(TAG, "Supplying Google transport");
- return mGoogleTransport;
-
- default:
- Log.e(TAG, "Asked for unknown transport " + transportID);
- return null;
+ private IBackupTransport getTransport(String transportName) {
+ synchronized (mTransports) {
+ IBackupTransport transport = mTransports.get(transportName);
+ if (transport == null) {
+ Log.w(TAG, "Requested unavailable transport: " + transportName);
+ }
+ return transport;
}
}
@@ -1111,21 +1125,51 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- // Report the currently active transport
- public int getCurrentTransport() {
+ // Report the name of the currently active transport
+ public String getCurrentTransport() {
+ mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport");
+ Log.v(TAG, "getCurrentTransport() returning " + mCurrentTransport);
+ return mCurrentTransport;
+ }
+
+ // Report all known, available backup transports
+ public String[] listAllTransports() {
mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport");
- Log.v(TAG, "getCurrentTransport() returning " + mTransportId);
- return mTransportId;
+
+ String[] list = null;
+ ArrayList<String> known = new ArrayList<String>();
+ for (Map.Entry<String, IBackupTransport> entry : mTransports.entrySet()) {
+ if (entry.getValue() != null) {
+ known.add(entry.getKey());
+ }
+ }
+
+ if (known.size() > 0) {
+ list = new String[known.size()];
+ known.toArray(list);
+ }
+ return list;
}
- // Select which transport to use for the next backup operation
- public int selectBackupTransport(int transportId) {
+ // Select which transport to use for the next backup operation. If the given
+ // name is not one of the available transports, no action is taken and the method
+ // returns null.
+ public String selectBackupTransport(String transport) {
mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport");
- int prevTransport = mTransportId;
- mTransportId = transportId;
- Log.v(TAG, "selectBackupTransport() set " + mTransportId + " returning " + prevTransport);
- return prevTransport;
+ synchronized (mTransports) {
+ String prevTransport = null;
+ if (mTransports.get(transport) != null) {
+ prevTransport = mCurrentTransport;
+ mCurrentTransport = transport;
+ SystemProperties.set(BACKUP_TRANSPORT_PROPERTY, transport);
+ Log.v(TAG, "selectBackupTransport() set " + mCurrentTransport
+ + " returning " + prevTransport);
+ } else {
+ Log.w(TAG, "Attempt to select unavailable transport " + transport);
+ }
+ return prevTransport;
+ }
}
// Callback: a requested backup agent has been instantiated. This should only
@@ -1163,7 +1207,7 @@ class BackupManagerService extends IBackupManager.Stub {
}
// Hand off a restore session
- public IRestoreSession beginRestoreSession(int transportID) {
+ public IRestoreSession beginRestoreSession(String transport) {
mContext.enforceCallingPermission("android.permission.BACKUP", "beginRestoreSession");
synchronized(this) {
@@ -1171,7 +1215,7 @@ class BackupManagerService extends IBackupManager.Stub {
Log.d(TAG, "Restore session requested but one already active");
return null;
}
- mActiveRestoreSession = new RestoreSession(transportID);
+ mActiveRestoreSession = new RestoreSession(transport);
}
return mActiveRestoreSession;
}
@@ -1184,8 +1228,8 @@ class BackupManagerService extends IBackupManager.Stub {
private IBackupTransport mRestoreTransport = null;
RestoreSet[] mRestoreSets = null;
- RestoreSession(int transportID) {
- mRestoreTransport = getTransport(transportID);
+ RestoreSession(String transport) {
+ mRestoreTransport = getTransport(transport);
}
// --- Binder interface ---
@@ -1246,6 +1290,10 @@ class BackupManagerService extends IBackupManager.Stub {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mQueueLock) {
+ pw.println("Available transports:");
+ for (String t : listAllTransports()) {
+ pw.println(" " + t);
+ }
int N = mBackupParticipants.size();
pw.println("Participants:");
for (int i=0; i<N; i++) {