Loading services/java/com/android/server/BackupManagerService.java +111 −38 Original line number Diff line number Diff line Loading @@ -100,18 +100,18 @@ class BackupManagerService extends IBackupManager.Stub { private PowerManager mPowerManager; private AlarmManager mAlarmManager; private boolean mEnabled; // access to this is synchronized on 'this' private boolean mProvisioned; private PowerManager.WakeLock mWakelock; private final BackupHandler mBackupHandler = new BackupHandler(); private PendingIntent mRunBackupIntent; private BroadcastReceiver mRunBackupReceiver; private IntentFilter mRunBackupFilter; boolean mEnabled; // access to this is synchronized on 'this' boolean mProvisioned; PowerManager.WakeLock mWakelock; final BackupHandler mBackupHandler = new BackupHandler(); PendingIntent mRunBackupIntent; BroadcastReceiver mRunBackupReceiver; IntentFilter mRunBackupFilter; // map UIDs to the set of backup client services within that UID's app set private final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants = new SparseArray<HashSet<ApplicationInfo>>(); // set of backup services that have pending changes private class BackupRequest { class BackupRequest { public ApplicationInfo appInfo; public boolean fullBackup; Loading @@ -125,35 +125,35 @@ class BackupManagerService extends IBackupManager.Stub { } } // Backups that we haven't started yet. private HashMap<ApplicationInfo,BackupRequest> mPendingBackups HashMap<ApplicationInfo,BackupRequest> mPendingBackups = new HashMap<ApplicationInfo,BackupRequest>(); // Pseudoname that we use for the Package Manager metadata "package" private static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; // locking around the pending-backup management private final Object mQueueLock = new Object(); final Object mQueueLock = new Object(); // The thread performing the sequence of queued backups binds to each app's agent // in succession. Bind notifications are asynchronously delivered through the // Activity Manager; use this lock object to signal when a requested binding has // completed. private final Object mAgentConnectLock = new Object(); private IBackupAgent mConnectedAgent; private volatile boolean mConnecting; final Object mAgentConnectLock = new Object(); IBackupAgent mConnectedAgent; volatile boolean mConnecting; // A similar synchronicity mechanism around clearing apps' data for restore private final Object mClearDataLock = new Object(); private volatile boolean mClearingData; final Object mClearDataLock = new Object(); volatile boolean mClearingData; // Transport bookkeeping private final HashMap<String,IBackupTransport> mTransports final HashMap<String,IBackupTransport> mTransports = new HashMap<String,IBackupTransport>(); private String mCurrentTransport; private IBackupTransport mLocalTransport, mGoogleTransport; private RestoreSession mActiveRestoreSession; String mCurrentTransport; IBackupTransport mLocalTransport, mGoogleTransport; RestoreSession mActiveRestoreSession; private class RestoreParams { class RestoreParams { public IBackupTransport transport; public IRestoreObserver observer; public long token; Loading @@ -165,7 +165,7 @@ class BackupManagerService extends IBackupManager.Stub { } } private class ClearParams { class ClearParams { public IBackupTransport transport; public PackageInfo packageInfo; Loading @@ -176,11 +176,17 @@ class BackupManagerService extends IBackupManager.Stub { } // Where we keep our journal files and other bookkeeping private File mBaseStateDir; private File mDataDir; private File mJournalDir; private File mJournal; private RandomAccessFile mJournalStream; File mBaseStateDir; File mDataDir; File mJournalDir; File mJournal; RandomAccessFile mJournalStream; // Keep a log of all the apps we've ever backed up private File mEverStored; private RandomAccessFile mEverStoredStream; HashSet<String> mEverStoredApps = new HashSet<String>(); public BackupManagerService(Context context) { mContext = context; Loading Loading @@ -215,6 +221,9 @@ class BackupManagerService extends IBackupManager.Stub { mJournalDir.mkdirs(); // creates mBaseStateDir along the way makeJournalLocked(); // okay because no other threads are running yet // Set up the various sorts of package tracking we do initPackageTracking(); // Build our mapping of uid to backup client services. This implicitly // schedules a backup pass on the Package Manager metadata the first // time anything needs to be backed up. Loading Loading @@ -249,14 +258,6 @@ class BackupManagerService extends IBackupManager.Stub { // leftover journal files into the pending backup set parseLeftoverJournals(); // Register for broadcasts about package install, etc., so we can // update the provider list. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); mContext.registerReceiver(mBroadcastReceiver, filter); // Power management mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "backup"); Loading @@ -281,6 +282,39 @@ class BackupManagerService extends IBackupManager.Stub { } } private void initPackageTracking() { if (DEBUG) Log.v(TAG, "Initializing package tracking"); // Keep a log of what apps we've ever backed up mEverStored = new File(mBaseStateDir, "processed"); try { mEverStoredStream = new RandomAccessFile(mEverStored, "rwd"); // parse its existing contents mEverStoredStream.seek(0); try { while (true) { String pkg = mEverStoredStream.readUTF(); mEverStoredApps.add(pkg); if (DEBUG) Log.v(TAG, " + " + pkg); } } catch (EOFException e) { // now we're at EOF } } catch (IOException e) { Log.e(TAG, "Unable to open known-stored file!"); mEverStoredStream = null; } // Register for broadcasts about package install, etc., so we can // update the provider list. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); mContext.registerReceiver(mBroadcastReceiver, filter); } private void makeJournalLocked() { try { mJournal = File.createTempFile("journal", null, mJournalDir); Loading Loading @@ -485,6 +519,17 @@ class BackupManagerService extends IBackupManager.Stub { mBackupParticipants.put(uid, set); } set.add(pkg.applicationInfo); // If we've never seen this app before, schedule a backup for it if (!mEverStoredApps.contains(pkg.packageName)) { if (DEBUG) Log.i(TAG, "New app " + pkg.packageName + " never backed up; scheduling"); try { dataChanged(pkg.packageName); } catch (RemoteException e) { // can't happen; it's a local method call } } } } } Loading Loading @@ -540,7 +585,7 @@ class BackupManagerService extends IBackupManager.Stub { } // Returns the set of all applications that define an android:backupAgent attribute private List<PackageInfo> allAgentPackages() { List<PackageInfo> allAgentPackages() { // !!! TODO: cache this and regenerate only when necessary int flags = PackageManager.GET_SIGNATURES; List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags); Loading Loading @@ -570,6 +615,28 @@ class BackupManagerService extends IBackupManager.Stub { addPackageParticipantsLockedInner(packageName, allApps); } // Called from the backup thread: record that the given app has been successfully // backed up at least once void logBackupComplete(String packageName) { if (mEverStoredStream != null) { synchronized (mEverStoredApps) { if (mEverStoredApps.add(packageName)) { try { mEverStoredStream.writeUTF(packageName); } catch (IOException e) { Log.e(TAG, "Unable to log backup of " + packageName + ", ceasing log"); try { mEverStoredStream.close(); } catch (IOException ioe) { // we're dropping it; no need to handle an exception on close here } mEverStoredStream = null; } } } } } // Return the given transport private IBackupTransport getTransport(String transportName) { synchronized (mTransports) { Loading Loading @@ -799,6 +866,7 @@ class BackupManagerService extends IBackupManager.Stub { boolean success = false; try { agent.doBackup(savedState, backupData, newState); logBackupComplete(packageName); success = true; } finally { if (savedState != null) { Loading Loading @@ -1235,7 +1303,8 @@ class BackupManagerService extends IBackupManager.Stub { } } } else { Log.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"); Log.w(TAG, "dataChanged but no participant pkg='" + packageName + "'" + " uid=" + Binder.getCallingUid()); } } Loading Loading @@ -1566,6 +1635,10 @@ class BackupManagerService extends IBackupManager.Stub { pw.println(" " + app.toString()); } } pw.println("Ever backed up: " + mEverStoredApps.size()); for (String pkg : mEverStoredApps) { pw.println(" " + pkg); } pw.println("Pending: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.println(" " + req); Loading Loading
services/java/com/android/server/BackupManagerService.java +111 −38 Original line number Diff line number Diff line Loading @@ -100,18 +100,18 @@ class BackupManagerService extends IBackupManager.Stub { private PowerManager mPowerManager; private AlarmManager mAlarmManager; private boolean mEnabled; // access to this is synchronized on 'this' private boolean mProvisioned; private PowerManager.WakeLock mWakelock; private final BackupHandler mBackupHandler = new BackupHandler(); private PendingIntent mRunBackupIntent; private BroadcastReceiver mRunBackupReceiver; private IntentFilter mRunBackupFilter; boolean mEnabled; // access to this is synchronized on 'this' boolean mProvisioned; PowerManager.WakeLock mWakelock; final BackupHandler mBackupHandler = new BackupHandler(); PendingIntent mRunBackupIntent; BroadcastReceiver mRunBackupReceiver; IntentFilter mRunBackupFilter; // map UIDs to the set of backup client services within that UID's app set private final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants = new SparseArray<HashSet<ApplicationInfo>>(); // set of backup services that have pending changes private class BackupRequest { class BackupRequest { public ApplicationInfo appInfo; public boolean fullBackup; Loading @@ -125,35 +125,35 @@ class BackupManagerService extends IBackupManager.Stub { } } // Backups that we haven't started yet. private HashMap<ApplicationInfo,BackupRequest> mPendingBackups HashMap<ApplicationInfo,BackupRequest> mPendingBackups = new HashMap<ApplicationInfo,BackupRequest>(); // Pseudoname that we use for the Package Manager metadata "package" private static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; // locking around the pending-backup management private final Object mQueueLock = new Object(); final Object mQueueLock = new Object(); // The thread performing the sequence of queued backups binds to each app's agent // in succession. Bind notifications are asynchronously delivered through the // Activity Manager; use this lock object to signal when a requested binding has // completed. private final Object mAgentConnectLock = new Object(); private IBackupAgent mConnectedAgent; private volatile boolean mConnecting; final Object mAgentConnectLock = new Object(); IBackupAgent mConnectedAgent; volatile boolean mConnecting; // A similar synchronicity mechanism around clearing apps' data for restore private final Object mClearDataLock = new Object(); private volatile boolean mClearingData; final Object mClearDataLock = new Object(); volatile boolean mClearingData; // Transport bookkeeping private final HashMap<String,IBackupTransport> mTransports final HashMap<String,IBackupTransport> mTransports = new HashMap<String,IBackupTransport>(); private String mCurrentTransport; private IBackupTransport mLocalTransport, mGoogleTransport; private RestoreSession mActiveRestoreSession; String mCurrentTransport; IBackupTransport mLocalTransport, mGoogleTransport; RestoreSession mActiveRestoreSession; private class RestoreParams { class RestoreParams { public IBackupTransport transport; public IRestoreObserver observer; public long token; Loading @@ -165,7 +165,7 @@ class BackupManagerService extends IBackupManager.Stub { } } private class ClearParams { class ClearParams { public IBackupTransport transport; public PackageInfo packageInfo; Loading @@ -176,11 +176,17 @@ class BackupManagerService extends IBackupManager.Stub { } // Where we keep our journal files and other bookkeeping private File mBaseStateDir; private File mDataDir; private File mJournalDir; private File mJournal; private RandomAccessFile mJournalStream; File mBaseStateDir; File mDataDir; File mJournalDir; File mJournal; RandomAccessFile mJournalStream; // Keep a log of all the apps we've ever backed up private File mEverStored; private RandomAccessFile mEverStoredStream; HashSet<String> mEverStoredApps = new HashSet<String>(); public BackupManagerService(Context context) { mContext = context; Loading Loading @@ -215,6 +221,9 @@ class BackupManagerService extends IBackupManager.Stub { mJournalDir.mkdirs(); // creates mBaseStateDir along the way makeJournalLocked(); // okay because no other threads are running yet // Set up the various sorts of package tracking we do initPackageTracking(); // Build our mapping of uid to backup client services. This implicitly // schedules a backup pass on the Package Manager metadata the first // time anything needs to be backed up. Loading Loading @@ -249,14 +258,6 @@ class BackupManagerService extends IBackupManager.Stub { // leftover journal files into the pending backup set parseLeftoverJournals(); // Register for broadcasts about package install, etc., so we can // update the provider list. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); mContext.registerReceiver(mBroadcastReceiver, filter); // Power management mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "backup"); Loading @@ -281,6 +282,39 @@ class BackupManagerService extends IBackupManager.Stub { } } private void initPackageTracking() { if (DEBUG) Log.v(TAG, "Initializing package tracking"); // Keep a log of what apps we've ever backed up mEverStored = new File(mBaseStateDir, "processed"); try { mEverStoredStream = new RandomAccessFile(mEverStored, "rwd"); // parse its existing contents mEverStoredStream.seek(0); try { while (true) { String pkg = mEverStoredStream.readUTF(); mEverStoredApps.add(pkg); if (DEBUG) Log.v(TAG, " + " + pkg); } } catch (EOFException e) { // now we're at EOF } } catch (IOException e) { Log.e(TAG, "Unable to open known-stored file!"); mEverStoredStream = null; } // Register for broadcasts about package install, etc., so we can // update the provider list. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); mContext.registerReceiver(mBroadcastReceiver, filter); } private void makeJournalLocked() { try { mJournal = File.createTempFile("journal", null, mJournalDir); Loading Loading @@ -485,6 +519,17 @@ class BackupManagerService extends IBackupManager.Stub { mBackupParticipants.put(uid, set); } set.add(pkg.applicationInfo); // If we've never seen this app before, schedule a backup for it if (!mEverStoredApps.contains(pkg.packageName)) { if (DEBUG) Log.i(TAG, "New app " + pkg.packageName + " never backed up; scheduling"); try { dataChanged(pkg.packageName); } catch (RemoteException e) { // can't happen; it's a local method call } } } } } Loading Loading @@ -540,7 +585,7 @@ class BackupManagerService extends IBackupManager.Stub { } // Returns the set of all applications that define an android:backupAgent attribute private List<PackageInfo> allAgentPackages() { List<PackageInfo> allAgentPackages() { // !!! TODO: cache this and regenerate only when necessary int flags = PackageManager.GET_SIGNATURES; List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags); Loading Loading @@ -570,6 +615,28 @@ class BackupManagerService extends IBackupManager.Stub { addPackageParticipantsLockedInner(packageName, allApps); } // Called from the backup thread: record that the given app has been successfully // backed up at least once void logBackupComplete(String packageName) { if (mEverStoredStream != null) { synchronized (mEverStoredApps) { if (mEverStoredApps.add(packageName)) { try { mEverStoredStream.writeUTF(packageName); } catch (IOException e) { Log.e(TAG, "Unable to log backup of " + packageName + ", ceasing log"); try { mEverStoredStream.close(); } catch (IOException ioe) { // we're dropping it; no need to handle an exception on close here } mEverStoredStream = null; } } } } } // Return the given transport private IBackupTransport getTransport(String transportName) { synchronized (mTransports) { Loading Loading @@ -799,6 +866,7 @@ class BackupManagerService extends IBackupManager.Stub { boolean success = false; try { agent.doBackup(savedState, backupData, newState); logBackupComplete(packageName); success = true; } finally { if (savedState != null) { Loading Loading @@ -1235,7 +1303,8 @@ class BackupManagerService extends IBackupManager.Stub { } } } else { Log.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"); Log.w(TAG, "dataChanged but no participant pkg='" + packageName + "'" + " uid=" + Binder.getCallingUid()); } } Loading Loading @@ -1566,6 +1635,10 @@ class BackupManagerService extends IBackupManager.Stub { pw.println(" " + app.toString()); } } pw.println("Ever backed up: " + mEverStoredApps.size()); for (String pkg : mEverStoredApps) { pw.println(" " + pkg); } pw.println("Pending: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.println(" " + req); Loading