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

Commit abef289b authored by Philip Junker's avatar Philip Junker
Browse files

Require TURN_SCREEN_ON permission for ACQUIRE_CAUSES_WAKEUP flag.

Bug: 237045954
Test: atest PowerManagerServiceTest
Test: manually verified that app without permission can't turn screen on
Change-Id: I525f824c74be77b93e3035ec76ca26202a2ab637
parent 862f455d
Loading
Loading
Loading
Loading
+5 −46
Original line number Diff line number Diff line
@@ -42,8 +42,6 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.SynchronousUserSwitchObserver;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -64,7 +62,6 @@ import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.BatterySaverPolicyConfig;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
@@ -127,7 +124,6 @@ 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.compat.PlatformCompat;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
import com.android.server.policy.WindowManagerPolicy;
@@ -283,17 +279,6 @@ public final class PowerManagerService extends SystemService
     */
    private static final long ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS = 60 * 1000L;

    /**
     * Apps targeting Android U and above need to define
     * {@link android.Manifest.permission#TURN_SCREEN_ON} in their manifest for
     * {@link android.os.PowerManager#ACQUIRE_CAUSES_WAKEUP} to have any effect.
     * Note that most applications should use {@link android.R.attr#turnScreenOn} or
     * {@link android.app.Activity#setTurnScreenOn(boolean)} instead, as this prevents the
     * previous foreground app from being resumed first when the screen turns on.
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    public static final long REQUIRE_TURN_SCREEN_ON_PERMISSION = 216114297L;
    /** Reason ID for holding display suspend blocker. */
    private static final String HOLDING_DISPLAY_SUSPEND_BLOCKER = "holding display";

@@ -317,7 +302,6 @@ public final class PowerManagerService extends SystemService
    private final SystemPropertiesWrapper mSystemProperties;
    private final Clock mClock;
    private final Injector mInjector;
    private final PlatformCompat mPlatformCompat;

    private AppOpsManager mAppOpsManager;
    private LightsManager mLightsManager;
@@ -1005,11 +989,6 @@ public final class PowerManagerService extends SystemService
                public void set(String key, String val) {
                    SystemProperties.set(key, val);
                }

                @Override
                public boolean getBoolean(String key, boolean def) {
                    return SystemProperties.getBoolean(key, def);
                }
            };
        }

@@ -1046,10 +1025,6 @@ public final class PowerManagerService extends SystemService
        AppOpsManager createAppOpsManager(Context context) {
            return context.getSystemService(AppOpsManager.class);
        }

        PlatformCompat createPlatformCompat(Context context) {
            return context.getSystemService(PlatformCompat.class);
        }
    }

    final Constants mConstants;
@@ -1106,8 +1081,6 @@ public final class PowerManagerService extends SystemService

        mAppOpsManager = injector.createAppOpsManager(mContext);

        mPlatformCompat = injector.createPlatformCompat(mContext);

        mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();

        // Save brightness values:
@@ -1614,28 +1587,14 @@ public final class PowerManagerService extends SystemService
        }
        if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName)
                == AppOpsManager.MODE_ALLOWED) {
            if (mPlatformCompat.isChangeEnabledByPackageName(REQUIRE_TURN_SCREEN_ON_PERMISSION,
                    opPackageName, UserHandle.getUserId(opUid))) {
                if (mContext.checkCallingOrSelfPermission(
                        android.Manifest.permission.TURN_SCREEN_ON)
            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TURN_SCREEN_ON)
                    == PackageManager.PERMISSION_GRANTED) {
                    if (DEBUG_SPEW) {
                        Slog.d(TAG, "Allowing device wake-up from app " + opPackageName);
                    }
                    return true;
                }
            } else {
                // android.permission.TURN_SCREEN_ON has only been introduced in Android U, only
                // check for appOp for apps targeting lower SDK versions
                if (DEBUG_SPEW) {
                    Slog.d(TAG, "Allowing device wake-up from app with "
                            + "REQUIRE_TURN_SCREEN_ON_PERMISSION disabled " + opPackageName);
                }
                Slog.i(TAG, "Allowing device wake-up from app " + opPackageName);
                return true;
            }
        }
        if (PowerProperties.permissionless_turn_screen_on().orElse(true)) {
            Slog.d(TAG, "Device wake-up will be denied without android.permission.TURN_SCREEN_ON");
        if (PowerProperties.permissionless_turn_screen_on().orElse(false)) {
            Slog.d(TAG, "Device wake-up allowed by debug.power.permissionless_turn_screen_on");
            return true;
        }
        Slog.w(TAG, "Not allowing device wake-up for " + opPackageName);
+0 −15
Original line number Diff line number Diff line
@@ -48,19 +48,4 @@ interface SystemPropertiesWrapper {
     * SELinux. libc will log the underlying reason.
     */
    void set(@NonNull String key, @Nullable String val);

    /**
     * Get the value for the given {@code key}, returned as a boolean.
     * Values 'n', 'no', '0', 'false' or 'off' are considered false.
     * Values 'y', 'yes', '1', 'true' or 'on' are considered true.
     * (case sensitive).
     * If the key does not exist, or has any other value, then the default
     * result is returned.
     *
     * @param key the key to lookup
     * @param def a default value to return
     * @return the key parsed as a boolean, or def if the key isn't found or is
     *         not able to be parsed as a boolean.
     */
    boolean getBoolean(@NonNull String key, boolean def);
}
+2 −32
Original line number Diff line number Diff line
@@ -87,7 +87,6 @@ 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.compat.PlatformCompat;
import com.android.server.lights.LightsManager;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.PowerManagerService.BatteryReceiver;
@@ -147,7 +146,6 @@ public class PowerManagerServiceTest {
    @Mock private SystemPropertiesWrapper mSystemPropertiesMock;
    @Mock private AppOpsManager mAppOpsManagerMock;
    @Mock private LowPowerStandbyController mLowPowerStandbyControllerMock;
    @Mock private PlatformCompat mPlatformCompat;

    @Mock
    private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
@@ -321,11 +319,6 @@ public class PowerManagerServiceTest {
            AppOpsManager createAppOpsManager(Context context) {
                return mAppOpsManagerMock;
            }

            @Override
            PlatformCompat createPlatformCompat(Context context) {
                return mPlatformCompat;
            }
        });
        return mService;
    }
@@ -499,9 +492,6 @@ public class PowerManagerServiceTest {
        String packageName = "pkg.name";
        when(mAppOpsManagerMock.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON,
                Binder.getCallingUid(), packageName)).thenReturn(MODE_ALLOWED);
        when(mPlatformCompat.isChangeEnabledByPackageName(
                eq(PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION), anyString(),
                anyInt())).thenReturn(true);
        when(mContextSpy.checkCallingOrSelfPermission(
                android.Manifest.permission.TURN_SCREEN_ON)).thenReturn(
                PackageManager.PERMISSION_GRANTED);
@@ -526,23 +516,6 @@ public class PowerManagerServiceTest {
                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);

        // Verify that on older platforms only the appOp is necessary and the permission isn't
        // checked
        when(mPlatformCompat.isChangeEnabledByPackageName(
                eq(PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION), anyString(),
                anyInt())).thenReturn(false);
        when(mContextSpy.checkCallingOrSelfPermission(
                android.Manifest.permission.TURN_SCREEN_ON)).thenReturn(
                PackageManager.PERMISSION_DENIED);
        forceSleep();
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);

        flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
        mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
    }

    @Test
@@ -562,7 +535,7 @@ public class PowerManagerServiceTest {
        int flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
        mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
        if (PowerProperties.permissionless_turn_screen_on().orElse(true)) {
        if (PowerProperties.permissionless_turn_screen_on().orElse(false)) {
            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        } else {
            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
@@ -571,9 +544,6 @@ public class PowerManagerServiceTest {

        when(mAppOpsManagerMock.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON,
                Binder.getCallingUid(), packageName)).thenReturn(MODE_ALLOWED);
        when(mPlatformCompat.isChangeEnabledByPackageName(
                eq(PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION), anyString(),
                anyInt())).thenReturn(true);
        when(mContextSpy.checkCallingOrSelfPermission(
                android.Manifest.permission.TURN_SCREEN_ON)).thenReturn(
                PackageManager.PERMISSION_DENIED);
@@ -583,7 +553,7 @@ public class PowerManagerServiceTest {
        flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
        mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
        if (PowerProperties.permissionless_turn_screen_on().orElse(true)) {
        if (PowerProperties.permissionless_turn_screen_on().orElse(false)) {
            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        } else {
            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);