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

Commit 336a649c authored by Christopher Tate's avatar Christopher Tate
Browse files

Prevent concurrent backup operations

We've seen cases (bug 5417779) where the transport kicked off an immediate
backup operation but then was perfectly content to allow the periodic
timer to start *another* pass concurrently while the first was still in
progress.  This wound up with the backup manager getting mightily
confused and leaking wakelock acquisitions, which is Very Bad(tm).

This patch adds a little bookkeeping so that the backup manager is aware
of backups in flight, and refuses to kick off a new one until the ongoing
one has finished.

Change-Id: If12b54f4db3effc8af36d31c58d8f9b415ddc01e
parent 63d8b0c8
Loading
Loading
Loading
Loading
+30 −12
Original line number Original line Diff line number Diff line
@@ -228,6 +228,7 @@ class BackupManagerService extends IBackupManager.Stub {
    // completed.
    // completed.
    final Object mAgentConnectLock = new Object();
    final Object mAgentConnectLock = new Object();
    IBackupAgent mConnectedAgent;
    IBackupAgent mConnectedAgent;
    volatile boolean mBackupRunning;
    volatile boolean mConnecting;
    volatile boolean mConnecting;
    volatile long mLastBackupPass;
    volatile long mLastBackupPass;
    volatile long mNextBackupPass;
    volatile long mNextBackupPass;
@@ -434,6 +435,9 @@ class BackupManagerService extends IBackupManager.Stub {
                IBackupTransport transport = getTransport(mCurrentTransport);
                IBackupTransport transport = getTransport(mCurrentTransport);
                if (transport == null) {
                if (transport == null) {
                    Slog.v(TAG, "Backup requested but no transport available");
                    Slog.v(TAG, "Backup requested but no transport available");
                    synchronized (mQueueLock) {
                        mBackupRunning = false;
                    }
                    mWakelock.release();
                    mWakelock.release();
                    break;
                    break;
                }
                }
@@ -470,6 +474,9 @@ class BackupManagerService extends IBackupManager.Stub {
                    sendMessage(pbtMessage);
                    sendMessage(pbtMessage);
                } else {
                } else {
                    Slog.v(TAG, "Backup requested but nothing pending");
                    Slog.v(TAG, "Backup requested but nothing pending");
                    synchronized (mQueueLock) {
                        mBackupRunning = false;
                    }
                    mWakelock.release();
                    mWakelock.release();
                }
                }
                break;
                break;
@@ -804,14 +811,19 @@ class BackupManagerService extends IBackupManager.Stub {
                        // Don't run backups now if we're disabled or not yet
                        // Don't run backups now if we're disabled or not yet
                        // fully set up.
                        // fully set up.
                        if (mEnabled && mProvisioned) {
                        if (mEnabled && mProvisioned) {
                            if (!mBackupRunning) {
                                if (DEBUG) Slog.v(TAG, "Running a backup pass");
                                if (DEBUG) Slog.v(TAG, "Running a backup pass");


                                // Acquire the wakelock and pass it to the backup thread.  it will
                                // Acquire the wakelock and pass it to the backup thread.  it will
                                // be released once backup concludes.
                                // be released once backup concludes.
                                mBackupRunning = true;
                                mWakelock.acquire();
                                mWakelock.acquire();


                                Message msg = mBackupHandler.obtainMessage(MSG_RUN_BACKUP);
                                Message msg = mBackupHandler.obtainMessage(MSG_RUN_BACKUP);
                                mBackupHandler.sendMessage(msg);
                                mBackupHandler.sendMessage(msg);
                            } else {
                                Slog.i(TAG, "Backup time but one already running");
                            }
                        } else {
                        } else {
                            Slog.w(TAG, "Backup pass but e=" + mEnabled + " p=" + mProvisioned);
                            Slog.w(TAG, "Backup pass but e=" + mEnabled + " p=" + mProvisioned);
                        }
                        }
@@ -1948,10 +1960,15 @@ class BackupManagerService extends IBackupManager.Stub {
                writeRestoreTokens();
                writeRestoreTokens();
            }
            }


            // Set up the next backup pass
            // Set up the next backup pass - at this point we can set mBackupRunning
            // to false to allow another pass to fire, because we're done with the
            // state machine sequence and the wakelock is refcounted.
            synchronized (mQueueLock) {
                mBackupRunning = false;
                if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
                if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
                    backupNow();
                    backupNow();
                }
                }
            }


            // Only once we're entirely finished do we release the wakelock
            // Only once we're entirely finished do we release the wakelock
            Slog.i(TAG, "Backup pass finished.");
            Slog.i(TAG, "Backup pass finished.");
@@ -2400,8 +2417,8 @@ class BackupManagerService extends IBackupManager.Stub {
                    mLatchObject.notifyAll();
                    mLatchObject.notifyAll();
                }
                }
                sendEndBackup();
                sendEndBackup();
                mWakelock.release();
                if (DEBUG) Slog.d(TAG, "Full backup pass complete.");
                if (DEBUG) Slog.d(TAG, "Full backup pass complete.");
                mWakelock.release();
            }
            }
        }
        }


@@ -2908,8 +2925,8 @@ class BackupManagerService extends IBackupManager.Stub {
                    mLatchObject.notifyAll();
                    mLatchObject.notifyAll();
                }
                }
                sendEndRestore();
                sendEndRestore();
                mWakelock.release();
                Slog.d(TAG, "Full restore pass complete.");
                Slog.d(TAG, "Full restore pass complete.");
                mWakelock.release();
            }
            }
        }
        }


@@ -5630,7 +5647,8 @@ class BackupManagerService extends IBackupManager.Stub {
                    + " / " + (!mProvisioned ? "not " : "") + "provisioned / "
                    + " / " + (!mProvisioned ? "not " : "") + "provisioned / "
                    + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init");
                    + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init");
            pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled"));
            pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled"));
            pw.println("Last backup pass: " + mLastBackupPass
            if (mBackupRunning) pw.println("Backup currently running");
            pw.println("Last backup pass started: " + mLastBackupPass
                    + " (now = " + System.currentTimeMillis() + ')');
                    + " (now = " + System.currentTimeMillis() + ')');
            pw.println("  next scheduled: " + mNextBackupPass);
            pw.println("  next scheduled: " + mNextBackupPass);