Skip to content

Commit 3066da9

Browse files
author
Android Build Coastguard Worker
committed
Snap for 9936701 from 0c50e33 to tm-qpr3-release
Change-Id: I96ae45ff634c092fa05b4b53b53172afeab6b739
2 parents 4d3f423 + 0c50e33 commit 3066da9

5 files changed

Lines changed: 90 additions & 18 deletions

File tree

packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ import androidx.annotation.VisibleForTesting
2424
import com.android.systemui.dagger.qualifiers.Application
2525
import com.android.systemui.dagger.qualifiers.Background
2626
import com.android.systemui.keyguard.data.repository.KeyguardRepository
27+
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
28+
import com.android.systemui.keyguard.shared.model.KeyguardState
29+
import com.android.systemui.keyguard.shared.model.TransitionState
30+
import com.android.systemui.keyguard.shared.model.TransitionStep
2731
import com.android.systemui.plugins.statusbar.StatusBarStateController
2832
import com.android.systemui.statusbar.StatusBarState
2933
import com.android.systemui.statusbar.expansionChanges
@@ -40,22 +44,26 @@ import com.android.systemui.statusbar.policy.HeadsUpManager
4044
import com.android.systemui.statusbar.policy.headsUpEvents
4145
import com.android.systemui.util.settings.SecureSettings
4246
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
43-
import javax.inject.Inject
44-
import kotlin.time.Duration
45-
import kotlin.time.Duration.Companion.seconds
4647
import kotlinx.coroutines.CoroutineDispatcher
4748
import kotlinx.coroutines.CoroutineScope
4849
import kotlinx.coroutines.ExperimentalCoroutinesApi
4950
import kotlinx.coroutines.coroutineScope
5051
import kotlinx.coroutines.delay
52+
import kotlinx.coroutines.flow.Flow
5153
import kotlinx.coroutines.flow.collectLatest
5254
import kotlinx.coroutines.flow.conflate
55+
import kotlinx.coroutines.flow.distinctUntilChanged
56+
import kotlinx.coroutines.flow.emitAll
5357
import kotlinx.coroutines.flow.first
5458
import kotlinx.coroutines.flow.flowOn
5559
import kotlinx.coroutines.flow.map
5660
import kotlinx.coroutines.flow.onStart
5761
import kotlinx.coroutines.flow.transformLatest
5862
import kotlinx.coroutines.launch
63+
import kotlinx.coroutines.yield
64+
import javax.inject.Inject
65+
import kotlin.time.Duration
66+
import kotlin.time.Duration.Companion.seconds
5967

6068
/**
6169
* Filters low priority and privacy-sensitive notifications from the lockscreen, and hides section
@@ -69,6 +77,7 @@ constructor(
6977
private val headsUpManager: HeadsUpManager,
7078
private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
7179
private val keyguardRepository: KeyguardRepository,
80+
private val keyguardTransitionRepository: KeyguardTransitionRepository,
7281
private val notifPipelineFlags: NotifPipelineFlags,
7382
@Application private val scope: CoroutineScope,
7483
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
@@ -99,21 +108,46 @@ constructor(
99108
}
100109

101110
private suspend fun trackUnseenNotificationsWhileUnlocked() {
111+
// Whether or not we're actively tracking unseen notifications to mark them as seen when
112+
// appropriate.
113+
val isTrackingUnseen: Flow<Boolean> =
114+
keyguardRepository.isKeyguardShowing
115+
// transformLatest so that we can cancel listening to keyguard transitions once
116+
// isKeyguardShowing changes (after a successful transition to the keyguard).
117+
.transformLatest { isShowing ->
118+
if (isShowing) {
119+
// If the keyguard is showing, we're not tracking unseen.
120+
emit(false)
121+
} else {
122+
// If the keyguard stops showing, then start tracking unseen notifications.
123+
emit(true)
124+
// If the screen is turning off, stop tracking, but if that transition is
125+
// cancelled, then start again.
126+
emitAll(
127+
keyguardTransitionRepository.transitions
128+
.map { step -> !step.isScreenTurningOff }
129+
)
130+
}
131+
}
132+
// Prevent double emit of `false` caused by transition to AOD, followed by keyguard
133+
// showing
134+
.distinctUntilChanged()
135+
102136
// Use collectLatest so that trackUnseenNotifications() is cancelled when the keyguard is
103137
// showing again
104-
var clearUnseenOnUnlock = false
105-
keyguardRepository.isKeyguardShowing.collectLatest { isKeyguardShowing ->
106-
if (isKeyguardShowing) {
138+
var clearUnseenOnBeginTracking = false
139+
isTrackingUnseen.collectLatest { trackingUnseen ->
140+
if (!trackingUnseen) {
107141
// Wait for the user to spend enough time on the lock screen before clearing unseen
108142
// set when unlocked
109143
awaitTimeSpentNotDozing(SEEN_TIMEOUT)
110-
clearUnseenOnUnlock = true
144+
clearUnseenOnBeginTracking = true
111145
} else {
112-
unseenNotifFilter.invalidateList("keyguard no longer showing")
113-
if (clearUnseenOnUnlock) {
114-
clearUnseenOnUnlock = false
146+
if (clearUnseenOnBeginTracking) {
147+
clearUnseenOnBeginTracking = false
115148
unseenNotifications.clear()
116149
}
150+
unseenNotifFilter.invalidateList("keyguard no longer showing")
117151
trackUnseenNotifications()
118152
}
119153
}
@@ -142,7 +176,10 @@ constructor(
142176
}
143177

144178
private suspend fun clearUnseenNotificationsWhenShadeIsExpanded() {
145-
statusBarStateController.expansionChanges.collect { isExpanded ->
179+
statusBarStateController.expansionChanges.collectLatest { isExpanded ->
180+
// Give keyguard events time to propagate, in case this expansion is part of the
181+
// keyguard transition and not the user expanding the shade
182+
yield()
146183
if (isExpanded) {
147184
unseenNotifications.clear()
148185
}
@@ -276,3 +313,6 @@ constructor(
276313
private val SEEN_TIMEOUT = 5.seconds
277314
}
278315
}
316+
317+
private val TransitionStep.isScreenTurningOff: Boolean get() =
318+
transitionState == TransitionState.STARTED && to != KeyguardState.GONE

packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ import androidx.test.filters.SmallTest
2525
import com.android.systemui.SysuiTestCase
2626
import com.android.systemui.coroutines.advanceTimeBy
2727
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
28+
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
29+
import com.android.systemui.keyguard.shared.model.KeyguardState
30+
import com.android.systemui.keyguard.shared.model.TransitionState
31+
import com.android.systemui.keyguard.shared.model.TransitionStep
2832
import com.android.systemui.plugins.statusbar.StatusBarStateController
2933
import com.android.systemui.statusbar.StatusBarState
3034
import com.android.systemui.statusbar.notification.NotifPipelineFlags
@@ -69,6 +73,7 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
6973
private val headsUpManager: HeadsUpManager = mock()
7074
private val keyguardNotifVisibilityProvider: KeyguardNotificationVisibilityProvider = mock()
7175
private val keyguardRepository = FakeKeyguardRepository()
76+
private val keyguardTransitionRepository = FakeKeyguardTransitionRepository()
7277
private val notifPipelineFlags: NotifPipelineFlags = mock()
7378
private val notifPipeline: NotifPipeline = mock()
7479
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider = mock()
@@ -117,6 +122,33 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
117122
}
118123
}
119124

125+
@Test
126+
fun unseenFilterStopsMarkingSeenNotifWhenTransitionToAod() {
127+
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
128+
129+
// GIVEN: Keyguard is not showing, shade is not expanded, and a notification is present
130+
keyguardRepository.setKeyguardShowing(false)
131+
whenever(statusBarStateController.isExpanded).thenReturn(false)
132+
runKeyguardCoordinatorTest {
133+
val fakeEntry = NotificationEntryBuilder().build()
134+
collectionListener.onEntryAdded(fakeEntry)
135+
136+
// WHEN: The device transitions to AOD
137+
keyguardTransitionRepository.sendTransitionStep(
138+
TransitionStep(to = KeyguardState.AOD, transitionState = TransitionState.STARTED),
139+
)
140+
testScheduler.runCurrent()
141+
142+
// WHEN: The shade is expanded
143+
whenever(statusBarStateController.isExpanded).thenReturn(true)
144+
statusBarStateListener.onExpandedChanged(true)
145+
testScheduler.runCurrent()
146+
147+
// THEN: The notification is still treated as "unseen" and is not filtered out.
148+
assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
149+
}
150+
}
151+
120152
@Test
121153
fun unseenFilter_headsUpMarkedAsSeen() {
122154
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
@@ -373,6 +405,7 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
373405
headsUpManager,
374406
keyguardNotifVisibilityProvider,
375407
keyguardRepository,
408+
keyguardTransitionRepository,
376409
notifPipelineFlags,
377410
testScope.backgroundScope,
378411
sectionHeaderVisibilityProvider,

packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/UnfoldRemoteFilter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class UnfoldRemoteFilter(
3535

3636
private var inProgress = false
3737

38-
private var processedProgress: Float = 0.0f
38+
private var processedProgress: Float = 1.0f
3939
set(newProgress) {
4040
if (inProgress) {
4141
logCounter({ "$TAG#filtered_progress" }, newProgress)

services/core/java/com/android/server/wm/RootWindowContainer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,11 +2282,10 @@ boolean resumeFocusedTasksTopActivities(
22822282
resumedOnDisplay[0] |= curResult;
22832283
return;
22842284
}
2285-
if (rootTask.getDisplayArea().isTopRootTask(rootTask)
2286-
&& topRunningActivity.isState(RESUMED)) {
2287-
// Kick off any lingering app transitions form the MoveTaskToFront
2288-
// operation, but only consider the top task and root-task on that
2289-
// display.
2285+
if (topRunningActivity.isState(RESUMED)
2286+
&& topRunningActivity == rootTask.getDisplayArea().topRunningActivity()) {
2287+
// Kick off any lingering app transitions form the MoveTaskToFront operation,
2288+
// but only consider the top activity on that display.
22902289
rootTask.executeAppTransition(targetOptions);
22912290
} else {
22922291
resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);

services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ public void testResumeActivityLingeringTransition_notExecuted() {
761761

762762
// Assume the task is at the topmost position
763763
assertFalse(rootTask.isTopRootTaskInDisplayArea());
764-
doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
764+
doReturn(taskDisplayArea.getHomeActivity()).when(taskDisplayArea).topRunningActivity();
765765

766766
// Use the task as target to resume.
767767
mRootWindowContainer.resumeFocusedTasksTopActivities();

0 commit comments

Comments
 (0)