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

Commit 0a04ca7c authored by Android (Google) Code Review's avatar Android (Google) Code Review Committed by The Android Open Source Project
Browse files

am 7c5ae202: Merge change 6104 into donut

Merge commit '7c5ae202'

* commit '7c5ae202':
  Add a "clear backed-up data" method to the backup mechanism
parents 6375cf73 7c5ae202
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -32,9 +32,23 @@ 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.
+15 −3
Original line number Diff line number Diff line
@@ -83,13 +83,25 @@ interface IBackupTransport {
    boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);

    /**
     * Finish sending application data to the backup destination.  This must be
     * called after {@link #performBackup} to ensure that all data is sent.  Only
     * when this method returns true can the backup be assumed to have succeeded.
     * Erase the give application's data from the backup destination.  This clears
     * out the given package's data from the current backup set, making it as though
     * the app had never yet been backed up.  After this is called, {@link finishBackup}
     * must be called to ensure that the operation is recorded successfully.
     *
     * @return false if errors occurred (the backup should be aborted and rescheduled),
     *   true if everything is OK so far (but {@link #finishBackup} must be called).
     */
    boolean clearBackupData(in PackageInfo packageInfo);

    /**
     * Finish sending application data to the backup destination.  This must be
     * called after {@link #performBackup} or {@link clearBackupData} to ensure that
     * all data is sent.  Only when this method returns true can a backup be assumed
     * to have succeeded.
     *
     * @return false if errors occurred (the backup should be aborted and rescheduled),
     *   true if everything is OK.
     */
    boolean finishBackup();

    /**
+11 −0
Original line number Diff line number Diff line
@@ -111,6 +111,17 @@ public class LocalTransport extends IBackupTransport.Stub {
        }
    }

    public boolean clearBackupData(PackageInfo packageInfo) {
        if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName);

        File packageDir = new File(mDataDir, packageInfo.packageName);
        for (File f : packageDir.listFiles()) {
            f.delete();
        }
        packageDir.delete();
        return true;
    }

    public boolean finishBackup() throws RemoteException {
        if (DEBUG) Log.v(TAG, "finishBackup()");
        return true;
+95 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ 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 int MSG_RUN_CLEAR = 4;

    // Timeout interval for deciding that a bind or clear-data has taken too long
    static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -148,6 +149,16 @@ class BackupManagerService extends IBackupManager.Stub {
        }
    }

    private class ClearParams {
        public IBackupTransport transport;
        public PackageInfo packageInfo;

        ClearParams(IBackupTransport _transport, PackageInfo _info) {
            transport = _transport;
            packageInfo = _info;
        }
    }

    // Where we keep our journal files and other bookkeeping
    private File mBaseStateDir;
    private File mDataDir;
@@ -386,6 +397,13 @@ class BackupManagerService extends IBackupManager.Stub {
                (new PerformRestoreThread(params.transport, params.observer, params.token)).start();
                break;
            }

            case MSG_RUN_CLEAR:
            {
                ClearParams params = (ClearParams)msg.obj;
                (new PerformClearThread(params.transport, params.packageInfo)).start();
                break;
            }
            }
        }
    }
@@ -1071,6 +1089,37 @@ class BackupManagerService extends IBackupManager.Stub {
        }
    }

    class PerformClearThread extends Thread {
        IBackupTransport mTransport;
        PackageInfo mPackage;

        PerformClearThread(IBackupTransport transport, PackageInfo packageInfo) {
            mTransport = transport;
            mPackage = packageInfo;
        }

        @Override
        public void run() {
            try {
                // Clear the on-device backup state to ensure a full backup next time
                File stateDir = new File(mBaseStateDir, mTransport.transportDirName());
                File stateFile = new File(stateDir, mPackage.packageName);
                stateFile.delete();

                // Tell the transport to remove all the persistent storage for the app
                mTransport.clearBackupData(mPackage);
            } catch (RemoteException e) {
                // can't happen; the transport is local
            } finally {
                try {
                    mTransport.finishBackup();
                } catch (RemoteException e) {
                    // can't happen; the transport is local
                }
            }
        }
    }


    // ----- IBackupManager binder interface -----

@@ -1142,6 +1191,52 @@ class BackupManagerService extends IBackupManager.Stub {
        }
    }

    // Clear the given package's backup data from the current transport
    public void clearBackupData(String packageName) {
        if (DEBUG) Log.v(TAG, "clearBackupData() of " + packageName);
        PackageInfo info;
        try {
            info = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
        } catch (NameNotFoundException e) {
            Log.d(TAG, "No such package '" + packageName + "' - not clearing backup data");
            return;
        }

        // If the caller does not hold the BACKUP permission, it can only request a
        // wipe of its own backed-up data.
        HashSet<ApplicationInfo> apps;
        if ((mContext.checkPermission("android.permission.BACKUP", Binder.getCallingPid(),
                Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
            apps = mBackupParticipants.get(Binder.getCallingUid());
        } else {
            // a caller with full permission can ask to back up any participating app
            // !!! TODO: allow data-clear of ANY app?
            if (DEBUG) Log.v(TAG, "Privileged caller, allowing clear of other apps");
            apps = new HashSet<ApplicationInfo>();
            int N = mBackupParticipants.size();
            for (int i = 0; i < N; i++) {
                HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
                if (s != null) {
                    apps.addAll(s);
                }
            }
        }

        // now find the given package in the set of candidate apps
        for (ApplicationInfo app : apps) {
            if (app.packageName.equals(packageName)) {
                if (DEBUG) Log.v(TAG, "Found the app - running clear process");
                // found it; fire off the clear request
                synchronized (mQueueLock) {
                    Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
                            new ClearParams(getTransport(mCurrentTransport), info));
                    mBackupHandler.sendMessage(msg);
                }
                break;
            }
        }
    }

    // Run a backup pass immediately for any applications that have declared
    // that they have pending updates.
    public void backupNow() throws RemoteException {