Merge "Don't block in the BackupManagerService.dataChanged() Binder call." into gingerbread

This commit is contained in:
Brad Fitzpatrick
2010-09-08 15:20:20 -07:00
committed by Android (Google) Code Review

View File

@@ -668,7 +668,7 @@ class BackupManagerService extends IBackupManager.Stub {
while (true) { while (true) {
String packageName = in.readUTF(); String packageName = in.readUTF();
Slog.i(TAG, " + " + packageName); Slog.i(TAG, " + " + packageName);
dataChanged(packageName); dataChangedImpl(packageName);
} }
} catch (EOFException e) { } catch (EOFException e) {
// no more data; we're done // no more data; we're done
@@ -740,7 +740,7 @@ class BackupManagerService extends IBackupManager.Stub {
int uid = mBackupParticipants.keyAt(i); int uid = mBackupParticipants.keyAt(i);
HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i); HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
for (ApplicationInfo app: participants) { for (ApplicationInfo app: participants) {
dataChanged(app.packageName); dataChangedImpl(app.packageName);
} }
} }
} }
@@ -896,7 +896,7 @@ class BackupManagerService extends IBackupManager.Stub {
if (!mEverStoredApps.contains(pkg.packageName)) { if (!mEverStoredApps.contains(pkg.packageName)) {
if (DEBUG) Slog.i(TAG, "New app " + pkg.packageName if (DEBUG) Slog.i(TAG, "New app " + pkg.packageName
+ " never backed up; scheduling"); + " never backed up; scheduling");
dataChanged(pkg.packageName); dataChangedImpl(pkg.packageName);
} }
} }
} }
@@ -1327,7 +1327,7 @@ class BackupManagerService extends IBackupManager.Stub {
if (status != BackupConstants.TRANSPORT_OK) { if (status != BackupConstants.TRANSPORT_OK) {
Slog.w(TAG, "Backup pass unsuccessful, restaging"); Slog.w(TAG, "Backup pass unsuccessful, restaging");
for (BackupRequest req : mQueue) { for (BackupRequest req : mQueue) {
dataChanged(req.appInfo.packageName); dataChangedImpl(req.appInfo.packageName);
} }
// We also want to reset the backup schedule based on whatever // We also want to reset the backup schedule based on whatever
@@ -1997,34 +1997,23 @@ class BackupManagerService extends IBackupManager.Stub {
} }
} }
private void dataChangedImpl(String packageName) {
HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
dataChangedImpl(packageName, targets);
}
// ----- IBackupManager binder interface ----- private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> targets) {
public void dataChanged(String packageName) {
// Record that we need a backup pass for the caller. Since multiple callers // Record that we need a backup pass for the caller. Since multiple callers
// may share a uid, we need to note all candidates within that uid and schedule // may share a uid, we need to note all candidates within that uid and schedule
// a backup pass for each of them. // a backup pass for each of them.
EventLog.writeEvent(EventLogTags.BACKUP_DATA_CHANGED, packageName); EventLog.writeEvent(EventLogTags.BACKUP_DATA_CHANGED, packageName);
// If the caller does not hold the BACKUP permission, it can only request a if (targets == null) {
// backup of its own data. Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
HashSet<ApplicationInfo> targets; + " uid=" + Binder.getCallingUid());
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), return;
Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
targets = mBackupParticipants.get(Binder.getCallingUid());
} else {
// a caller with full permission can ask to back up any participating app
// !!! TODO: allow backup of ANY app?
targets = new HashSet<ApplicationInfo>();
int N = mBackupParticipants.size();
for (int i = 0; i < N; i++) {
HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
if (s != null) {
targets.addAll(s);
} }
}
}
if (targets != null) {
synchronized (mQueueLock) { synchronized (mQueueLock) {
// Note that this client has made data changes that need to be backed up // Note that this client has made data changes that need to be backed up
for (ApplicationInfo app : targets) { for (ApplicationInfo app : targets) {
@@ -2051,10 +2040,32 @@ class BackupManagerService extends IBackupManager.Stub {
} }
} }
} }
} else {
Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+ " uid=" + Binder.getCallingUid());
} }
// Note: packageName is currently unused, but may be in the future
private HashSet<ApplicationInfo> dataChangedTargets(String packageName) {
// If the caller does not hold the BACKUP permission, it can only request a
// backup of its own data.
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
synchronized (mBackupParticipants) {
return mBackupParticipants.get(Binder.getCallingUid());
}
}
// a caller with full permission can ask to back up any participating app
// !!! TODO: allow backup of ANY app?
HashSet<ApplicationInfo> targets = new HashSet<ApplicationInfo>();
synchronized (mBackupParticipants) {
int N = mBackupParticipants.size();
for (int i = 0; i < N; i++) {
HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
if (s != null) {
targets.addAll(s);
}
}
}
return targets;
} }
private void writeToJournalLocked(String str) { private void writeToJournalLocked(String str) {
@@ -2072,6 +2083,23 @@ class BackupManagerService extends IBackupManager.Stub {
} }
} }
// ----- IBackupManager binder interface -----
public void dataChanged(final String packageName) {
final HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
if (targets == null) {
Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+ " uid=" + Binder.getCallingUid());
return;
}
mBackupHandler.post(new Runnable() {
public void run() {
dataChangedImpl(packageName, targets);
}
});
}
// Clear the given package's backup data from the current transport // Clear the given package's backup data from the current transport
public void clearBackupData(String packageName) { public void clearBackupData(String packageName) {
if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName); if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName);