summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandlerTest.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt189
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt4
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java4
-rw-r--r--services/core/java/com/android/server/am/ProcessServiceRecord.java3
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java23
16 files changed, 382 insertions, 65 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 6d14440c9b18..f8d7b6bc3aad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -202,17 +202,18 @@ class DesktopTasksController(
}
/**
- * Moves a single task to freeform and sets the taskBounds to the passed in bounds,
- * startBounds
+ * The first part of the animated move to desktop transition. Applies the changes to move task
+ * to desktop mode and sets the taskBounds to the passed in bounds, startBounds. This is
+ * followed with a call to {@link finishMoveToDesktop} or {@link cancelMoveToDesktop}.
*/
- fun moveToFreeform(
+ fun startMoveToDesktop(
taskInfo: RunningTaskInfo,
startBounds: Rect,
dragToDesktopValueAnimator: MoveToDesktopAnimator
) {
KtProtoLog.v(
WM_SHELL_DESKTOP_MODE,
- "DesktopTasksController: moveToFreeform with bounds taskId=%d",
+ "DesktopTasksController: startMoveToDesktop taskId=%d",
taskInfo.taskId
)
val wct = WindowContainerTransaction()
@@ -221,18 +222,21 @@ class DesktopTasksController(
wct.setBounds(taskInfo.token, startBounds)
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- enterDesktopTaskTransitionHandler.startMoveToFreeformAnimation(wct,
- dragToDesktopValueAnimator, mOnAnimationFinishedCallback)
+ enterDesktopTaskTransitionHandler.startMoveToDesktop(wct, dragToDesktopValueAnimator,
+ mOnAnimationFinishedCallback)
} else {
shellTaskOrganizer.applyTransaction(wct)
}
}
- /** Brings apps to front and sets freeform task bounds */
- private fun moveToDesktopWithAnimation(taskInfo: RunningTaskInfo, freeformBounds: Rect) {
+ /**
+ * The second part of the animated move to desktop transition, called after
+ * {@link startMoveToDesktop}. Brings apps to front and sets freeform task bounds.
+ */
+ private fun finalizeMoveToDesktop(taskInfo: RunningTaskInfo, freeformBounds: Rect) {
KtProtoLog.v(
WM_SHELL_DESKTOP_MODE,
- "DesktopTasksController: moveToDesktop with animation taskId=%d",
+ "DesktopTasksController: finalizeMoveToDesktop taskId=%d",
taskInfo.taskId
)
val wct = WindowContainerTransaction()
@@ -241,8 +245,8 @@ class DesktopTasksController(
wct.setBounds(taskInfo.token, freeformBounds)
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- enterDesktopTaskTransitionHandler.startTransition(
- Transitions.TRANSIT_ENTER_DESKTOP_MODE, wct, mOnAnimationFinishedCallback)
+ enterDesktopTaskTransitionHandler.finalizeMoveToDesktop(wct,
+ mOnAnimationFinishedCallback)
} else {
shellTaskOrganizer.applyTransaction(wct)
releaseVisualIndicator()
@@ -272,13 +276,14 @@ class DesktopTasksController(
}
/**
- * Move a task to fullscreen after being dragged from fullscreen and released back into
- * status bar area
+ * The second part of the animated move to desktop transition, called after
+ * {@link startMoveToDesktop}. Move a task to fullscreen after being dragged from fullscreen
+ * and released back into status bar area.
*/
- fun cancelMoveToFreeform(task: RunningTaskInfo, moveToDesktopAnimator: MoveToDesktopAnimator) {
+ fun cancelMoveToDesktop(task: RunningTaskInfo, moveToDesktopAnimator: MoveToDesktopAnimator) {
KtProtoLog.v(
WM_SHELL_DESKTOP_MODE,
- "DesktopTasksController: cancelMoveToFreeform taskId=%d",
+ "DesktopTasksController: cancelMoveToDesktop taskId=%d",
task.taskId
)
val wct = WindowContainerTransaction()
@@ -784,7 +789,7 @@ class DesktopTasksController(
taskInfo: RunningTaskInfo,
freeformBounds: Rect
) {
- moveToDesktopWithAnimation(taskInfo, freeformBounds)
+ finalizeMoveToDesktop(taskInfo, freeformBounds)
}
private fun getStatusBarHeight(taskInfo: RunningTaskInfo): Int {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
index 650cac5cb999..1acf783257f2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandler.java
@@ -79,7 +79,7 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
* @param wct WindowContainerTransaction for transition
* @param onAnimationEndCallback to be called after animation
*/
- public void startTransition(@WindowManager.TransitionType int type,
+ private void startTransition(@WindowManager.TransitionType int type,
@NonNull WindowContainerTransaction wct,
Consumer<SurfaceControl.Transaction> onAnimationEndCallback) {
mOnAnimationFinishedCallback = onAnimationEndCallback;
@@ -88,17 +88,29 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
}
/**
- * Starts Transition of type TRANSIT_ENTER_FREEFORM
+ * Starts Transition of type TRANSIT_START_MOVE_TO_DESKTOP_MODE
* @param wct WindowContainerTransaction for transition
* @param moveToDesktopAnimator Animator that shrinks and positions task during two part move
* to desktop animation
* @param onAnimationEndCallback to be called after animation
*/
- public void startMoveToFreeformAnimation(@NonNull WindowContainerTransaction wct,
+ public void startMoveToDesktop(@NonNull WindowContainerTransaction wct,
@NonNull MoveToDesktopAnimator moveToDesktopAnimator,
Consumer<SurfaceControl.Transaction> onAnimationEndCallback) {
mMoveToDesktopAnimator = moveToDesktopAnimator;
- startTransition(Transitions.TRANSIT_ENTER_FREEFORM, wct, onAnimationEndCallback);
+ startTransition(Transitions.TRANSIT_START_MOVE_TO_DESKTOP_MODE, wct,
+ onAnimationEndCallback);
+ }
+
+ /**
+ * Starts Transition of type TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE
+ * @param wct WindowContainerTransaction for transition
+ * @param onAnimationEndCallback to be called after animation
+ */
+ public void finalizeMoveToDesktop(@NonNull WindowContainerTransaction wct,
+ Consumer<SurfaceControl.Transaction> onAnimationEndCallback) {
+ startTransition(Transitions.TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE, wct,
+ onAnimationEndCallback);
}
/**
@@ -155,7 +167,7 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
}
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (type == Transitions.TRANSIT_ENTER_FREEFORM
+ if (type == Transitions.TRANSIT_START_MOVE_TO_DESKTOP_MODE
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
// Transitioning to freeform but keeping fullscreen bounds, so the crop is set
// to null and we don't require an animation
@@ -182,7 +194,7 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
}
Rect endBounds = change.getEndAbsBounds();
- if (type == Transitions.TRANSIT_ENTER_DESKTOP_MODE
+ if (type == Transitions.TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
&& !endBounds.isEmpty()) {
// This Transition animates a task to freeform bounds after being dragged into freeform
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 75659960bc32..4ca383f66267 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -149,11 +149,13 @@ public class Transitions implements RemoteCallable<Transitions>,
/** Transition type for maximize to freeform transition. */
public static final int TRANSIT_RESTORE_FROM_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 9;
- /** Transition type to freeform in desktop mode. */
- public static final int TRANSIT_ENTER_FREEFORM = WindowManager.TRANSIT_FIRST_CUSTOM + 10;
+ /** Transition type for starting the move to desktop mode. */
+ public static final int TRANSIT_START_MOVE_TO_DESKTOP_MODE =
+ WindowManager.TRANSIT_FIRST_CUSTOM + 10;
- /** Transition type to freeform in desktop mode. */
- public static final int TRANSIT_ENTER_DESKTOP_MODE = WindowManager.TRANSIT_FIRST_CUSTOM + 11;
+ /** Transition type for finalizing the move to desktop mode. */
+ public static final int TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE =
+ WindowManager.TRANSIT_FIRST_CUSTOM + 11;
/** Transition type to fullscreen from desktop mode. */
public static final int TRANSIT_EXIT_DESKTOP_MODE = WindowManager.TRANSIT_FIRST_CUSTOM + 12;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 1a18fc2d7546..80cf96a93efa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -197,7 +197,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change) {
if (change.getMode() == WindowManager.TRANSIT_CHANGE
- && (info.getType() == Transitions.TRANSIT_ENTER_DESKTOP_MODE
+ && (info.getType() == Transitions.TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE
|| info.getType() == Transitions.TRANSIT_CANCEL_ENTERING_DESKTOP_MODE
|| info.getType() == Transitions.TRANSIT_EXIT_DESKTOP_MODE
|| info.getType() == Transitions.TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE)) {
@@ -616,7 +616,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
} else if (mMoveToDesktopAnimator != null) {
relevantDecor.incrementRelayoutBlock();
mDesktopTasksController.ifPresent(
- c -> c.cancelMoveToFreeform(relevantDecor.mTaskInfo,
+ c -> c.cancelMoveToDesktop(relevantDecor.mTaskInfo,
mMoveToDesktopAnimator));
mMoveToDesktopAnimator = null;
return;
@@ -643,7 +643,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mDragToDesktopAnimationStartBounds, relevantDecor.mTaskInfo,
relevantDecor.mTaskSurface);
mDesktopTasksController.ifPresent(
- c -> c.moveToFreeform(relevantDecor.mTaskInfo,
+ c -> c.startMoveToDesktop(relevantDecor.mTaskInfo,
mDragToDesktopAnimationStartBounds,
mMoveToDesktopAnimator));
mMoveToDesktopAnimator.startAnimation();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandlerTest.java
index c6642f3472f0..885ae3851c6d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/EnterDesktopTaskTransitionHandlerTest.java
@@ -99,16 +99,17 @@ public class EnterDesktopTaskTransitionHandlerTest {
final int taskId = 1;
WindowContainerTransaction wct = new WindowContainerTransaction();
doReturn(mToken).when(mTransitions)
- .startTransition(Transitions.TRANSIT_ENTER_FREEFORM, wct,
+ .startTransition(Transitions.TRANSIT_START_MOVE_TO_DESKTOP_MODE, wct,
mEnterDesktopTaskTransitionHandler);
doReturn(taskId).when(mMoveToDesktopAnimator).getTaskId();
- mEnterDesktopTaskTransitionHandler.startMoveToFreeformAnimation(wct,
+ mEnterDesktopTaskTransitionHandler.startMoveToDesktop(wct,
mMoveToDesktopAnimator, null);
TransitionInfo.Change change =
createChange(WindowManager.TRANSIT_CHANGE, taskId, WINDOWING_MODE_FREEFORM);
- TransitionInfo info = createTransitionInfo(Transitions.TRANSIT_ENTER_FREEFORM, change);
+ TransitionInfo info = createTransitionInfo(Transitions.TRANSIT_START_MOVE_TO_DESKTOP_MODE,
+ change);
assertTrue(mEnterDesktopTaskTransitionHandler
@@ -120,17 +121,18 @@ public class EnterDesktopTaskTransitionHandlerTest {
@Test
public void testTransitEnterDesktopModeAnimation() throws Throwable {
- final int transitionType = Transitions.TRANSIT_ENTER_DESKTOP_MODE;
+ final int transitionType = Transitions.TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE;
final int taskId = 1;
WindowContainerTransaction wct = new WindowContainerTransaction();
doReturn(mToken).when(mTransitions)
.startTransition(transitionType, wct, mEnterDesktopTaskTransitionHandler);
- mEnterDesktopTaskTransitionHandler.startTransition(transitionType, wct, null);
+ mEnterDesktopTaskTransitionHandler.finalizeMoveToDesktop(wct, null);
TransitionInfo.Change change =
createChange(WindowManager.TRANSIT_CHANGE, taskId, WINDOWING_MODE_FREEFORM);
change.setEndAbsBounds(new Rect(0, 0, 1, 1));
- TransitionInfo info = createTransitionInfo(Transitions.TRANSIT_ENTER_DESKTOP_MODE, change);
+ TransitionInfo info = createTransitionInfo(
+ Transitions.TRANSIT_FINALIZE_MOVE_TO_DESKTOP_MODE, change);
runOnUiThread(() -> {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
index eb1ca66f6ca8..809edc09070a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
@@ -70,6 +70,19 @@ constructor(
}
}
+ /**
+ * Wakes up the device if dreaming with a screensaver.
+ *
+ * @param why a string explaining why we're waking the device for debugging purposes. Should be
+ * in SCREAMING_SNAKE_CASE.
+ * @param wakeReason the PowerManager-based reason why we're waking the device.
+ */
+ fun wakeUpIfDreaming(why: String, @PowerManager.WakeReason wakeReason: Int) {
+ if (statusBarStateController.isDreaming) {
+ repository.wakeUp(why, wakeReason)
+ }
+ }
+
companion object {
private const val FSI_WAKE_WHY = "full_screen_intent"
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt
new file mode 100644
index 000000000000..45fc68a793bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.systemui.shade
+
+import android.os.PowerManager
+import android.view.GestureDetector
+import android.view.MotionEvent
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.statusbar.StatusBarState
+import javax.inject.Inject
+
+/**
+ * This gestureListener will wake up by tap when the device is dreaming but not dozing, and the
+ * selected screensaver is hosted in lockscreen. Tap is gated by the falsing manager.
+ *
+ * Touches go through the [NotificationShadeWindowViewController].
+ */
+@SysUISingleton
+class LockscreenHostedDreamGestureListener
+@Inject
+constructor(
+ private val falsingManager: FalsingManager,
+ private val powerInteractor: PowerInteractor,
+ private val statusBarStateController: StatusBarStateController,
+ private val primaryBouncerInteractor: PrimaryBouncerInteractor,
+ private val keyguardRepository: KeyguardRepository,
+ private val shadeLogger: ShadeLogger,
+) : GestureDetector.SimpleOnGestureListener() {
+ private val TAG = this::class.simpleName
+
+ override fun onSingleTapUp(e: MotionEvent): Boolean {
+ if (shouldHandleMotionEvent()) {
+ if (!falsingManager.isFalseTap(LOW_PENALTY)) {
+ shadeLogger.d("$TAG#onSingleTapUp tap handled, requesting wakeUpIfDreaming")
+ powerInteractor.wakeUpIfDreaming(
+ "DREAMING_SINGLE_TAP",
+ PowerManager.WAKE_REASON_TAP
+ )
+ } else {
+ shadeLogger.d("$TAG#onSingleTapUp false tap ignored")
+ }
+ return true
+ }
+ return false
+ }
+
+ private fun shouldHandleMotionEvent(): Boolean {
+ return keyguardRepository.isActiveDreamLockscreenHosted.value &&
+ statusBarStateController.state == StatusBarState.KEYGUARD &&
+ !primaryBouncerInteractor.isBouncerShowing()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index f6db9e434610..108ea68ae8e0 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -16,6 +16,7 @@
package com.android.systemui.shade;
+import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
import static com.android.systemui.flags.Flags.TRACKPAD_GESTURE_COMMON;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -102,9 +103,12 @@ public class NotificationShadeWindowViewController {
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final AmbientState mAmbientState;
private final PulsingGestureListener mPulsingGestureListener;
+ private final LockscreenHostedDreamGestureListener mLockscreenHostedDreamGestureListener;
private final NotificationInsetsController mNotificationInsetsController;
private final boolean mIsTrackpadCommonEnabled;
+ private final FeatureFlags mFeatureFlags;
private GestureDetector mPulsingWakeupGestureHandler;
+ private GestureDetector mDreamingWakeupGestureHandler;
private View mBrightnessMirror;
private boolean mTouchActive;
private boolean mTouchCancelled;
@@ -156,6 +160,7 @@ public class NotificationShadeWindowViewController {
NotificationInsetsController notificationInsetsController,
AmbientState ambientState,
PulsingGestureListener pulsingGestureListener,
+ LockscreenHostedDreamGestureListener lockscreenHostedDreamGestureListener,
KeyguardBouncerViewModel keyguardBouncerViewModel,
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
@@ -187,8 +192,10 @@ public class NotificationShadeWindowViewController {
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mAmbientState = ambientState;
mPulsingGestureListener = pulsingGestureListener;
+ mLockscreenHostedDreamGestureListener = lockscreenHostedDreamGestureListener;
mNotificationInsetsController = notificationInsetsController;
mIsTrackpadCommonEnabled = featureFlags.isEnabled(TRACKPAD_GESTURE_COMMON);
+ mFeatureFlags = featureFlags;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -237,7 +244,10 @@ public class NotificationShadeWindowViewController {
mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
mPulsingWakeupGestureHandler = new GestureDetector(mView.getContext(),
mPulsingGestureListener);
-
+ if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) {
+ mDreamingWakeupGestureHandler = new GestureDetector(mView.getContext(),
+ mLockscreenHostedDreamGestureListener);
+ }
mView.setLayoutInsetsController(mNotificationInsetsController);
mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() {
@Override
@@ -291,6 +301,10 @@ public class NotificationShadeWindowViewController {
mFalsingCollector.onTouchEvent(ev);
mPulsingWakeupGestureHandler.onTouchEvent(ev);
+ if (mDreamingWakeupGestureHandler != null
+ && mDreamingWakeupGestureHandler.onTouchEvent(ev)) {
+ return true;
+ }
if (mStatusBarKeyguardViewManager.dispatchTouchEvent(ev)) {
return true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
index 45bb9313264c..435a1f1327d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
@@ -182,6 +182,32 @@ class PowerInteractorTest : SysuiTestCase() {
assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_APPLICATION)
}
+ @Test
+ fun wakeUpIfDreaming_dreaming_woken() {
+ // GIVEN device is dreaming
+ whenever(statusBarStateController.isDreaming).thenReturn(true)
+
+ // WHEN wakeUpIfDreaming is called
+ underTest.wakeUpIfDreaming("testReason", PowerManager.WAKE_REASON_GESTURE)
+
+ // THEN device is woken up
+ assertThat(repository.lastWakeWhy).isEqualTo("testReason")
+ assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_GESTURE)
+ }
+
+ @Test
+ fun wakeUpIfDreaming_notDreaming_notWoken() {
+ // GIVEN device is not dreaming
+ whenever(statusBarStateController.isDreaming).thenReturn(false)
+
+ // WHEN wakeUpIfDreaming is called
+ underTest.wakeUpIfDreaming("why", PowerManager.WAKE_REASON_TAP)
+
+ // THEN device is not woken
+ assertThat(repository.lastWakeWhy).isNull()
+ assertThat(repository.lastWakeReason).isNull()
+ }
+
companion object {
private val IMMEDIATE = Dispatchers.Main.immediate
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
new file mode 100644
index 000000000000..24d62fba8471
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
@@ -0,0 +1,189 @@
+/*
+ * 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.systemui.shade
+
+import android.os.PowerManager
+import android.testing.AndroidTestingRunner
+import android.view.MotionEvent
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.power.data.repository.FakePowerRepository
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidTestingRunner::class)
+class LockscreenHostedDreamGestureListenerTest : SysuiTestCase() {
+ @Mock private lateinit var falsingManager: FalsingManager
+ @Mock private lateinit var falsingCollector: FalsingCollector
+ @Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var shadeLogger: ShadeLogger
+ @Mock private lateinit var screenOffAnimationController: ScreenOffAnimationController
+ @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ private lateinit var powerRepository: FakePowerRepository
+ private lateinit var keyguardRepository: FakeKeyguardRepository
+ private lateinit var underTest: LockscreenHostedDreamGestureListener
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ powerRepository = FakePowerRepository()
+ keyguardRepository = FakeKeyguardRepository()
+
+ underTest =
+ LockscreenHostedDreamGestureListener(
+ falsingManager,
+ PowerInteractor(
+ powerRepository,
+ keyguardRepository,
+ falsingCollector,
+ screenOffAnimationController,
+ statusBarStateController,
+ ),
+ statusBarStateController,
+ primaryBouncerInteractor,
+ keyguardRepository,
+ shadeLogger,
+ )
+ whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+ whenever(primaryBouncerInteractor.isBouncerShowing()).thenReturn(false)
+ }
+
+ @Test
+ fun testGestureDetector_onSingleTap_whileDreaming() =
+ testScope.runTest {
+ // GIVEN device dreaming and the dream is hosted in lockscreen
+ whenever(statusBarStateController.isDreaming).thenReturn(true)
+ keyguardRepository.setIsActiveDreamLockscreenHosted(true)
+ testScope.runCurrent()
+
+ // GIVEN the falsing manager does NOT think the tap is a false tap
+ whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(false)
+
+ // WHEN there's a tap
+ underTest.onSingleTapUp(upEv)
+
+ // THEN wake up device if dreaming
+ Truth.assertThat(powerRepository.lastWakeWhy).isNotNull()
+ Truth.assertThat(powerRepository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_TAP)
+ }
+
+ @Test
+ fun testGestureDetector_onSingleTap_notOnKeyguard() =
+ testScope.runTest {
+ // GIVEN device dreaming and the dream is hosted in lockscreen
+ whenever(statusBarStateController.isDreaming).thenReturn(true)
+ keyguardRepository.setIsActiveDreamLockscreenHosted(true)
+ testScope.runCurrent()
+
+ // GIVEN shade is open
+ whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
+
+ // GIVEN the falsing manager does NOT think the tap is a false tap
+ whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(false)
+
+ // WHEN there's a tap
+ underTest.onSingleTapUp(upEv)
+
+ // THEN the falsing manager never gets a call
+ verify(falsingManager, never()).isFalseTap(ArgumentMatchers.anyInt())
+ }
+
+ @Test
+ fun testGestureDetector_onSingleTap_bouncerShown() =
+ testScope.runTest {
+ // GIVEN device dreaming and the dream is hosted in lockscreen
+ whenever(statusBarStateController.isDreaming).thenReturn(true)
+ keyguardRepository.setIsActiveDreamLockscreenHosted(true)
+ testScope.runCurrent()
+
+ // GIVEN bouncer is expanded
+ whenever(primaryBouncerInteractor.isBouncerShowing()).thenReturn(true)
+
+ // GIVEN the falsing manager does NOT think the tap is a false tap
+ whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(false)
+
+ // WHEN there's a tap
+ underTest.onSingleTapUp(upEv)
+
+ // THEN the falsing manager never gets a call
+ verify(falsingManager, never()).isFalseTap(ArgumentMatchers.anyInt())
+ }
+
+ @Test
+ fun testGestureDetector_onSingleTap_falsing() =
+ testScope.runTest {
+ // GIVEN device dreaming and the dream is hosted in lockscreen
+ whenever(statusBarStateController.isDreaming).thenReturn(true)
+ keyguardRepository.setIsActiveDreamLockscreenHosted(true)
+ testScope.runCurrent()
+
+ // GIVEN the falsing manager thinks the tap is a false tap
+ whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(true)
+
+ // WHEN there's a tap
+ underTest.onSingleTapUp(upEv)
+
+ // THEN the device doesn't wake up
+ Truth.assertThat(powerRepository.lastWakeWhy).isNull()
+ Truth.assertThat(powerRepository.lastWakeReason).isNull()
+ }
+
+ @Test
+ fun testSingleTap_notDreaming_noFalsingCheck() =
+ testScope.runTest {
+ // GIVEN device not dreaming with lockscreen hosted dream
+ whenever(statusBarStateController.isDreaming).thenReturn(false)
+ keyguardRepository.setIsActiveDreamLockscreenHosted(false)
+ testScope.runCurrent()
+
+ // WHEN there's a tap
+ underTest.onSingleTapUp(upEv)
+
+ // THEN the falsing manager never gets a call
+ verify(falsingManager, never()).isFalseTap(ArgumentMatchers.anyInt())
+ }
+}
+
+private val upEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 5fb3a7955b5c..2a398c55560c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -111,6 +111,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Mock private lateinit var lockIconViewController: LockIconViewController
@Mock private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
@Mock private lateinit var pulsingGestureListener: PulsingGestureListener
+ @Mock
+ private lateinit var mLockscreenHostedDreamGestureListener: LockscreenHostedDreamGestureListener
@Mock private lateinit var notificationInsetsController: NotificationInsetsController
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
@@ -147,6 +149,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
featureFlags.set(Flags.DUAL_SHADE, false)
featureFlags.set(Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
+ featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
val inputProxy = MultiShadeInputProxy()
testScope = TestScope()
@@ -183,6 +186,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
notificationInsetsController,
ambientState,
pulsingGestureListener,
+ mLockscreenHostedDreamGestureListener,
keyguardBouncerViewModel,
keyguardBouncerComponentFactory,
mock(KeyguardMessageAreaController.Factory::class.java),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 544137e95779..d9eb9b9166b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -113,6 +113,8 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
@Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
@Mock private lateinit var ambientState: AmbientState
@Mock private lateinit var pulsingGestureListener: PulsingGestureListener
+ @Mock
+ private lateinit var mLockscreenHostedDreamGestureListener: LockscreenHostedDreamGestureListener
@Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
@Mock private lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
@Mock private lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
@@ -161,6 +163,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
featureFlags.set(Flags.DUAL_SHADE, false)
featureFlags.set(Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
+ featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
val inputProxy = MultiShadeInputProxy()
testScope = TestScope()
val multiShadeInteractor =
@@ -196,6 +199,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
notificationInsetsController,
ambientState,
pulsingGestureListener,
+ mLockscreenHostedDreamGestureListener,
keyguardBouncerViewModel,
keyguardBouncerComponentFactory,
Mockito.mock(KeyguardMessageAreaController.Factory::class.java),
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 502e0ecac6fb..7d46c0cd075f 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3701,9 +3701,7 @@ public final class ActiveServices {
}
clientPsr.addConnection(c);
c.startAssociationIfNeeded();
- // Don't set hasAboveClient if binding to self to prevent modifyRawOomAdj() from
- // dropping the process' adjustment level.
- if (b.client != s.app && c.hasFlag(Context.BIND_ABOVE_CLIENT)) {
+ if (c.hasFlag(Context.BIND_ABOVE_CLIENT)) {
clientPsr.setHasAboveClient(true);
}
if (c.hasFlag(BIND_ALLOW_WHITELIST_MANAGEMENT)) {
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 7ff6d116baaf..81d0b6ac700b 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -341,8 +341,7 @@ final class ProcessServiceRecord {
mHasAboveClient = false;
for (int i = mConnections.size() - 1; i >= 0; i--) {
ConnectionRecord cr = mConnections.valueAt(i);
- if (cr.binding.service.app.mServices != this
- && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) {
+ if (cr.hasFlag(Context.BIND_ABOVE_CLIENT)) {
mHasAboveClient = true;
break;
}
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 27329e20bc8d..6821c40ec5d3 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -16244,7 +16244,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
NP = in.readInt();
- if (NP > 1000) {
+ if (NP > 10000) {
throw new ParcelFormatException("File corrupt: too many processes " + NP);
}
for (int ip = 0; ip < NP; ip++) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 1f4563fb2682..9545a8a4544b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -68,7 +68,6 @@ import static com.android.server.am.ProcessList.UNKNOWN_ADJ;
import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
@@ -2522,28 +2521,6 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
- public void testUpdateOomAdj_DoOne_AboveClient_SameProcess() {
- ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
- MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
- doReturn(app).when(sService).getTopApp();
- sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
- sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
-
- assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
-
- // Simulate binding to a service in the same process using BIND_ABOVE_CLIENT and
- // verify that its OOM adjustment level is unaffected.
- bindService(app, app, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
- app.mServices.updateHasAboveClientLocked();
- assertFalse(app.mServices.hasAboveClient());
-
- sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
- assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
- }
-
- @SuppressWarnings("GuardedBy")
- @Test
public void testUpdateOomAdj_DoAll_Side_Cycle() {
final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));