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

Commit c339d55d authored by Philip Junker's avatar Philip Junker Committed by Android (Google) Code Review
Browse files

Merge "Disable screen wake locks for cached apps" into udc-dev

parents d77e6968 4138a2e2
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1762,6 +1762,15 @@ public final class DisplayManager {
         * 123,1,critical,0.8,default;123,1,moderate,0.6,id_2;456,2,moderate,0.9,critical,0.7
         */
        String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data";

        /**
         * Key for disabling screen wake locks while apps are in cached state.
         * Read value via {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)}
         * with {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace.
         * @hide
         */
        String KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED =
                "disable_screen_wake_locks_while_cached";
    }

    /**
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.display.feature;

import android.hardware.display.DisplayManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;

import java.util.concurrent.Executor;

/**
 * Helper class to access all DeviceConfig features for display_manager namespace
 *
 **/
public class DeviceConfigParameterProvider {

    private static final String TAG = "DisplayFeatureProvider";

    private final DeviceConfigInterface mDeviceConfig;

    public DeviceConfigParameterProvider(DeviceConfigInterface deviceConfig) {
        mDeviceConfig = deviceConfig;
    }

    public boolean isDisableScreenWakeLocksWhileCachedFeatureEnabled() {
        return mDeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                DisplayManager.DeviceConfig.KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED, true);
    }

    /** add property change listener to DeviceConfig */
    public void addOnPropertiesChangedListener(Executor executor,
            DeviceConfig.OnPropertiesChangedListener listener) {
        mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                executor, listener);
    }
}
+46 −6
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
@@ -128,6 +129,7 @@ import com.android.server.UiThread;
import com.android.server.UserspaceRebootLogger;
import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
import com.android.server.policy.WindowManagerPolicy;
@@ -323,6 +325,9 @@ public final class PowerManagerService extends SystemService
    private final Injector mInjector;
    private final PermissionCheckerWrapper mPermissionCheckerWrapper;
    private final PowerPropertiesWrapper mPowerPropertiesWrapper;
    private final DeviceConfigParameterProvider mDeviceConfigProvider;

    private boolean mDisableScreenWakeLocksWhileCached;

    private LightsManager mLightsManager;
    private BatteryManagerInternal mBatteryManagerInternal;
@@ -1065,6 +1070,10 @@ public final class PowerManagerService extends SystemService
                }
            };
        }

        DeviceConfigParameterProvider createDeviceConfigParameterProvider() {
            return new DeviceConfigParameterProvider(DeviceConfigInterface.REAL);
        }
    }

    /** Interface for checking an app op permission */
@@ -1161,6 +1170,7 @@ public final class PowerManagerService extends SystemService
                mInjector.createInattentiveSleepWarningController();
        mPermissionCheckerWrapper = mInjector.createPermissionCheckerWrapper();
        mPowerPropertiesWrapper = mInjector.createPowerPropertiesWrapper();
        mDeviceConfigProvider = mInjector.createDeviceConfigParameterProvider();

        mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();

@@ -1346,6 +1356,14 @@ public final class PowerManagerService extends SystemService

            mLightsManager = getLocalService(LightsManager.class);
            mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
            updateDeviceConfigLocked();
            mDeviceConfigProvider.addOnPropertiesChangedListener(BackgroundThread.getExecutor(),
                    properties -> {
                        synchronized (mLock) {
                            updateDeviceConfigLocked();
                            updateWakeLockDisabledStatesLocked();
                        }
                    });

            // Initialize display power management.
            mDisplayManagerInternal.initPowerManagement(
@@ -1545,6 +1563,12 @@ public final class PowerManagerService extends SystemService
        updatePowerStateLocked();
    }

    @GuardedBy("mLock")
    private void updateDeviceConfigLocked() {
        mDisableScreenWakeLocksWhileCached = mDeviceConfigProvider
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
    }

    @RequiresPermission(value = android.Manifest.permission.TURN_SCREEN_ON, conditional = true)
    private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag,
            String packageName, WorkSource ws, String historyTag, int uid, int pid,
@@ -2760,13 +2784,13 @@ public final class PowerManagerService extends SystemService
    /** Get wake lock summary flags that correspond to the given wake lock. */
    @SuppressWarnings("deprecation")
    private int getWakeLockSummaryFlags(WakeLock wakeLock) {
        if (wakeLock.mDisabled) {
            // We only respect this if the wake lock is not disabled.
            return 0;
        }
        switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
            case PowerManager.PARTIAL_WAKE_LOCK:
                if (!wakeLock.mDisabled) {
                    // We only respect this if the wake lock is not disabled.
                return WAKE_LOCK_CPU;
                }
                break;
            case PowerManager.FULL_WAKE_LOCK:
                return WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
@@ -4151,7 +4175,7 @@ public final class PowerManagerService extends SystemService
        for (int i = 0; i < numWakeLocks; i++) {
            final WakeLock wakeLock = mWakeLocks.get(i);
            if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                    == PowerManager.PARTIAL_WAKE_LOCK) {
                    == PowerManager.PARTIAL_WAKE_LOCK || isScreenLock(wakeLock)) {
                if (setWakeLockDisabledStateLocked(wakeLock)) {
                    changed = true;
                    if (wakeLock.mDisabled) {
@@ -4205,6 +4229,22 @@ public final class PowerManagerService extends SystemService
                }
            }
            return wakeLock.setDisabled(disabled);
        } else if (mDisableScreenWakeLocksWhileCached && isScreenLock(wakeLock)) {
            boolean disabled = false;
            final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
            final UidState state = wakeLock.mUidState;
            // Cached inactive processes are never allowed to hold wake locks.
            if (mConstants.NO_CACHED_WAKE_LOCKS
                    && appid >= Process.FIRST_APPLICATION_UID
                    && !state.mActive
                    && state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
                    && state.mProcState >= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
                if (DEBUG_SPEW) {
                    Slog.d(TAG, "disabling full wakelock " + wakeLock);
                }
                disabled = true;
            }
            return wakeLock.setDisabled(disabled);
        }
        return false;
    }
