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

Commit 2e8c28e3 authored by Rupesh Bansal's avatar Rupesh Bansal
Browse files

Remove frozen callback links when wakelock binder dies

Bug: 413298655
Test: atest PowerManagerServiceTest
Flag: com.android.server.power.feature.flags.disable_frozen_process_wakelocks
Change-Id: Iea98415496ca08b017dc847e6c9115a73b22b68a
parent bd6fc1b5
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -1864,11 +1864,23 @@ public final class PowerManagerService extends SystemService
            if (index < 0) {
                return;
            }

            removeWakeLockDeathLocked(wakeLock, index);
        }
    }

    private void removeWakelockFrozenStateReferences(WakeLock wakelock) {
        if (mFeatureFlags.isDisableFrozenProcessWakelocksEnabled()) {
            try {
                wakelock.mLock.removeFrozenStateChangeCallback(wakelock);
            } catch (UnsupportedOperationException e) {
                if (DEBUG_SPEW) {
                    Slog.v(TAG, "FrozenStateChangeCallback not supported for this wakelock "
                            + wakelock.mTag + " " + e.getLocalizedMessage());
                }
            }
        }
    }

    @GuardedBy("mLock")
    private void removeWakeLockNoUpdateLocked(WakeLock wakeLock, int index) {
        removeWakeLockNoUpdateLocked(wakeLock, index,
@@ -1898,6 +1910,7 @@ public final class PowerManagerService extends SystemService

    @GuardedBy("mLock")
    private void removeWakeLockDeathLocked(WakeLock wakeLock, int index) {
        removeWakelockFrozenStateReferences(wakeLock);
        removeWakeLockNoUpdateLocked(wakeLock, index, RELEASE_REASON_WAKE_LOCK_DEATH);
        updatePowerStateLocked();
    }
+25 −11
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -64,7 +65,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.annotation.NonNull;
import android.app.ActivityManagerInternal;
import android.attention.AttentionManagerInternal;
import android.compat.testing.PlatformCompatChangeRule;
@@ -96,6 +96,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.test.TestLooper;
@@ -3195,36 +3196,49 @@ public class PowerManagerServiceTest {

    @Test
    @RequiresFlagsEnabled({Flags.FLAG_DISABLE_FROZEN_PROCESS_WAKELOCKS})
    public void testDisableWakelocks_whenFrozen() {
    public void testDisableWakelocks_whenFrozen() throws RemoteException {
        createService();
        startSystem();

        class RemoteBinder extends Binder {
            @Override
            public void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) {
        IBinder mockBinder = mock(IBinder.class);
        doNothing().when(mockBinder).addFrozenStateChangeCallback(any());
        when(mockBinder.removeFrozenStateChangeCallback(any())).thenReturn(true);

            }
        }
        RemoteBinder token = new RemoteBinder();
        WakeLock wakeLock = acquireWakeLock("frozenTestWakeLock",
                PowerManager.PARTIAL_WAKE_LOCK, token, Display.INVALID_DISPLAY);
                PowerManager.PARTIAL_WAKE_LOCK, mockBinder, Display.INVALID_DISPLAY);
        assertThat(wakeLock.mDisabled).isFalse();
        assertThat(wakeLock.isFrozenLocked()).isFalse();
        advanceTime(1000);

        // The process gets frozen, which disables the wakelock
        wakeLock.onFrozenStateChanged(token, 0);
        wakeLock.onFrozenStateChanged(mockBinder, 0);
        advanceTime(1000);
        assertThat(wakeLock.mDisabled).isTrue();
        assertThat(wakeLock.isFrozenLocked()).isTrue();

        // The process gets unfrozen, which enables the wakelock
        wakeLock.onFrozenStateChanged(token, 1);
        wakeLock.onFrozenStateChanged(mockBinder, 1);
        advanceTime(1000);
        assertThat(wakeLock.mDisabled).isFalse();
        assertThat(wakeLock.isFrozenLocked()).isFalse();
    }

    @Test
    @RequiresFlagsEnabled({Flags.FLAG_DISABLE_FROZEN_PROCESS_WAKELOCKS})
    public void testDisableWakelocks_whenBinderDies() {
        createService();
        startSystem();

        IBinder mockBinder = mock(IBinder.class);
        when(mockBinder.removeFrozenStateChangeCallback(any())).thenReturn(true);

        WakeLock wakeLock = acquireWakeLock("frozenTestWakeLock",
                PowerManager.PARTIAL_WAKE_LOCK, mockBinder, Display.INVALID_DISPLAY);

        wakeLock.binderDied();
        verify(mockBinder).removeFrozenStateChangeCallback(wakeLock);
    }

    @Test
    public void testDisableWakelocksInLightDeviceIdle_FlagDisabled_FgApp() {
        mSetFlagsRule.disableFlags(FLAG_DISABLE_WAKELOCKS_IN_LIGHT_IDLE);