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

Commit 3682f501 authored by Sarp Misoglu's avatar Sarp Misoglu
Browse files

Move BackupWakeLock to its own file

There's no reason for it to be under UserBackupManagerService and bloat
it up.

Test: n/a
Flag: EXEMPT no-op refactor
Change-Id: I595fe26e97e804e59033a5dc95e8fa8e16de895f
parent 8a7102c1
Loading
Loading
Loading
Loading
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.backup;

import static com.android.server.backup.BackupManagerService.TAG;

import android.annotation.Nullable;
import android.os.PowerManager;
import android.os.WorkSource;
import android.util.Slog;

/**
 * Wrapper over {@link PowerManager.WakeLock} to prevent double-free exceptions on release()
 * after quit().
 *
 * <p>There should be a single instance of this class per {@link UserBackupManagerService}.
 */
public class BackupWakeLock {
    private final PowerManager.WakeLock mPowerManagerWakeLock;
    private boolean mHasQuit = false;
    private final String mUserIdMessage;
    private final BackupManagerConstants mBackupManagerConstants;

    public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId,
            BackupManagerConstants backupManagerConstants) {
        mPowerManagerWakeLock = powerManagerWakeLock;
        mUserIdMessage = "[UserID:" + userId + "] ";
        mBackupManagerConstants = backupManagerConstants;
    }

    /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */
    public synchronized void acquire() {
        if (mHasQuit) {
            Slog.d(TAG, mUserIdMessage + "Ignore wakelock acquire after quit: "
                    + mPowerManagerWakeLock.getTag());
            return;
        }
        // Set a timeout for the wakelock. Otherwise if we fail internally and never call
        // release(), the device might stay awake and drain battery indefinitely.
        mPowerManagerWakeLock.acquire(mBackupManagerConstants.getWakelockTimeoutMillis());
        Slog.d(TAG, mUserIdMessage + "Acquired wakelock:" + mPowerManagerWakeLock.getTag());
    }

    /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */
    public synchronized void release() {
        if (mHasQuit) {
            Slog.d(TAG, mUserIdMessage + "Ignore wakelock release after quit: "
                    + mPowerManagerWakeLock.getTag());
            return;
        }

        if (!mPowerManagerWakeLock.isHeld()) {
            Slog.w(TAG, mUserIdMessage + "Wakelock not held: " + mPowerManagerWakeLock.getTag());
            return;
        }

        mPowerManagerWakeLock.release();
        Slog.d(TAG, mUserIdMessage + "Released wakelock:" + mPowerManagerWakeLock.getTag());
    }

    /**
     * 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.d(TAG, mUserIdMessage + "Releasing wakelock: " + mPowerManagerWakeLock.getTag());
            mPowerManagerWakeLock.release();
        }
        mHasQuit = true;
    }

    /** Calls {@link PowerManager.WakeLock#setWorkSource} on the underlying wake lock. */
    public void setWorkSource(@Nullable WorkSource workSource) {
        mPowerManagerWakeLock.setWorkSource(workSource);
    }
}
+1 −94
Original line number Diff line number Diff line
@@ -86,7 +86,6 @@ import android.os.RemoteException;
import android.os.SELinux;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -172,88 +171,6 @@ 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;
        private final int mUserId;
        private final BackupManagerConstants mBackupManagerConstants;

        public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId,
                BackupManagerConstants backupManagerConstants) {
            mPowerManagerWakeLock = powerManagerWakeLock;
            mUserId = userId;
            mBackupManagerConstants = backupManagerConstants;
        }

        /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */
        public synchronized void acquire() {
            if (mHasQuit) {
                Slog.d(
                        TAG,
                        addUserIdToLogMessage(
                                mUserId,
                                "Ignore wakelock acquire after quit: "
                                        + mPowerManagerWakeLock.getTag()));
                return;
            }
            // Set a timeout for the wakelock. Otherwise if we fail internally and never call
            // release(), the device might stay awake and drain battery indefinitely.
            mPowerManagerWakeLock.acquire(mBackupManagerConstants.getWakelockTimeoutMillis());
            Slog.d(
                    TAG,
                    addUserIdToLogMessage(
                            mUserId, "Acquired wakelock:" + mPowerManagerWakeLock.getTag()));
        }

        /** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */
        public synchronized void release() {
            if (mHasQuit) {
                Slog.d(
                        TAG,
                        addUserIdToLogMessage(
                                mUserId,
                                "Ignore wakelock release after quit: "
                                        + mPowerManagerWakeLock.getTag()));
                return;
            }

            if (!mPowerManagerWakeLock.isHeld()) {
                Slog.w(TAG, addUserIdToLogMessage(mUserId,
                        "Wakelock not held: " + mPowerManagerWakeLock.getTag()));
                return;
            }

            mPowerManagerWakeLock.release();
            Slog.d(
                    TAG,
                    addUserIdToLogMessage(
                            mUserId, "Released wakelock:" + mPowerManagerWakeLock.getTag()));
        }

        /**
         * 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.d(
                        TAG,
                        addUserIdToLogMessage(
                                mUserId, "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_";

@@ -756,20 +673,10 @@ public class UserBackupManagerService {
        mSetupComplete = setupComplete;
    }

    public BackupWakeLock getWakelock() {
    public BackupWakeLock getWakeLock() {
        return mWakelock;
    }

    /**
     * Sets the {@link WorkSource} of the {@link PowerManager.WakeLock} returned by {@link
     * #getWakelock()}.
     */
    @VisibleForTesting
    public void setWorkSource(@Nullable WorkSource workSource) {
        // TODO: This is for testing, unfortunately WakeLock is final and WorkSource is not exposed
        mWakelock.mPowerManagerWakeLock.setWorkSource(workSource);
    }

    public Handler getBackupHandler() {
        return mBackupHandler;
    }
+1 −1
Original line number Diff line number Diff line
@@ -468,7 +468,7 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
            sendEndBackup();
            obbConnection.tearDown();
            Slog.d(TAG, "Full backup pass complete.");
            mUserBackupManagerService.getWakelock().release();
            mUserBackupManagerService.getWakeLock().release();
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -688,7 +688,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
                    .getBackupAgentConnectionManager().clearNoRestrictedModePackages();

            Slog.i(TAG, "Full data backup pass finished.");
            mUserBackupManagerService.getWakelock().release();
            mUserBackupManagerService.getWakeLock().release();
        }
    }

+4 −4
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ public class BackupHandler extends Handler {
    public void handleMessage(Message msg) {
        if (msg.what == MSG_STOP) {
            Slog.d(TAG, "Stopping backup handler");
            backupManagerService.getWakelock().quit();
            backupManagerService.getWakeLock().quit();
            mBackupThread.quitSafely();
        }

@@ -181,7 +181,7 @@ public class BackupHandler extends Handler {
                    // Acquire the wakelock and pass it to the backup thread. It will be released
                    // once backup concludes.
                    backupManagerService.setBackupRunning(true);
                    backupManagerService.getWakelock().acquire();
                    backupManagerService.getWakeLock().acquire();

                    // Do we have any work to do?  Construct the work queue
                    // then release the synchronization lock to actually run
@@ -254,7 +254,7 @@ public class BackupHandler extends Handler {
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.setBackupRunning(false);
                    }
                    backupManagerService.getWakelock().release();
                    backupManagerService.getWakeLock().release();
                }
                break;
            }
@@ -466,7 +466,7 @@ public class BackupHandler extends Handler {
                    Slog.d(TAG, "MSG_REQUEST_BACKUP observer=" + params.observer);
                }
                backupManagerService.setBackupRunning(true);
                backupManagerService.getWakelock().acquire();
                backupManagerService.getWakeLock().acquire();

                KeyValueBackupTask.start(
                        backupManagerService,
Loading