Loading services/core/java/com/android/server/devicestate/DeviceState.java +11 −1 Original line number Diff line number Diff line Loading @@ -64,10 +64,20 @@ public final class DeviceState { */ public static final int FLAG_EMULATED_ONLY = 1 << 2; /** * This flag indicates that the corresponding state should be automatically canceled when the * requesting app is no longer on top. The app is considered not on top when (1) the top * activity in the system is from a different app, (2) the device is in sleep mode, or * (3) the keyguard shows up. */ public static final int FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 1 << 3; /** @hide */ @IntDef(prefix = {"FLAG_"}, flag = true, value = { FLAG_CANCEL_OVERRIDE_REQUESTS, FLAG_APP_INACCESSIBLE FLAG_APP_INACCESSIBLE, FLAG_EMULATED_ONLY, FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP }) @Retention(RetentionPolicy.SOURCE) public @interface DeviceStateFlags {} Loading services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +65 −5 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskStackListener; import android.content.Context; import android.hardware.devicestate.DeviceStateInfo; import android.hardware.devicestate.DeviceStateManager; Loading Loading @@ -176,6 +177,12 @@ public final class DeviceStateManagerService extends SystemService { @NonNull private final SystemPropertySetter mSystemPropertySetter; @VisibleForTesting TaskStackListener mOverrideRequestTaskStackListener = new OverrideRequestTaskStackListener(); @VisibleForTesting ActivityTaskManagerInternal.ScreenObserver mOverrideRequestScreenObserver = new OverrideRequestScreenObserver(); public DeviceStateManagerService(@NonNull Context context) { this(context, DeviceStatePolicy.Provider .fromResources(context.getResources()) Loading Loading @@ -215,6 +222,9 @@ public final class DeviceStateManagerService extends SystemService { readStatesAvailableForRequestFromApps(); mFoldedDeviceStates = readFoldedStates(); } mActivityTaskManagerInternal.registerTaskStackListener(mOverrideRequestTaskStackListener); mActivityTaskManagerInternal.registerScreenObserver(mOverrideRequestScreenObserver); } @VisibleForTesting Loading Loading @@ -842,9 +852,7 @@ public final class DeviceStateManagerService extends SystemService { * @param state state that is being requested. */ private void assertCanRequestDeviceState(int callingPid, int state) { final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp(); if (topApp == null || topApp.getPid() != callingPid || !isStateAvailableForAppRequests(state)) { if (!isTopApp(callingPid) || !isStateAvailableForAppRequests(state)) { getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "Permission required to request device state, " + "or the call must come from the top app " Loading @@ -859,14 +867,18 @@ public final class DeviceStateManagerService extends SystemService { * @param callingPid Process ID that is requesting this state change */ private void assertCanControlDeviceState(int callingPid) { final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp(); if (topApp == null || topApp.getPid() != callingPid) { if (!isTopApp(callingPid)) { getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "Permission required to request device state, " + "or the call must come from the top app."); } } private boolean isTopApp(int callingPid) { final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp(); return topApp != null && topApp.getPid() == callingPid; } private boolean isStateAvailableForAppRequests(int state) { synchronized (mLock) { return mDeviceStatesAvailableForAppRequests.contains(state); Loading Loading @@ -1185,4 +1197,52 @@ public final class DeviceStateManagerService extends SystemService { } } } @GuardedBy("mLock") private boolean shouldCancelOverrideRequestWhenRequesterNotOnTop() { if (mActiveOverride.isEmpty()) { return false; } int identifier = mActiveOverride.get().getRequestedState(); DeviceState deviceState = mDeviceStates.get(identifier); return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP); } private class OverrideRequestTaskStackListener extends TaskStackListener { @Override public void onTaskStackChanged() throws RemoteException { synchronized (mLock) { if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) { return; } OverrideRequest request = mActiveOverride.get(); if (!isTopApp(request.getPid())) { mOverrideRequestController.cancelRequest(request); } } } } private class OverrideRequestScreenObserver implements ActivityTaskManagerInternal.ScreenObserver { @Override public void onAwakeStateChanged(boolean isAwake) { synchronized (mLock) { if (!isAwake && shouldCancelOverrideRequestWhenRequesterNotOnTop()) { mOverrideRequestController.cancelRequest(mActiveOverride.get()); } } } @Override public void onKeyguardStateChanged(boolean isShowing) { synchronized (mLock) { if (isShowing && shouldCancelOverrideRequestWhenRequesterNotOnTop()) { mOverrideRequestController.cancelRequest(mActiveOverride.get()); } } } } } services/core/java/com/android/server/policy/DeviceStateProviderImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,8 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider, private static final String FLAG_CANCEL_OVERRIDE_REQUESTS = "FLAG_CANCEL_OVERRIDE_REQUESTS"; private static final String FLAG_APP_INACCESSIBLE = "FLAG_APP_INACCESSIBLE"; private static final String FLAG_EMULATED_ONLY = "FLAG_EMULATED_ONLY"; private static final String FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = "FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP"; /** Interface that allows reading the device state configuration. */ interface ReadableConfig { Loading Loading @@ -152,6 +154,10 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider, break; case FLAG_EMULATED_ONLY: flags |= DeviceState.FLAG_EMULATED_ONLY; break; case FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP: flags |= DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP; break; default: Slog.w(TAG, "Parsed unknown flag with name: " + configFlagString); Loading services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.app.AppProtoEnums; import android.app.BackgroundStartPrivileges; import android.app.IActivityManager; import android.app.IApplicationThread; import android.app.ITaskStackListener; import android.app.ProfilerInfo; import android.content.ComponentName; import android.content.IIntentSender; Loading Loading @@ -740,4 +741,10 @@ public abstract class ActivityTaskManagerInternal { */ public abstract void restartTaskActivityProcessIfVisible( int taskId, @NonNull String packageName); /** Sets the task stack listener that gets callbacks when a task stack changes. */ public abstract void registerTaskStackListener(ITaskStackListener listener); /** Unregister a task stack listener so that it stops receiving callbacks. */; public abstract void unregisterTaskStackListener(ITaskStackListener listener); } services/core/java/com/android/server/wm/ActivityTaskManagerService.java +12 −0 Original line number Diff line number Diff line Loading @@ -6916,5 +6916,17 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { activity.restartProcessIfVisible(); } } /** Sets the task stack listener that gets callbacks when a task stack changes. */ @Override public void registerTaskStackListener(ITaskStackListener listener) { ActivityTaskManagerService.this.registerTaskStackListener(listener); } /** Unregister a task stack listener so that it stops receiving callbacks. */ @Override public void unregisterTaskStackListener(ITaskStackListener listener) { ActivityTaskManagerService.this.unregisterTaskStackListener(listener); } } } Loading
services/core/java/com/android/server/devicestate/DeviceState.java +11 −1 Original line number Diff line number Diff line Loading @@ -64,10 +64,20 @@ public final class DeviceState { */ public static final int FLAG_EMULATED_ONLY = 1 << 2; /** * This flag indicates that the corresponding state should be automatically canceled when the * requesting app is no longer on top. The app is considered not on top when (1) the top * activity in the system is from a different app, (2) the device is in sleep mode, or * (3) the keyguard shows up. */ public static final int FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 1 << 3; /** @hide */ @IntDef(prefix = {"FLAG_"}, flag = true, value = { FLAG_CANCEL_OVERRIDE_REQUESTS, FLAG_APP_INACCESSIBLE FLAG_APP_INACCESSIBLE, FLAG_EMULATED_ONLY, FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP }) @Retention(RetentionPolicy.SOURCE) public @interface DeviceStateFlags {} Loading
services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +65 −5 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskStackListener; import android.content.Context; import android.hardware.devicestate.DeviceStateInfo; import android.hardware.devicestate.DeviceStateManager; Loading Loading @@ -176,6 +177,12 @@ public final class DeviceStateManagerService extends SystemService { @NonNull private final SystemPropertySetter mSystemPropertySetter; @VisibleForTesting TaskStackListener mOverrideRequestTaskStackListener = new OverrideRequestTaskStackListener(); @VisibleForTesting ActivityTaskManagerInternal.ScreenObserver mOverrideRequestScreenObserver = new OverrideRequestScreenObserver(); public DeviceStateManagerService(@NonNull Context context) { this(context, DeviceStatePolicy.Provider .fromResources(context.getResources()) Loading Loading @@ -215,6 +222,9 @@ public final class DeviceStateManagerService extends SystemService { readStatesAvailableForRequestFromApps(); mFoldedDeviceStates = readFoldedStates(); } mActivityTaskManagerInternal.registerTaskStackListener(mOverrideRequestTaskStackListener); mActivityTaskManagerInternal.registerScreenObserver(mOverrideRequestScreenObserver); } @VisibleForTesting Loading Loading @@ -842,9 +852,7 @@ public final class DeviceStateManagerService extends SystemService { * @param state state that is being requested. */ private void assertCanRequestDeviceState(int callingPid, int state) { final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp(); if (topApp == null || topApp.getPid() != callingPid || !isStateAvailableForAppRequests(state)) { if (!isTopApp(callingPid) || !isStateAvailableForAppRequests(state)) { getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "Permission required to request device state, " + "or the call must come from the top app " Loading @@ -859,14 +867,18 @@ public final class DeviceStateManagerService extends SystemService { * @param callingPid Process ID that is requesting this state change */ private void assertCanControlDeviceState(int callingPid) { final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp(); if (topApp == null || topApp.getPid() != callingPid) { if (!isTopApp(callingPid)) { getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE, "Permission required to request device state, " + "or the call must come from the top app."); } } private boolean isTopApp(int callingPid) { final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp(); return topApp != null && topApp.getPid() == callingPid; } private boolean isStateAvailableForAppRequests(int state) { synchronized (mLock) { return mDeviceStatesAvailableForAppRequests.contains(state); Loading Loading @@ -1185,4 +1197,52 @@ public final class DeviceStateManagerService extends SystemService { } } } @GuardedBy("mLock") private boolean shouldCancelOverrideRequestWhenRequesterNotOnTop() { if (mActiveOverride.isEmpty()) { return false; } int identifier = mActiveOverride.get().getRequestedState(); DeviceState deviceState = mDeviceStates.get(identifier); return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP); } private class OverrideRequestTaskStackListener extends TaskStackListener { @Override public void onTaskStackChanged() throws RemoteException { synchronized (mLock) { if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) { return; } OverrideRequest request = mActiveOverride.get(); if (!isTopApp(request.getPid())) { mOverrideRequestController.cancelRequest(request); } } } } private class OverrideRequestScreenObserver implements ActivityTaskManagerInternal.ScreenObserver { @Override public void onAwakeStateChanged(boolean isAwake) { synchronized (mLock) { if (!isAwake && shouldCancelOverrideRequestWhenRequesterNotOnTop()) { mOverrideRequestController.cancelRequest(mActiveOverride.get()); } } } @Override public void onKeyguardStateChanged(boolean isShowing) { synchronized (mLock) { if (isShowing && shouldCancelOverrideRequestWhenRequesterNotOnTop()) { mOverrideRequestController.cancelRequest(mActiveOverride.get()); } } } } }
services/core/java/com/android/server/policy/DeviceStateProviderImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,8 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider, private static final String FLAG_CANCEL_OVERRIDE_REQUESTS = "FLAG_CANCEL_OVERRIDE_REQUESTS"; private static final String FLAG_APP_INACCESSIBLE = "FLAG_APP_INACCESSIBLE"; private static final String FLAG_EMULATED_ONLY = "FLAG_EMULATED_ONLY"; private static final String FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = "FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP"; /** Interface that allows reading the device state configuration. */ interface ReadableConfig { Loading Loading @@ -152,6 +154,10 @@ public final class DeviceStateProviderImpl implements DeviceStateProvider, break; case FLAG_EMULATED_ONLY: flags |= DeviceState.FLAG_EMULATED_ONLY; break; case FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP: flags |= DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP; break; default: Slog.w(TAG, "Parsed unknown flag with name: " + configFlagString); Loading
services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.app.AppProtoEnums; import android.app.BackgroundStartPrivileges; import android.app.IActivityManager; import android.app.IApplicationThread; import android.app.ITaskStackListener; import android.app.ProfilerInfo; import android.content.ComponentName; import android.content.IIntentSender; Loading Loading @@ -740,4 +741,10 @@ public abstract class ActivityTaskManagerInternal { */ public abstract void restartTaskActivityProcessIfVisible( int taskId, @NonNull String packageName); /** Sets the task stack listener that gets callbacks when a task stack changes. */ public abstract void registerTaskStackListener(ITaskStackListener listener); /** Unregister a task stack listener so that it stops receiving callbacks. */; public abstract void unregisterTaskStackListener(ITaskStackListener listener); }
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +12 −0 Original line number Diff line number Diff line Loading @@ -6916,5 +6916,17 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { activity.restartProcessIfVisible(); } } /** Sets the task stack listener that gets callbacks when a task stack changes. */ @Override public void registerTaskStackListener(ITaskStackListener listener) { ActivityTaskManagerService.this.registerTaskStackListener(listener); } /** Unregister a task stack listener so that it stops receiving callbacks. */ @Override public void unregisterTaskStackListener(ITaskStackListener listener) { ActivityTaskManagerService.this.unregisterTaskStackListener(listener); } } }