Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65634a79 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick Committed by Android (Google) Code Review
Browse files

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

parents d9c80ab3 3dd42334
Loading
Loading
Loading
Loading
+72 −44
Original line number Diff line number Diff line
@@ -668,7 +668,7 @@ class BackupManagerService extends IBackupManager.Stub {
                    while (true) {
                        String packageName = in.readUTF();
                        Slog.i(TAG, "    + " + packageName);
                        dataChanged(packageName);
                        dataChangedImpl(packageName);
                    }
                } catch (EOFException e) {
                    // no more data; we're done
@@ -740,7 +740,7 @@ class BackupManagerService extends IBackupManager.Stub {
                int uid = mBackupParticipants.keyAt(i);
                HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
                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 (DEBUG) Slog.i(TAG, "New app " + pkg.packageName
                            + " never backed up; scheduling");
                    dataChanged(pkg.packageName);
                    dataChangedImpl(pkg.packageName);
                }
            }
        }
@@ -1327,7 +1327,7 @@ class BackupManagerService extends IBackupManager.Stub {
                if (status != BackupConstants.TRANSPORT_OK) {
                    Slog.w(TAG, "Backup pass unsuccessful, restaging");
                    for (BackupRequest req : mQueue) {
                        dataChanged(req.appInfo.packageName);
                        dataChangedImpl(req.appInfo.packageName);
                    }

                    // 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 -----

    public void dataChanged(String packageName) {
    private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> targets) {
        // 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
        // a backup pass for each of them.
        EventLog.writeEvent(EventLogTags.BACKUP_DATA_CHANGED, packageName);

        // If the caller does not hold the BACKUP permission, it can only request a
        // backup of its own data.
        HashSet<ApplicationInfo> targets;
        if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
                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) {
            Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
                   + " uid=" + Binder.getCallingUid());
            return;
        }
        if (targets != null) {

        synchronized (mQueueLock) {
            // Note that this client has made data changes that need to be backed up
            for (ApplicationInfo app : targets) {
@@ -2051,12 +2040,34 @@ 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) {
        RandomAccessFile out = null;
        try {
@@ -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
    public void clearBackupData(String packageName) {
        if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName);