Loading services/backup/java/com/android/server/backup/UserBackupManagerService.java +55 −8 Original line number Diff line number Diff line Loading @@ -166,6 +166,52 @@ import java.util.concurrent.atomic.AtomicInteger; /** System service that performs backup/restore operations. */ public class UserBackupManagerService { /** Wrapper over {@link PowerManager.WakeLock} to prevent double-free exceptions on release() * after quit(). * */ public static class BackupWakeLock { private final PowerManager.WakeLock mPowerManagerWakeLock; private boolean mHasQuit = false; public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock) { mPowerManagerWakeLock = powerManagerWakeLock; } /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */ public synchronized void acquire() { if (mHasQuit) { Slog.v(TAG, "Ignore wakelock acquire after quit:" + mPowerManagerWakeLock.getTag()); return; } mPowerManagerWakeLock.acquire(); } /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */ public synchronized void release() { if (mHasQuit) { Slog.v(TAG, "Ignore wakelock release after quit:" + mPowerManagerWakeLock.getTag()); return; } mPowerManagerWakeLock.release(); } /** * Returns true if the {@link PowerManager.WakeLock} has been acquired but not yet released. */ public synchronized boolean isHeld() { return mPowerManagerWakeLock.isHeld(); } /** Release the {@link PowerManager.WakeLock} till it isn't held. */ public synchronized void quit() { while (mPowerManagerWakeLock.isHeld()) { Slog.v(TAG, "Releasing wakelock:" + mPowerManagerWakeLock.getTag()); mPowerManagerWakeLock.release(); } mHasQuit = true; } } // Persistently track the need to do a full init. private static final String INIT_SENTINEL_FILE_NAME = "_need_init_"; Loading Loading @@ -252,7 +298,6 @@ public class UserBackupManagerService { private final @UserIdInt int mUserId; private final BackupAgentTimeoutParameters mAgentTimeoutParameters; private final TransportManager mTransportManager; private final HandlerThread mUserBackupThread; private final Context mContext; private final PackageManager mPackageManager; Loading @@ -263,7 +308,7 @@ public class UserBackupManagerService { private final AlarmManager mAlarmManager; private final IStorageManager mStorageManager; private final BackupManagerConstants mConstants; private final PowerManager.WakeLock mWakelock; private final BackupWakeLock mWakelock; private final BackupHandler mBackupHandler; private final IBackupManager mBackupManagerBinder; Loading Loading @@ -487,8 +532,7 @@ public class UserBackupManagerService { mAgentTimeoutParameters.start(); checkNotNull(userBackupThread, "userBackupThread cannot be null"); mUserBackupThread = userBackupThread; mBackupHandler = new BackupHandler(this, userBackupThread.getLooper()); mBackupHandler = new BackupHandler(this, userBackupThread); // Set up our bookkeeping final ContentResolver resolver = context.getContentResolver(); Loading Loading @@ -588,7 +632,10 @@ public class UserBackupManagerService { mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS); // Power management mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*-" + userId); mWakelock = new BackupWakeLock( mPowerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "*backup*-" + userId + "-" + userBackupThread.getThreadId())); // Set up the various sorts of package tracking we do mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule"); Loading @@ -608,7 +655,7 @@ public class UserBackupManagerService { mContext.unregisterReceiver(mRunBackupReceiver); mContext.unregisterReceiver(mRunInitReceiver); mContext.unregisterReceiver(mPackageTrackingReceiver); mUserBackupThread.quit(); mBackupHandler.stop(); } public @UserIdInt int getUserId() { Loading Loading @@ -668,7 +715,7 @@ public class UserBackupManagerService { mSetupComplete = setupComplete; } public PowerManager.WakeLock getWakelock() { public BackupWakeLock getWakelock() { return mWakelock; } Loading @@ -679,7 +726,7 @@ public class UserBackupManagerService { @VisibleForTesting public void setWorkSource(@Nullable WorkSource workSource) { // TODO: This is for testing, unfortunately WakeLock is final and WorkSource is not exposed mWakelock.setWorkSource(workSource); mWakelock.mPowerManagerWakeLock.setWorkSource(workSource); } public Handler getBackupHandler() { Loading services/backup/java/com/android/server/backup/internal/BackupHandler.java +31 −3 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ import static com.android.server.backup.BackupManagerService.TAG; import android.app.backup.RestoreSet; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.os.HandlerThread; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; Loading Loading @@ -83,19 +83,47 @@ public class BackupHandler extends Handler { // backup task state machine tick public static final int MSG_BACKUP_RESTORE_STEP = 20; public static final int MSG_OP_COMPLETE = 21; // Release the wakelock. This is used to ensure we don't hold it after // a user is removed. This will also terminate the looper thread. public static final int MSG_STOP = 22; private final UserBackupManagerService backupManagerService; private final BackupAgentTimeoutParameters mAgentTimeoutParameters; public BackupHandler(UserBackupManagerService backupManagerService, Looper looper) { super(looper); private final HandlerThread mBackupThread; private volatile boolean mIsStopping = false; public BackupHandler( UserBackupManagerService backupManagerService, HandlerThread backupThread) { super(backupThread.getLooper()); mBackupThread = backupThread; this.backupManagerService = backupManagerService; mAgentTimeoutParameters = Preconditions.checkNotNull( backupManagerService.getAgentTimeoutParameters(), "Timeout parameters cannot be null"); } /** * Put the BackupHandler into a stopping state where the remaining messages on the queue will be * silently dropped and the {@link WakeLock} held by the {@link UserBackupManagerService} will * then be released. */ public void stop() { mIsStopping = true; sendMessage(obtainMessage(BackupHandler.MSG_STOP)); } public void handleMessage(Message msg) { if (msg.what == MSG_STOP) { Slog.v(TAG, "Stopping backup handler"); backupManagerService.getWakelock().quit(); mBackupThread.quitSafely(); } if (mIsStopping) { // If we're finishing all other types of messages should be ignored return; } TransportManager transportManager = backupManagerService.getTransportManager(); switch (msg.what) { Loading services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java +2 −2 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import static com.android.server.backup.UserBackupManagerService.RUN_INITIALIZE_ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.util.Slog; import com.android.server.backup.UserBackupManagerService; Loading Loading @@ -57,7 +56,8 @@ public class RunInitializeReceiver extends BroadcastReceiver { mUserBackupManagerService.clearPendingInits(); PowerManager.WakeLock wakelock = mUserBackupManagerService.getWakelock(); UserBackupManagerService.BackupWakeLock wakelock = mUserBackupManagerService.getWakelock(); wakelock.acquire(); OnTaskFinishedListener listener = caller -> wakelock.release(); Loading services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java +2 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Binder; import android.os.Handler; import android.os.Message; import android.os.PowerManager; import android.util.Slog; import com.android.server.backup.TransportManager; Loading Loading @@ -110,7 +109,7 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { // comes in. mBackupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT); PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock(); UserBackupManagerService.BackupWakeLock wakelock = mBackupManagerService.getWakelock(); wakelock.acquire(); // Prevent lambda from leaking 'this' Loading Loading @@ -392,7 +391,7 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { Handler backupHandler = mBackupManagerService.getBackupHandler(); backupHandler.removeMessages(MSG_RESTORE_SESSION_TIMEOUT); PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock(); UserBackupManagerService.BackupWakeLock wakelock = mBackupManagerService.getWakelock(); wakelock.acquire(); if (MORE_DEBUG) { Slog.d(TAG, callerLogString); Loading services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java +1 −2 Original line number Diff line number Diff line Loading @@ -94,7 +94,6 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.util.Pair; Loading Loading @@ -184,7 +183,7 @@ public class KeyValueBackupTaskTest { private TransportData mTransport; private ShadowLooper mShadowBackupLooper; private Handler mBackupHandler; private PowerManager.WakeLock mWakeLock; private UserBackupManagerService.BackupWakeLock mWakeLock; private KeyValueBackupReporter mReporter; private PackageManager mPackageManager; private ShadowPackageManager mShadowPackageManager; Loading Loading
services/backup/java/com/android/server/backup/UserBackupManagerService.java +55 −8 Original line number Diff line number Diff line Loading @@ -166,6 +166,52 @@ import java.util.concurrent.atomic.AtomicInteger; /** System service that performs backup/restore operations. */ public class UserBackupManagerService { /** Wrapper over {@link PowerManager.WakeLock} to prevent double-free exceptions on release() * after quit(). * */ public static class BackupWakeLock { private final PowerManager.WakeLock mPowerManagerWakeLock; private boolean mHasQuit = false; public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock) { mPowerManagerWakeLock = powerManagerWakeLock; } /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */ public synchronized void acquire() { if (mHasQuit) { Slog.v(TAG, "Ignore wakelock acquire after quit:" + mPowerManagerWakeLock.getTag()); return; } mPowerManagerWakeLock.acquire(); } /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */ public synchronized void release() { if (mHasQuit) { Slog.v(TAG, "Ignore wakelock release after quit:" + mPowerManagerWakeLock.getTag()); return; } mPowerManagerWakeLock.release(); } /** * Returns true if the {@link PowerManager.WakeLock} has been acquired but not yet released. */ public synchronized boolean isHeld() { return mPowerManagerWakeLock.isHeld(); } /** Release the {@link PowerManager.WakeLock} till it isn't held. */ public synchronized void quit() { while (mPowerManagerWakeLock.isHeld()) { Slog.v(TAG, "Releasing wakelock:" + mPowerManagerWakeLock.getTag()); mPowerManagerWakeLock.release(); } mHasQuit = true; } } // Persistently track the need to do a full init. private static final String INIT_SENTINEL_FILE_NAME = "_need_init_"; Loading Loading @@ -252,7 +298,6 @@ public class UserBackupManagerService { private final @UserIdInt int mUserId; private final BackupAgentTimeoutParameters mAgentTimeoutParameters; private final TransportManager mTransportManager; private final HandlerThread mUserBackupThread; private final Context mContext; private final PackageManager mPackageManager; Loading @@ -263,7 +308,7 @@ public class UserBackupManagerService { private final AlarmManager mAlarmManager; private final IStorageManager mStorageManager; private final BackupManagerConstants mConstants; private final PowerManager.WakeLock mWakelock; private final BackupWakeLock mWakelock; private final BackupHandler mBackupHandler; private final IBackupManager mBackupManagerBinder; Loading Loading @@ -487,8 +532,7 @@ public class UserBackupManagerService { mAgentTimeoutParameters.start(); checkNotNull(userBackupThread, "userBackupThread cannot be null"); mUserBackupThread = userBackupThread; mBackupHandler = new BackupHandler(this, userBackupThread.getLooper()); mBackupHandler = new BackupHandler(this, userBackupThread); // Set up our bookkeeping final ContentResolver resolver = context.getContentResolver(); Loading Loading @@ -588,7 +632,10 @@ public class UserBackupManagerService { mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS); // Power management mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*-" + userId); mWakelock = new BackupWakeLock( mPowerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "*backup*-" + userId + "-" + userBackupThread.getThreadId())); // Set up the various sorts of package tracking we do mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule"); Loading @@ -608,7 +655,7 @@ public class UserBackupManagerService { mContext.unregisterReceiver(mRunBackupReceiver); mContext.unregisterReceiver(mRunInitReceiver); mContext.unregisterReceiver(mPackageTrackingReceiver); mUserBackupThread.quit(); mBackupHandler.stop(); } public @UserIdInt int getUserId() { Loading Loading @@ -668,7 +715,7 @@ public class UserBackupManagerService { mSetupComplete = setupComplete; } public PowerManager.WakeLock getWakelock() { public BackupWakeLock getWakelock() { return mWakelock; } Loading @@ -679,7 +726,7 @@ public class UserBackupManagerService { @VisibleForTesting public void setWorkSource(@Nullable WorkSource workSource) { // TODO: This is for testing, unfortunately WakeLock is final and WorkSource is not exposed mWakelock.setWorkSource(workSource); mWakelock.mPowerManagerWakeLock.setWorkSource(workSource); } public Handler getBackupHandler() { Loading
services/backup/java/com/android/server/backup/internal/BackupHandler.java +31 −3 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ import static com.android.server.backup.BackupManagerService.TAG; import android.app.backup.RestoreSet; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.os.HandlerThread; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; Loading Loading @@ -83,19 +83,47 @@ public class BackupHandler extends Handler { // backup task state machine tick public static final int MSG_BACKUP_RESTORE_STEP = 20; public static final int MSG_OP_COMPLETE = 21; // Release the wakelock. This is used to ensure we don't hold it after // a user is removed. This will also terminate the looper thread. public static final int MSG_STOP = 22; private final UserBackupManagerService backupManagerService; private final BackupAgentTimeoutParameters mAgentTimeoutParameters; public BackupHandler(UserBackupManagerService backupManagerService, Looper looper) { super(looper); private final HandlerThread mBackupThread; private volatile boolean mIsStopping = false; public BackupHandler( UserBackupManagerService backupManagerService, HandlerThread backupThread) { super(backupThread.getLooper()); mBackupThread = backupThread; this.backupManagerService = backupManagerService; mAgentTimeoutParameters = Preconditions.checkNotNull( backupManagerService.getAgentTimeoutParameters(), "Timeout parameters cannot be null"); } /** * Put the BackupHandler into a stopping state where the remaining messages on the queue will be * silently dropped and the {@link WakeLock} held by the {@link UserBackupManagerService} will * then be released. */ public void stop() { mIsStopping = true; sendMessage(obtainMessage(BackupHandler.MSG_STOP)); } public void handleMessage(Message msg) { if (msg.what == MSG_STOP) { Slog.v(TAG, "Stopping backup handler"); backupManagerService.getWakelock().quit(); mBackupThread.quitSafely(); } if (mIsStopping) { // If we're finishing all other types of messages should be ignored return; } TransportManager transportManager = backupManagerService.getTransportManager(); switch (msg.what) { Loading
services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java +2 −2 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import static com.android.server.backup.UserBackupManagerService.RUN_INITIALIZE_ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.util.Slog; import com.android.server.backup.UserBackupManagerService; Loading Loading @@ -57,7 +56,8 @@ public class RunInitializeReceiver extends BroadcastReceiver { mUserBackupManagerService.clearPendingInits(); PowerManager.WakeLock wakelock = mUserBackupManagerService.getWakelock(); UserBackupManagerService.BackupWakeLock wakelock = mUserBackupManagerService.getWakelock(); wakelock.acquire(); OnTaskFinishedListener listener = caller -> wakelock.release(); Loading
services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java +2 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Binder; import android.os.Handler; import android.os.Message; import android.os.PowerManager; import android.util.Slog; import com.android.server.backup.TransportManager; Loading Loading @@ -110,7 +109,7 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { // comes in. mBackupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT); PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock(); UserBackupManagerService.BackupWakeLock wakelock = mBackupManagerService.getWakelock(); wakelock.acquire(); // Prevent lambda from leaking 'this' Loading Loading @@ -392,7 +391,7 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { Handler backupHandler = mBackupManagerService.getBackupHandler(); backupHandler.removeMessages(MSG_RESTORE_SESSION_TIMEOUT); PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock(); UserBackupManagerService.BackupWakeLock wakelock = mBackupManagerService.getWakelock(); wakelock.acquire(); if (MORE_DEBUG) { Slog.d(TAG, callerLogString); Loading
services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java +1 −2 Original line number Diff line number Diff line Loading @@ -94,7 +94,6 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.util.Pair; Loading Loading @@ -184,7 +183,7 @@ public class KeyValueBackupTaskTest { private TransportData mTransport; private ShadowLooper mShadowBackupLooper; private Handler mBackupHandler; private PowerManager.WakeLock mWakeLock; private UserBackupManagerService.BackupWakeLock mWakeLock; private KeyValueBackupReporter mReporter; private PackageManager mPackageManager; private ShadowPackageManager mShadowPackageManager; Loading