+203 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.power;

import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING;
import static android.os.PowerManager.USER_ACTIVITY_EVENT_BUTTON;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -78,6 +80,7 @@ import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.UserHandle;
import android.os.test.TestLooper;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.sysprop.PowerProperties;
@@ -91,6 +94,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.PowerManagerService.BatteryReceiver;
@@ -159,6 +163,7 @@ public class PowerManagerServiceTest {
    @Mock private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
    @Mock private PowerManagerService.PermissionCheckerWrapper mPermissionCheckerWrapperMock;
    @Mock private PowerManagerService.PowerPropertiesWrapper mPowerPropertiesWrapper;
    @Mock private DeviceConfigParameterProvider mDeviceParameterProvider;

    @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();

@@ -340,6 +345,11 @@ public class PowerManagerServiceTest {
            PowerManagerService.PowerPropertiesWrapper createPowerPropertiesWrapper() {
                return mPowerPropertiesWrapper;
            }

            @Override
            DeviceConfigParameterProvider createDeviceConfigParameterProvider() {
                return mDeviceParameterProvider;
            }
        });
        return mService;
    }
@@ -2680,4 +2690,197 @@ public class PowerManagerServiceTest {
        verify(mNotifierMock, never()).onUserActivity(anyInt(),  anyInt(), anyInt());
    }

    @Test
    public void testFeatureEnabledProcStateUncachedToCached_fullWakeLockDisabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);

        setCachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isTrue();
    }

    @Test
    public void testFeatureDisabledProcStateUncachedToCached_fullWakeLockEnabled() {
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);

        setCachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureEnabledProcStateUncachedToCached_screenBrightWakeLockDisabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);

        setCachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isTrue();
    }

    @Test
    public void testFeatureDisabledProcStateUncachedToCached_screenBrightWakeLockEnabled() {
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);

        setCachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureEnabledProcStateUncachedToCached_screenDimWakeLockDisabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
                PowerManager.SCREEN_DIM_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);

        setCachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isTrue();
    }

    @Test
    public void testFeatureDisabledProcStateUncachedToCached_screenDimWakeLockEnabled() {
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
                PowerManager.SCREEN_DIM_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);

        setCachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureEnabledProcStateCachedToUncached_fullWakeLockEnabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
        setCachedUidProcState(wakeLock.mOwnerUid);

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureDisabledProcStateCachedToUncached_fullWakeLockEnabled() {
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
        setCachedUidProcState(wakeLock.mOwnerUid);

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureEnabledProcStateCachedToUncached_screenBrightWakeLockEnabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
        setCachedUidProcState(wakeLock.mOwnerUid);

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureDisabledProcStateCachedToUncached_screenBrightWakeLockEnabled() {
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
        setCachedUidProcState(wakeLock.mOwnerUid);

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureEnabledProcStateCachedToUncached_screenDimWakeLockEnabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
                PowerManager.SCREEN_DIM_WAKE_LOCK);
        setCachedUidProcState(wakeLock.mOwnerUid);

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureDisabledProcStateCachedToUncached_screenDimWakeLockEnabled() {
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        createService();
        startSystem();
        WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
                PowerManager.SCREEN_DIM_WAKE_LOCK);
        setCachedUidProcState(wakeLock.mOwnerUid);

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    @Test
    public void testFeatureDynamicallyDisabledProcStateUncachedToCached_fullWakeLockEnabled() {
        doReturn(true).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        ArgumentCaptor<DeviceConfig.OnPropertiesChangedListener> listenerCaptor =
                ArgumentCaptor.forClass(DeviceConfig.OnPropertiesChangedListener.class);
        createService();
        startSystem();
        verify(mDeviceParameterProvider, times(1))
                .addOnPropertiesChangedListener(any(), listenerCaptor.capture());
        WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
        setUncachedUidProcState(wakeLock.mOwnerUid);
        // dynamically disable the feature
        doReturn(false).when(mDeviceParameterProvider)
                .isDisableScreenWakeLocksWhileCachedFeatureEnabled();
        listenerCaptor.getValue().onPropertiesChanged(
                new DeviceConfig.Properties("ignored_namespace", null));

        setUncachedUidProcState(wakeLock.mOwnerUid);
        assertThat(wakeLock.mDisabled).isFalse();
    }

    private void setCachedUidProcState(int uid) {
        mService.updateUidProcStateInternal(uid, PROCESS_STATE_TOP_SLEEPING);
    }

    private void setUncachedUidProcState(int uid) {
        mService.updateUidProcStateInternal(uid, PROCESS_STATE_RECEIVER);
    }
}