Merge "Extend lifetime of notifs during activity launch" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
89489bb5a8
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.notification.collection.coordinator
|
||||||
|
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
|
||||||
|
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
|
||||||
|
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
|
||||||
|
import com.android.systemui.statusbar.phone.NotifActivityLaunchEvents
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/** Extends the lifetime of notifications while their activity launch animation is playing. */
|
||||||
|
interface ActivityLaunchAnimCoordinator : Coordinator
|
||||||
|
|
||||||
|
/** Provides an [ActivityLaunchAnimCoordinator] to [CoordinatorScope]. */
|
||||||
|
@Module(includes = [PrivateActivityStarterCoordinatorModule::class])
|
||||||
|
object ActivityLaunchAnimCoordinatorModule
|
||||||
|
|
||||||
|
@Module
|
||||||
|
private interface PrivateActivityStarterCoordinatorModule {
|
||||||
|
@Binds
|
||||||
|
fun bindCoordinator(impl: ActivityLaunchAnimCoordinatorImpl): ActivityLaunchAnimCoordinator
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for [NotifActivityLaunchEvents], and then extends the lifetimes of any notifs while their
|
||||||
|
* launch animation is playing.
|
||||||
|
*/
|
||||||
|
@CoordinatorScope
|
||||||
|
private class ActivityLaunchAnimCoordinatorImpl @Inject constructor(
|
||||||
|
private val activityLaunchEvents: NotifActivityLaunchEvents
|
||||||
|
) : ActivityLaunchAnimCoordinator {
|
||||||
|
// Tracks notification launches, and whether or not their lifetimes are extended.
|
||||||
|
private val notifsLaunchingActivities = mutableMapOf<String, Boolean>()
|
||||||
|
|
||||||
|
private var onEndLifetimeExtensionCallback: OnEndLifetimeExtensionCallback? = null
|
||||||
|
|
||||||
|
override fun attach(pipeline: NotifPipeline) {
|
||||||
|
activityLaunchEvents.registerListener(activityStartEventListener)
|
||||||
|
pipeline.addNotificationLifetimeExtender(extender)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val activityStartEventListener = object : NotifActivityLaunchEvents.Listener {
|
||||||
|
override fun onStartLaunchNotifActivity(entry: NotificationEntry) {
|
||||||
|
notifsLaunchingActivities[entry.key] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinishLaunchNotifActivity(entry: NotificationEntry) {
|
||||||
|
if (notifsLaunchingActivities.remove(entry.key) == true) {
|
||||||
|
// If we were extending the lifetime of this notification, stop.
|
||||||
|
onEndLifetimeExtensionCallback?.onEndLifetimeExtension(extender, entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val extender = object : NotifLifetimeExtender {
|
||||||
|
override fun getName(): String = "ActivityStarterCoordinator"
|
||||||
|
|
||||||
|
override fun setCallback(callback: OnEndLifetimeExtensionCallback) {
|
||||||
|
onEndLifetimeExtensionCallback = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun maybeExtendLifetime(entry: NotificationEntry, reason: Int): Boolean {
|
||||||
|
if (entry.key in notifsLaunchingActivities) {
|
||||||
|
// Track that we're now extending this notif
|
||||||
|
notifsLaunchingActivities[entry.key] = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancelLifetimeExtension(entry: NotificationEntry) {
|
||||||
|
if (entry.key in notifsLaunchingActivities) {
|
||||||
|
notifsLaunchingActivities[entry.key] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,7 +58,8 @@ class NotifCoordinatorsImpl @Inject constructor(
|
|||||||
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
|
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
|
||||||
viewConfigCoordinator: ViewConfigCoordinator,
|
viewConfigCoordinator: ViewConfigCoordinator,
|
||||||
visualStabilityCoordinator: VisualStabilityCoordinator,
|
visualStabilityCoordinator: VisualStabilityCoordinator,
|
||||||
sensitiveContentCoordinator: SensitiveContentCoordinator
|
sensitiveContentCoordinator: SensitiveContentCoordinator,
|
||||||
|
activityLaunchAnimCoordinator: ActivityLaunchAnimCoordinator
|
||||||
) : NotifCoordinators {
|
) : NotifCoordinators {
|
||||||
|
|
||||||
private val mCoordinators: MutableList<Coordinator> = ArrayList()
|
private val mCoordinators: MutableList<Coordinator> = ArrayList()
|
||||||
@@ -97,6 +98,7 @@ class NotifCoordinatorsImpl @Inject constructor(
|
|||||||
mCoordinators.add(viewConfigCoordinator)
|
mCoordinators.add(viewConfigCoordinator)
|
||||||
mCoordinators.add(visualStabilityCoordinator)
|
mCoordinators.add(visualStabilityCoordinator)
|
||||||
mCoordinators.add(sensitiveContentCoordinator)
|
mCoordinators.add(sensitiveContentCoordinator)
|
||||||
|
mCoordinators.add(activityLaunchAnimCoordinator)
|
||||||
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
|
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
|
||||||
mCoordinators.add(smartspaceDedupingCoordinator)
|
mCoordinators.add(smartspaceDedupingCoordinator)
|
||||||
}
|
}
|
||||||
@@ -144,4 +146,4 @@ class NotifCoordinatorsImpl @Inject constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "NotifCoordinators"
|
private const val TAG = "NotifCoordinators"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ import dagger.Binds
|
|||||||
import dagger.Module
|
import dagger.Module
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Module(includes = [PrivateModule::class])
|
@Module(includes = [PrivateSensitiveContentCoordinatorModule::class])
|
||||||
interface SensitiveContentCoordinatorModule
|
interface SensitiveContentCoordinatorModule
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
private interface PrivateModule {
|
private interface PrivateSensitiveContentCoordinatorModule {
|
||||||
@Binds
|
@Binds
|
||||||
fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator
|
fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator
|
||||||
}
|
}
|
||||||
@@ -121,4 +121,4 @@ private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<Noti
|
|||||||
if (listEntry is GroupEntry) {
|
if (listEntry is GroupEntry) {
|
||||||
yieldAll(extractAllRepresentativeEntries(listEntry.children))
|
yieldAll(extractAllRepresentativeEntries(listEntry.children))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
|||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
|
||||||
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
|
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotifPanelEventSource;
|
import com.android.systemui.statusbar.phone.NotifPanelEvents;
|
||||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
|
||||||
@@ -53,10 +53,10 @@ import javax.inject.Inject;
|
|||||||
// TODO(b/204468557): Move to @CoordinatorScope
|
// TODO(b/204468557): Move to @CoordinatorScope
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
public class VisualStabilityCoordinator implements Coordinator, Dumpable,
|
public class VisualStabilityCoordinator implements Coordinator, Dumpable,
|
||||||
NotifPanelEventSource.Callbacks {
|
NotifPanelEvents.Listener {
|
||||||
private final DelayableExecutor mDelayableExecutor;
|
private final DelayableExecutor mDelayableExecutor;
|
||||||
private final HeadsUpManager mHeadsUpManager;
|
private final HeadsUpManager mHeadsUpManager;
|
||||||
private final NotifPanelEventSource mNotifPanelEventSource;
|
private final NotifPanelEvents mNotifPanelEvents;
|
||||||
private final StatusBarStateController mStatusBarStateController;
|
private final StatusBarStateController mStatusBarStateController;
|
||||||
private final VisualStabilityProvider mVisualStabilityProvider;
|
private final VisualStabilityProvider mVisualStabilityProvider;
|
||||||
private final WakefulnessLifecycle mWakefulnessLifecycle;
|
private final WakefulnessLifecycle mWakefulnessLifecycle;
|
||||||
@@ -87,7 +87,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
|
|||||||
DelayableExecutor delayableExecutor,
|
DelayableExecutor delayableExecutor,
|
||||||
DumpManager dumpManager,
|
DumpManager dumpManager,
|
||||||
HeadsUpManager headsUpManager,
|
HeadsUpManager headsUpManager,
|
||||||
NotifPanelEventSource notifPanelEventSource,
|
NotifPanelEvents notifPanelEvents,
|
||||||
StatusBarStateController statusBarStateController,
|
StatusBarStateController statusBarStateController,
|
||||||
VisualStabilityProvider visualStabilityProvider,
|
VisualStabilityProvider visualStabilityProvider,
|
||||||
WakefulnessLifecycle wakefulnessLifecycle) {
|
WakefulnessLifecycle wakefulnessLifecycle) {
|
||||||
@@ -96,7 +96,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
|
|||||||
mWakefulnessLifecycle = wakefulnessLifecycle;
|
mWakefulnessLifecycle = wakefulnessLifecycle;
|
||||||
mStatusBarStateController = statusBarStateController;
|
mStatusBarStateController = statusBarStateController;
|
||||||
mDelayableExecutor = delayableExecutor;
|
mDelayableExecutor = delayableExecutor;
|
||||||
mNotifPanelEventSource = notifPanelEventSource;
|
mNotifPanelEvents = notifPanelEvents;
|
||||||
|
|
||||||
dumpManager.registerDumpable(this);
|
dumpManager.registerDumpable(this);
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
|
|||||||
|
|
||||||
mStatusBarStateController.addCallback(mStatusBarStateControllerListener);
|
mStatusBarStateController.addCallback(mStatusBarStateControllerListener);
|
||||||
mPulsing = mStatusBarStateController.isPulsing();
|
mPulsing = mStatusBarStateController.isPulsing();
|
||||||
mNotifPanelEventSource.registerCallbacks(this);
|
mNotifPanelEvents.registerListener(this);
|
||||||
|
|
||||||
pipeline.setVisualStabilityManager(mNotifStabilityManager);
|
pipeline.setVisualStabilityManager(mNotifStabilityManager);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.systemui.statusbar.notification.collection.coordinator.dagger
|
package com.android.systemui.statusbar.notification.collection.coordinator.dagger
|
||||||
|
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.statusbar.notification.collection.coordinator.ActivityLaunchAnimCoordinatorModule
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
|
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
|
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule
|
import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule
|
||||||
@@ -47,7 +48,10 @@ interface CoordinatorsSubcomponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Module(includes = [SensitiveContentCoordinatorModule::class])
|
@Module(includes = [
|
||||||
|
ActivityLaunchAnimCoordinatorModule::class,
|
||||||
|
SensitiveContentCoordinatorModule::class,
|
||||||
|
])
|
||||||
private abstract class InternalCoordinatorsModule {
|
private abstract class InternalCoordinatorsModule {
|
||||||
@Binds
|
@Binds
|
||||||
@Internal
|
@Internal
|
||||||
@@ -62,4 +66,4 @@ private annotation class Internal
|
|||||||
@Scope
|
@Scope
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class CoordinatorScope
|
annotation class CoordinatorScope
|
||||||
|
|||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2022 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.statusbar.notification.collection.render
|
|
||||||
|
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
|
||||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController
|
|
||||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
|
|
||||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
|
|
||||||
import com.android.systemui.util.ListenerSet
|
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import dagger.multibindings.IntoSet
|
|
||||||
|
|
||||||
/** Provides certain notification panel events. */
|
|
||||||
interface NotifPanelEventSource {
|
|
||||||
|
|
||||||
/** Registers callbacks to be invoked when notification panel events occur. */
|
|
||||||
fun registerCallbacks(callbacks: Callbacks)
|
|
||||||
|
|
||||||
/** Unregisters callbacks previously registered via [.registerCallbacks] */
|
|
||||||
fun unregisterCallbacks(callbacks: Callbacks)
|
|
||||||
|
|
||||||
/** Callbacks for certain notification panel events. */
|
|
||||||
interface Callbacks {
|
|
||||||
|
|
||||||
/** Invoked when the notification panel starts or stops collapsing. */
|
|
||||||
fun onPanelCollapsingChanged(isCollapsing: Boolean)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when the notification panel starts or stops launching an [android.app.Activity].
|
|
||||||
*/
|
|
||||||
fun onLaunchingActivityChanged(isLaunchingActivity: Boolean)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Module
|
|
||||||
abstract class NotifPanelEventSourceModule {
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@SysUISingleton
|
|
||||||
abstract fun bindEventSource(manager: NotifPanelEventSourceManager): NotifPanelEventSource
|
|
||||||
|
|
||||||
@Module
|
|
||||||
companion object {
|
|
||||||
@JvmStatic
|
|
||||||
@Provides
|
|
||||||
fun provideManager(): NotifPanelEventSourceManager = NotifPanelEventSourceManagerImpl()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Module
|
|
||||||
object StatusBarNotifPanelEventSourceModule {
|
|
||||||
@JvmStatic
|
|
||||||
@Provides
|
|
||||||
@IntoSet
|
|
||||||
@CentralSurfacesScope
|
|
||||||
fun bindStartable(
|
|
||||||
manager: NotifPanelEventSourceManager,
|
|
||||||
notifPanelController: NotificationPanelViewController
|
|
||||||
): CentralSurfacesComponent.Startable =
|
|
||||||
EventSourceStatusBarStartableImpl(manager, notifPanelController)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Management layer that bridges [SysUiSingleton] and [CentralSurfacesScope]. Necessary because code
|
|
||||||
* that wants to listen to [NotifPanelEventSource] lives in [SysUiSingleton], but the events
|
|
||||||
* themselves come from [NotificationPanelViewController] in [CentralSurfacesScope].
|
|
||||||
*/
|
|
||||||
interface NotifPanelEventSourceManager : NotifPanelEventSource {
|
|
||||||
var eventSource: NotifPanelEventSource?
|
|
||||||
}
|
|
||||||
|
|
||||||
private class NotifPanelEventSourceManagerImpl
|
|
||||||
: NotifPanelEventSourceManager, NotifPanelEventSource.Callbacks {
|
|
||||||
|
|
||||||
private val callbackSet = ListenerSet<NotifPanelEventSource.Callbacks>()
|
|
||||||
|
|
||||||
override var eventSource: NotifPanelEventSource? = null
|
|
||||||
set(value) {
|
|
||||||
field?.unregisterCallbacks(this)
|
|
||||||
value?.registerCallbacks(this)
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun registerCallbacks(callbacks: NotifPanelEventSource.Callbacks) {
|
|
||||||
callbackSet.addIfAbsent(callbacks)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unregisterCallbacks(callbacks: NotifPanelEventSource.Callbacks) {
|
|
||||||
callbackSet.remove(callbacks)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPanelCollapsingChanged(isCollapsing: Boolean) {
|
|
||||||
callbackSet.forEach { it.onPanelCollapsingChanged(isCollapsing) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLaunchingActivityChanged(isLaunchingActivity: Boolean) {
|
|
||||||
callbackSet.forEach { it.onLaunchingActivityChanged(isLaunchingActivity) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class EventSourceStatusBarStartableImpl(
|
|
||||||
private val manager: NotifPanelEventSourceManager,
|
|
||||||
private val notifPanelController: NotificationPanelViewController
|
|
||||||
) : CentralSurfacesComponent.Startable {
|
|
||||||
|
|
||||||
override fun start() {
|
|
||||||
manager.eventSource = notifPanelController
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun stop() {
|
|
||||||
manager.eventSource = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -68,7 +68,6 @@ import com.android.systemui.statusbar.notification.collection.render.GroupExpans
|
|||||||
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
|
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl;
|
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
|
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotifPanelEventSourceModule;
|
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
|
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
|
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
|
||||||
import com.android.systemui.statusbar.notification.init.NotificationsController;
|
import com.android.systemui.statusbar.notification.init.NotificationsController;
|
||||||
@@ -84,9 +83,11 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
|
|||||||
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
|
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
|
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
|
||||||
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
|
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
|
||||||
import com.android.systemui.statusbar.phone.ShadeController;
|
|
||||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||||
|
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||||
|
import com.android.systemui.statusbar.phone.NotifActivityLaunchEventsModule;
|
||||||
|
import com.android.systemui.statusbar.phone.NotifPanelEventsModule;
|
||||||
|
import com.android.systemui.statusbar.phone.ShadeController;
|
||||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||||
import com.android.systemui.util.leak.LeakDetector;
|
import com.android.systemui.util.leak.LeakDetector;
|
||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
@@ -106,8 +107,9 @@ import dagger.Provides;
|
|||||||
*/
|
*/
|
||||||
@Module(includes = {
|
@Module(includes = {
|
||||||
CoordinatorsModule.class,
|
CoordinatorsModule.class,
|
||||||
|
NotifActivityLaunchEventsModule.class,
|
||||||
NotifPipelineChoreographerModule.class,
|
NotifPipelineChoreographerModule.class,
|
||||||
NotifPanelEventSourceModule.class,
|
NotifPanelEventsModule.class,
|
||||||
NotificationSectionHeadersModule.class,
|
NotificationSectionHeadersModule.class,
|
||||||
})
|
})
|
||||||
public interface NotificationsModule {
|
public interface NotificationsModule {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.phone
|
||||||
|
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
|
||||||
|
/** Provides events about [android.app.Activity] launches from Notifications. */
|
||||||
|
interface NotifActivityLaunchEvents {
|
||||||
|
|
||||||
|
/** Registers a [Listener] to be invoked when notification activity launch events occur. */
|
||||||
|
fun registerListener(listener: Listener)
|
||||||
|
|
||||||
|
/** Unregisters a [Listener] previously registered via [registerListener] */
|
||||||
|
fun unregisterListener(listener: Listener)
|
||||||
|
|
||||||
|
/** Listener for events about [android.app.Activity] launches from Notifications. */
|
||||||
|
interface Listener {
|
||||||
|
|
||||||
|
/** Invoked when an activity has started launching from a notification. */
|
||||||
|
fun onStartLaunchNotifActivity(entry: NotificationEntry)
|
||||||
|
|
||||||
|
/** Invoked when an activity has finished launching. */
|
||||||
|
fun onFinishLaunchNotifActivity(entry: NotificationEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.phone;
|
||||||
|
|
||||||
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
|
|
||||||
|
import dagger.Binds;
|
||||||
|
import dagger.Module;
|
||||||
|
|
||||||
|
/** Provides a {@link NotifActivityLaunchEvents} in {@link SysUISingleton} scope. */
|
||||||
|
@Module
|
||||||
|
public abstract class NotifActivityLaunchEventsModule {
|
||||||
|
@Binds
|
||||||
|
abstract NotifActivityLaunchEvents bindLaunchEvents(
|
||||||
|
StatusBarNotificationActivityStarter.LaunchEventsEmitter impl);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.phone
|
||||||
|
|
||||||
|
/** Provides certain notification panel events. */
|
||||||
|
interface NotifPanelEvents {
|
||||||
|
|
||||||
|
/** Registers callbacks to be invoked when notification panel events occur. */
|
||||||
|
fun registerListener(listener: Listener)
|
||||||
|
|
||||||
|
/** Unregisters callbacks previously registered via [registerListener] */
|
||||||
|
fun unregisterListener(listener: Listener)
|
||||||
|
|
||||||
|
/** Callbacks for certain notification panel events. */
|
||||||
|
interface Listener {
|
||||||
|
|
||||||
|
/** Invoked when the notification panel starts or stops collapsing. */
|
||||||
|
fun onPanelCollapsingChanged(isCollapsing: Boolean)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when the notification panel starts or stops launching an [android.app.Activity].
|
||||||
|
*/
|
||||||
|
fun onLaunchingActivityChanged(isLaunchingActivity: Boolean)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.phone;
|
||||||
|
|
||||||
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
|
|
||||||
|
import dagger.Binds;
|
||||||
|
import dagger.Module;
|
||||||
|
|
||||||
|
/** Provides a {@link NotifPanelEvents} in {@link SysUISingleton} scope. */
|
||||||
|
@Module
|
||||||
|
public abstract class NotifPanelEventsModule {
|
||||||
|
@Binds
|
||||||
|
abstract NotifPanelEvents bindPanelEvents(
|
||||||
|
NotificationPanelViewController.PanelEventsEmitter impl);
|
||||||
|
}
|
||||||
@@ -128,6 +128,7 @@ import com.android.systemui.communal.CommunalSourceMonitor;
|
|||||||
import com.android.systemui.communal.CommunalStateController;
|
import com.android.systemui.communal.CommunalStateController;
|
||||||
import com.android.systemui.communal.dagger.CommunalViewComponent;
|
import com.android.systemui.communal.dagger.CommunalViewComponent;
|
||||||
import com.android.systemui.controls.dagger.ControlsComponent;
|
import com.android.systemui.controls.dagger.ControlsComponent;
|
||||||
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.dagger.qualifiers.DisplayId;
|
import com.android.systemui.dagger.qualifiers.DisplayId;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.doze.DozeLog;
|
import com.android.systemui.doze.DozeLog;
|
||||||
@@ -176,7 +177,6 @@ import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
|
|||||||
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotifPanelEventSource;
|
|
||||||
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
|
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
|
||||||
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||||
@@ -223,8 +223,7 @@ import javax.inject.Inject;
|
|||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
|
||||||
@CentralSurfacesComponent.CentralSurfacesScope
|
@CentralSurfacesComponent.CentralSurfacesScope
|
||||||
public class NotificationPanelViewController extends PanelViewController
|
public class NotificationPanelViewController extends PanelViewController {
|
||||||
implements NotifPanelEventSource {
|
|
||||||
|
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
@@ -335,6 +334,7 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
private final TapAgainViewController mTapAgainViewController;
|
private final TapAgainViewController mTapAgainViewController;
|
||||||
private final SplitShadeHeaderController mSplitShadeHeaderController;
|
private final SplitShadeHeaderController mSplitShadeHeaderController;
|
||||||
private final RecordingController mRecordingController;
|
private final RecordingController mRecordingController;
|
||||||
|
private final PanelEventsEmitter mPanelEventsEmitter;
|
||||||
private boolean mShouldUseSplitNotificationShade;
|
private boolean mShouldUseSplitNotificationShade;
|
||||||
// The bottom padding reserved for elements of the keyguard measuring notifications
|
// The bottom padding reserved for elements of the keyguard measuring notifications
|
||||||
private float mKeyguardNotificationBottomPadding;
|
private float mKeyguardNotificationBottomPadding;
|
||||||
@@ -664,8 +664,6 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
private Optional<NotificationPanelUnfoldAnimationController>
|
private Optional<NotificationPanelUnfoldAnimationController>
|
||||||
mNotificationPanelUnfoldAnimationController;
|
mNotificationPanelUnfoldAnimationController;
|
||||||
|
|
||||||
private final ListenerSet<Callbacks> mNotifEventSourceCallbacks = new ListenerSet<>();
|
|
||||||
|
|
||||||
private final NotificationListContainer mNotificationListContainer;
|
private final NotificationListContainer mNotificationListContainer;
|
||||||
|
|
||||||
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
|
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
|
||||||
@@ -796,7 +794,8 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
QsFrameTranslateController qsFrameTranslateController,
|
QsFrameTranslateController qsFrameTranslateController,
|
||||||
SysUiState sysUiState,
|
SysUiState sysUiState,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
NotificationListContainer notificationListContainer) {
|
NotificationListContainer notificationListContainer,
|
||||||
|
PanelEventsEmitter panelEventsEmitter) {
|
||||||
super(view,
|
super(view,
|
||||||
falsingManager,
|
falsingManager,
|
||||||
dozeLog,
|
dozeLog,
|
||||||
@@ -868,6 +867,7 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
mSecureSettings = secureSettings;
|
mSecureSettings = secureSettings;
|
||||||
mInteractionJankMonitor = interactionJankMonitor;
|
mInteractionJankMonitor = interactionJankMonitor;
|
||||||
mSysUiState = sysUiState;
|
mSysUiState = sysUiState;
|
||||||
|
mPanelEventsEmitter = panelEventsEmitter;
|
||||||
pulseExpansionHandler.setPulseExpandAbortListener(() -> {
|
pulseExpansionHandler.setPulseExpandAbortListener(() -> {
|
||||||
if (mQs != null) {
|
if (mQs != null) {
|
||||||
mQs.animateHeaderSlidingOut();
|
mQs.animateHeaderSlidingOut();
|
||||||
@@ -3466,9 +3466,7 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
boolean wasRunning = isLaunchTransitionRunning();
|
boolean wasRunning = isLaunchTransitionRunning();
|
||||||
super.setIsLaunchAnimationRunning(running);
|
super.setIsLaunchAnimationRunning(running);
|
||||||
if (wasRunning != isLaunchTransitionRunning()) {
|
if (wasRunning != isLaunchTransitionRunning()) {
|
||||||
for (Callbacks cb : mNotifEventSourceCallbacks) {
|
mPanelEventsEmitter.notifyLaunchingActivityChanged(running);
|
||||||
cb.onLaunchingActivityChanged(running);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3477,9 +3475,7 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
boolean wasClosing = isClosing();
|
boolean wasClosing = isClosing();
|
||||||
super.setIsClosing(isClosing);
|
super.setIsClosing(isClosing);
|
||||||
if (wasClosing != isClosing) {
|
if (wasClosing != isClosing) {
|
||||||
for (Callbacks cb : mNotifEventSourceCallbacks) {
|
mPanelEventsEmitter.notifyPanelCollapsingChanged(isClosing);
|
||||||
cb.onPanelCollapsingChanged(isClosing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4381,16 +4377,6 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
.commitUpdate(mDisplayId);
|
.commitUpdate(mDisplayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerCallbacks(Callbacks callbacks) {
|
|
||||||
mNotifEventSourceCallbacks.addIfAbsent(callbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unregisterCallbacks(Callbacks callbacks) {
|
|
||||||
mNotifEventSourceCallbacks.remove(callbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
|
private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
|
||||||
@Override
|
@Override
|
||||||
public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
|
public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
|
||||||
@@ -5164,4 +5150,35 @@ public class NotificationPanelViewController extends PanelViewController
|
|||||||
1.0f /* speedUpFactor */);
|
1.0f /* speedUpFactor */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SysUISingleton
|
||||||
|
static class PanelEventsEmitter implements NotifPanelEvents {
|
||||||
|
|
||||||
|
private final ListenerSet<Listener> mListeners = new ListenerSet<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PanelEventsEmitter() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerListener(@NonNull Listener listener) {
|
||||||
|
mListeners.addIfAbsent(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterListener(@NonNull Listener listener) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyLaunchingActivityChanged(boolean isLaunchingActivity) {
|
||||||
|
for (Listener cb : mListeners) {
|
||||||
|
cb.onLaunchingActivityChanged(isLaunchingActivity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyPanelCollapsingChanged(boolean isCollapsing) {
|
||||||
|
for (NotifPanelEvents.Listener cb : mListeners) {
|
||||||
|
cb.onPanelCollapsingChanged(isCollapsing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.EventLog;
|
import android.util.EventLog;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.internal.jank.InteractionJankMonitor;
|
import com.android.internal.jank.InteractionJankMonitor;
|
||||||
@@ -51,6 +52,7 @@ import com.android.systemui.ActivityIntentHelper;
|
|||||||
import com.android.systemui.EventLogTags;
|
import com.android.systemui.EventLogTags;
|
||||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||||
import com.android.systemui.assist.AssistManager;
|
import com.android.systemui.assist.AssistManager;
|
||||||
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
@@ -75,6 +77,7 @@ import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback
|
|||||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
||||||
import com.android.systemui.statusbar.policy.HeadsUpUtil;
|
import com.android.systemui.statusbar.policy.HeadsUpUtil;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
import com.android.systemui.util.ListenerSet;
|
||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -128,6 +131,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
private final ActivityLaunchAnimator mActivityLaunchAnimator;
|
private final ActivityLaunchAnimator mActivityLaunchAnimator;
|
||||||
private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
|
private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
|
||||||
private final OnUserInteractionCallback mOnUserInteractionCallback;
|
private final OnUserInteractionCallback mOnUserInteractionCallback;
|
||||||
|
private final LaunchEventsEmitter mLaunchEventsEmitter;
|
||||||
|
|
||||||
private boolean mIsCollapsingToShowActivityOverLockscreen;
|
private boolean mIsCollapsingToShowActivityOverLockscreen;
|
||||||
|
|
||||||
@@ -166,7 +170,8 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
NotificationPresenter presenter,
|
NotificationPresenter presenter,
|
||||||
NotificationPanelViewController panel,
|
NotificationPanelViewController panel,
|
||||||
ActivityLaunchAnimator activityLaunchAnimator,
|
ActivityLaunchAnimator activityLaunchAnimator,
|
||||||
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider) {
|
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider,
|
||||||
|
LaunchEventsEmitter launchEventsEmitter) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mCommandQueue = commandQueue;
|
mCommandQueue = commandQueue;
|
||||||
mMainThreadHandler = mainThreadHandler;
|
mMainThreadHandler = mainThreadHandler;
|
||||||
@@ -192,18 +197,17 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
mLockPatternUtils = lockPatternUtils;
|
mLockPatternUtils = lockPatternUtils;
|
||||||
mStatusBarRemoteInputCallback = remoteInputCallback;
|
mStatusBarRemoteInputCallback = remoteInputCallback;
|
||||||
mActivityIntentHelper = activityIntentHelper;
|
mActivityIntentHelper = activityIntentHelper;
|
||||||
|
|
||||||
mNotifPipelineFlags = notifPipelineFlags;
|
mNotifPipelineFlags = notifPipelineFlags;
|
||||||
mMetricsLogger = metricsLogger;
|
mMetricsLogger = metricsLogger;
|
||||||
mLogger = logger;
|
mLogger = logger;
|
||||||
mOnUserInteractionCallback = onUserInteractionCallback;
|
mOnUserInteractionCallback = onUserInteractionCallback;
|
||||||
|
|
||||||
// TODO: use KeyguardStateController#isOccluded to remove this dependency
|
// TODO: use KeyguardStateController#isOccluded to remove this dependency
|
||||||
mCentralSurfaces = centralSurfaces;
|
mCentralSurfaces = centralSurfaces;
|
||||||
mPresenter = presenter;
|
mPresenter = presenter;
|
||||||
mNotificationPanel = panel;
|
mNotificationPanel = panel;
|
||||||
mActivityLaunchAnimator = activityLaunchAnimator;
|
mActivityLaunchAnimator = activityLaunchAnimator;
|
||||||
mNotificationAnimationProvider = notificationAnimationProvider;
|
mNotificationAnimationProvider = notificationAnimationProvider;
|
||||||
|
mLaunchEventsEmitter = launchEventsEmitter;
|
||||||
|
|
||||||
if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
|
if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
|
||||||
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
|
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
|
||||||
@@ -254,6 +258,8 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLaunchEventsEmitter.notifyStartLaunchNotifActivity(entry);
|
||||||
|
|
||||||
boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
|
boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
|
||||||
final boolean willLaunchResolverActivity = isActivityIntent
|
final boolean willLaunchResolverActivity = isActivityIntent
|
||||||
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
|
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
|
||||||
@@ -280,7 +286,9 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
postKeyguardAction.onDismiss();
|
postKeyguardAction.onDismiss();
|
||||||
} else {
|
} else {
|
||||||
mActivityStarter.dismissKeyguardThenExecute(
|
mActivityStarter.dismissKeyguardThenExecute(
|
||||||
postKeyguardAction, null /* cancel */, willLaunchResolverActivity);
|
postKeyguardAction,
|
||||||
|
() -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry),
|
||||||
|
willLaunchResolverActivity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,24 +388,26 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
// inform NMS that the notification was clicked
|
// inform NMS that the notification was clicked
|
||||||
mClickNotifier.onNotificationClick(notificationKey, nv);
|
mClickNotifier.onNotificationClick(notificationKey, nv);
|
||||||
|
|
||||||
if (!canBubble) {
|
if (!canBubble && (shouldAutoCancel
|
||||||
if (shouldAutoCancel || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
|
|| mRemoteInputManager.isNotificationKeptForRemoteInputHistory(notificationKey))) {
|
||||||
notificationKey)) {
|
// Immediately remove notification from visually showing.
|
||||||
// Immediately remove notification from visually showing.
|
// We have to post the removal to the UI thread for synchronization.
|
||||||
// We have to post the removal to the UI thread for synchronization.
|
mMainThreadHandler.post(() -> {
|
||||||
mMainThreadHandler.post(() -> {
|
final Runnable removeNotification = () -> {
|
||||||
final Runnable removeNotification = () ->
|
mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK, summaryToRemove);
|
||||||
mOnUserInteractionCallback.onDismiss(
|
mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry);
|
||||||
entry, REASON_CLICK, summaryToRemove);
|
};
|
||||||
if (mPresenter.isCollapsing()) {
|
if (mPresenter.isCollapsing()) {
|
||||||
// To avoid lags we're only performing the remove
|
// To avoid lags we're only performing the remove
|
||||||
// after the shade is collapsed
|
// after the shade is collapsed
|
||||||
mShadeController.addPostCollapseAction(removeNotification);
|
mShadeController.addPostCollapseAction(removeNotification);
|
||||||
} else {
|
} else {
|
||||||
removeNotification.run();
|
removeNotification.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
|
mMainThreadHandler.post(
|
||||||
|
() -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsCollapsingToShowActivityOverLockscreen = false;
|
mIsCollapsingToShowActivityOverLockscreen = false;
|
||||||
@@ -659,4 +669,35 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
|
|||||||
|
|
||||||
return entry.shouldSuppressFullScreenIntent();
|
return entry.shouldSuppressFullScreenIntent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SysUISingleton
|
||||||
|
static class LaunchEventsEmitter implements NotifActivityLaunchEvents {
|
||||||
|
|
||||||
|
private final ListenerSet<Listener> mListeners = new ListenerSet<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LaunchEventsEmitter() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerListener(@NonNull Listener listener) {
|
||||||
|
mListeners.addIfAbsent(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterListener(@NonNull Listener listener) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyStartLaunchNotifActivity(NotificationEntry entry) {
|
||||||
|
for (Listener listener : mListeners) {
|
||||||
|
listener.onStartLaunchNotifActivity(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyFinishLaunchNotifActivity(NotificationEntry entry) {
|
||||||
|
for (Listener listener : mListeners) {
|
||||||
|
listener.onFinishLaunchNotifActivity(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import com.android.systemui.statusbar.NotificationShelfController;
|
|||||||
import com.android.systemui.statusbar.core.StatusBarInitializer;
|
import com.android.systemui.statusbar.core.StatusBarInitializer;
|
||||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||||
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
|
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.StatusBarNotifPanelEventSourceModule;
|
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutListContainerModule;
|
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutListContainerModule;
|
||||||
@@ -60,8 +59,8 @@ import dagger.Subcomponent;
|
|||||||
* outside the component. Should more items be moved *into* this component to avoid so many getters?
|
* outside the component. Should more items be moved *into* this component to avoid so many getters?
|
||||||
*/
|
*/
|
||||||
@Subcomponent(modules = {
|
@Subcomponent(modules = {
|
||||||
|
CentralSurfacesStartableModule.class,
|
||||||
NotificationStackScrollLayoutListContainerModule.class,
|
NotificationStackScrollLayoutListContainerModule.class,
|
||||||
StatusBarNotifPanelEventSourceModule.class,
|
|
||||||
StatusBarViewModule.class,
|
StatusBarViewModule.class,
|
||||||
StatusBarNotificationActivityStarterModule.class,
|
StatusBarNotificationActivityStarterModule.class,
|
||||||
StatusBarNotificationPresenterModule.class,
|
StatusBarNotificationPresenterModule.class,
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.phone.dagger;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.multibindings.Multibinds;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
interface CentralSurfacesStartableModule {
|
||||||
|
@Multibinds
|
||||||
|
Set<CentralSurfacesComponent.Startable> multibindStartables();
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.statusbar.notification.collection.coordinator
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
|
||||||
|
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
|
||||||
|
import com.android.systemui.statusbar.phone.NotifActivityLaunchEvents
|
||||||
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import com.android.systemui.util.mockito.withArgCaptor
|
||||||
|
import dagger.BindsInstance
|
||||||
|
import dagger.Component
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
class ActivityLaunchAnimCoordinatorTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
val activityLaunchEvents: NotifActivityLaunchEvents = mock()
|
||||||
|
val pipeline: NotifPipeline = mock()
|
||||||
|
|
||||||
|
val coordinator: ActivityLaunchAnimCoordinator =
|
||||||
|
DaggerTestActivityStarterCoordinatorComponent
|
||||||
|
.factory()
|
||||||
|
.create(activityLaunchEvents)
|
||||||
|
.coordinator
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNoLifetimeExtensionIfNoAssociatedActivityLaunch() {
|
||||||
|
coordinator.attach(pipeline)
|
||||||
|
val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
|
||||||
|
verify(pipeline).addNotificationLifetimeExtender(capture())
|
||||||
|
}
|
||||||
|
val fakeEntry = mock<NotificationEntry>().also {
|
||||||
|
whenever(it.key).thenReturn("0")
|
||||||
|
}
|
||||||
|
assertFalse(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNoLifetimeExtensionIfAssociatedActivityLaunchAlreadyEnded() {
|
||||||
|
coordinator.attach(pipeline)
|
||||||
|
val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
|
||||||
|
verify(pipeline).addNotificationLifetimeExtender(capture())
|
||||||
|
}
|
||||||
|
val eventListener = withArgCaptor<NotifActivityLaunchEvents.Listener> {
|
||||||
|
verify(activityLaunchEvents).registerListener(capture())
|
||||||
|
}
|
||||||
|
val fakeEntry = mock<NotificationEntry>().also {
|
||||||
|
whenever(it.key).thenReturn("0")
|
||||||
|
}
|
||||||
|
eventListener.onStartLaunchNotifActivity(fakeEntry)
|
||||||
|
eventListener.onFinishLaunchNotifActivity(fakeEntry)
|
||||||
|
assertFalse(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLifetimeExtensionWhileActivityLaunchInProgress() {
|
||||||
|
coordinator.attach(pipeline)
|
||||||
|
val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
|
||||||
|
verify(pipeline).addNotificationLifetimeExtender(capture())
|
||||||
|
}
|
||||||
|
val eventListener = withArgCaptor<NotifActivityLaunchEvents.Listener> {
|
||||||
|
verify(activityLaunchEvents).registerListener(capture())
|
||||||
|
}
|
||||||
|
val onEndLifetimeExtensionCallback =
|
||||||
|
mock<NotifLifetimeExtender.OnEndLifetimeExtensionCallback>()
|
||||||
|
lifetimeExtender.setCallback(onEndLifetimeExtensionCallback)
|
||||||
|
|
||||||
|
val fakeEntry = mock<NotificationEntry>().also {
|
||||||
|
whenever(it.key).thenReturn("0")
|
||||||
|
}
|
||||||
|
eventListener.onStartLaunchNotifActivity(fakeEntry)
|
||||||
|
assertTrue(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
|
||||||
|
|
||||||
|
eventListener.onFinishLaunchNotifActivity(fakeEntry)
|
||||||
|
verify(onEndLifetimeExtensionCallback).onEndLifetimeExtension(lifetimeExtender, fakeEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCancelLifetimeExtensionDoesNotInvokeCallback() {
|
||||||
|
coordinator.attach(pipeline)
|
||||||
|
val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
|
||||||
|
verify(pipeline).addNotificationLifetimeExtender(capture())
|
||||||
|
}
|
||||||
|
val eventListener = withArgCaptor<NotifActivityLaunchEvents.Listener> {
|
||||||
|
verify(activityLaunchEvents).registerListener(capture())
|
||||||
|
}
|
||||||
|
val onEndLifetimeExtensionCallback =
|
||||||
|
mock<NotifLifetimeExtender.OnEndLifetimeExtensionCallback>()
|
||||||
|
lifetimeExtender.setCallback(onEndLifetimeExtensionCallback)
|
||||||
|
|
||||||
|
val fakeEntry = mock<NotificationEntry>().also {
|
||||||
|
whenever(it.key).thenReturn("0")
|
||||||
|
}
|
||||||
|
eventListener.onStartLaunchNotifActivity(fakeEntry)
|
||||||
|
assertTrue(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
|
||||||
|
|
||||||
|
lifetimeExtender.cancelLifetimeExtension(fakeEntry)
|
||||||
|
eventListener.onFinishLaunchNotifActivity(fakeEntry)
|
||||||
|
verify(onEndLifetimeExtensionCallback, never())
|
||||||
|
.onEndLifetimeExtension(lifetimeExtender, fakeEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CoordinatorScope
|
||||||
|
@Component(modules = [ActivityLaunchAnimCoordinatorModule::class])
|
||||||
|
interface TestActivityStarterCoordinatorComponent {
|
||||||
|
val coordinator: ActivityLaunchAnimCoordinator
|
||||||
|
|
||||||
|
@Component.Factory
|
||||||
|
interface Factory {
|
||||||
|
fun create(
|
||||||
|
@BindsInstance activityLaunchEvents: NotifActivityLaunchEvents
|
||||||
|
): TestActivityStarterCoordinatorComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
|
|||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
|
||||||
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
|
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NotifPanelEventSource;
|
import com.android.systemui.statusbar.phone.NotifPanelEvents;
|
||||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||||
import com.android.systemui.util.time.FakeSystemClock;
|
import com.android.systemui.util.time.FakeSystemClock;
|
||||||
@@ -67,12 +67,12 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
|
|||||||
@Mock private StatusBarStateController mStatusBarStateController;
|
@Mock private StatusBarStateController mStatusBarStateController;
|
||||||
@Mock private Pluggable.PluggableListener<NotifStabilityManager> mInvalidateListener;
|
@Mock private Pluggable.PluggableListener<NotifStabilityManager> mInvalidateListener;
|
||||||
@Mock private HeadsUpManager mHeadsUpManager;
|
@Mock private HeadsUpManager mHeadsUpManager;
|
||||||
@Mock private NotifPanelEventSource mNotifPanelEventSource;
|
@Mock private NotifPanelEvents mNotifPanelEvents;
|
||||||
@Mock private VisualStabilityProvider mVisualStabilityProvider;
|
@Mock private VisualStabilityProvider mVisualStabilityProvider;
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
|
@Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
|
||||||
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor;
|
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor;
|
||||||
@Captor private ArgumentCaptor<NotifPanelEventSource.Callbacks> mNotifPanelEventsCallbackCaptor;
|
@Captor private ArgumentCaptor<NotifPanelEvents.Listener> mNotifPanelEventsCallbackCaptor;
|
||||||
@Captor private ArgumentCaptor<NotifStabilityManager> mNotifStabilityManagerCaptor;
|
@Captor private ArgumentCaptor<NotifStabilityManager> mNotifStabilityManagerCaptor;
|
||||||
|
|
||||||
private FakeSystemClock mFakeSystemClock = new FakeSystemClock();
|
private FakeSystemClock mFakeSystemClock = new FakeSystemClock();
|
||||||
@@ -80,7 +80,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
|
|||||||
|
|
||||||
private WakefulnessLifecycle.Observer mWakefulnessObserver;
|
private WakefulnessLifecycle.Observer mWakefulnessObserver;
|
||||||
private StatusBarStateController.StateListener mStatusBarStateListener;
|
private StatusBarStateController.StateListener mStatusBarStateListener;
|
||||||
private NotifPanelEventSource.Callbacks mNotifPanelEventsCallback;
|
private NotifPanelEvents.Listener mNotifPanelEventsCallback;
|
||||||
private NotifStabilityManager mNotifStabilityManager;
|
private NotifStabilityManager mNotifStabilityManager;
|
||||||
private NotificationEntry mEntry;
|
private NotificationEntry mEntry;
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
|
|||||||
mFakeExecutor,
|
mFakeExecutor,
|
||||||
mDumpManager,
|
mDumpManager,
|
||||||
mHeadsUpManager,
|
mHeadsUpManager,
|
||||||
mNotifPanelEventSource,
|
mNotifPanelEvents,
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
mVisualStabilityProvider,
|
mVisualStabilityProvider,
|
||||||
mWakefulnessLifecycle);
|
mWakefulnessLifecycle);
|
||||||
@@ -106,7 +106,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
|
|||||||
verify(mStatusBarStateController).addCallback(mSBStateListenerCaptor.capture());
|
verify(mStatusBarStateController).addCallback(mSBStateListenerCaptor.capture());
|
||||||
mStatusBarStateListener = mSBStateListenerCaptor.getValue();
|
mStatusBarStateListener = mSBStateListenerCaptor.getValue();
|
||||||
|
|
||||||
verify(mNotifPanelEventSource).registerCallbacks(mNotifPanelEventsCallbackCaptor.capture());
|
verify(mNotifPanelEvents).registerListener(mNotifPanelEventsCallbackCaptor.capture());
|
||||||
mNotifPanelEventsCallback = mNotifPanelEventsCallbackCaptor.getValue();
|
mNotifPanelEventsCallback = mNotifPanelEventsCallbackCaptor.getValue();
|
||||||
|
|
||||||
verify(mNotifPipeline).setVisualStabilityManager(mNotifStabilityManagerCaptor.capture());
|
verify(mNotifPipeline).setVisualStabilityManager(mNotifStabilityManagerCaptor.capture());
|
||||||
|
|||||||
@@ -361,6 +361,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
private SysUiState mSysUiState;
|
private SysUiState mSysUiState;
|
||||||
@Mock
|
@Mock
|
||||||
private NotificationListContainer mNotificationListContainer;
|
private NotificationListContainer mNotificationListContainer;
|
||||||
|
private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter;
|
||||||
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
|
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
|
||||||
private SysuiStatusBarStateController mStatusBarStateController;
|
private SysuiStatusBarStateController mStatusBarStateController;
|
||||||
private NotificationPanelViewController mNotificationPanelViewController;
|
private NotificationPanelViewController mNotificationPanelViewController;
|
||||||
@@ -488,6 +489,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
}).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
|
}).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
|
||||||
|
|
||||||
mMainHandler = new Handler(Looper.getMainLooper());
|
mMainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
mPanelEventsEmitter = new NotificationPanelViewController.PanelEventsEmitter();
|
||||||
|
|
||||||
mNotificationPanelViewController = new NotificationPanelViewController(mView,
|
mNotificationPanelViewController = new NotificationPanelViewController(mView,
|
||||||
mResources,
|
mResources,
|
||||||
@@ -546,7 +548,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
mQsFrameTranslateController,
|
mQsFrameTranslateController,
|
||||||
mSysUiState,
|
mSysUiState,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mNotificationListContainer);
|
mNotificationListContainer,
|
||||||
|
mPanelEventsEmitter);
|
||||||
mNotificationPanelViewController.initDependencies(
|
mNotificationPanelViewController.initDependencies(
|
||||||
mCentralSurfaces,
|
mCentralSurfaces,
|
||||||
() -> {},
|
() -> {},
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import com.android.systemui.SysuiTestCase;
|
|||||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||||
import com.android.systemui.assist.AssistManager;
|
import com.android.systemui.assist.AssistManager;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.NotificationClickNotifier;
|
import com.android.systemui.statusbar.NotificationClickNotifier;
|
||||||
@@ -130,7 +131,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
private NotifPipeline mNotifPipeline;
|
private NotifPipeline mNotifPipeline;
|
||||||
@Mock
|
@Mock
|
||||||
private NotificationVisibilityProvider mVisibilityProvider;
|
private NotificationVisibilityProvider mVisibilityProvider;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ActivityIntentHelper mActivityIntentHelper;
|
private ActivityIntentHelper mActivityIntentHelper;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -145,14 +145,14 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
private ActivityLaunchAnimator mActivityLaunchAnimator;
|
private ActivityLaunchAnimator mActivityLaunchAnimator;
|
||||||
@Mock
|
@Mock
|
||||||
private InteractionJankMonitor mJankMonitor;
|
private InteractionJankMonitor mJankMonitor;
|
||||||
|
private StatusBarNotificationActivityStarter.LaunchEventsEmitter mLaunchEventsEmitter;
|
||||||
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
|
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
|
|
||||||
private NotificationTestHelper mNotificationTestHelper;
|
private NotificationTestHelper mNotificationTestHelper;
|
||||||
private ExpandableNotificationRow mNotificationRow;
|
private ExpandableNotificationRow mNotificationRow;
|
||||||
private ExpandableNotificationRow mBubbleNotificationRow;
|
private ExpandableNotificationRow mBubbleNotificationRow;
|
||||||
|
|
||||||
private final Answer<Void> mCallOnDismiss = answerVoid(
|
private final Answer<Void> mCallOnDismiss = answerVoid(
|
||||||
(ActivityStarter.OnDismissAction dismissAction, Runnable cancel,
|
(OnDismissAction dismissAction, Runnable cancel,
|
||||||
Boolean afterKeyguardGone) -> dismissAction.onDismiss());
|
Boolean afterKeyguardGone) -> dismissAction.onDismiss());
|
||||||
private ArrayList<NotificationEntry> mActiveNotifications;
|
private ArrayList<NotificationEntry> mActiveNotifications;
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
NotificationListContainer.class),
|
NotificationListContainer.class),
|
||||||
headsUpManager,
|
headsUpManager,
|
||||||
mJankMonitor);
|
mJankMonitor);
|
||||||
|
mLaunchEventsEmitter = new StatusBarNotificationActivityStarter.LaunchEventsEmitter();
|
||||||
mNotificationActivityStarter =
|
mNotificationActivityStarter =
|
||||||
new StatusBarNotificationActivityStarter(
|
new StatusBarNotificationActivityStarter(
|
||||||
getContext(),
|
getContext(),
|
||||||
@@ -237,12 +237,13 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
mock(NotificationPresenter.class),
|
mock(NotificationPresenter.class),
|
||||||
mock(NotificationPanelViewController.class),
|
mock(NotificationPanelViewController.class),
|
||||||
mActivityLaunchAnimator,
|
mActivityLaunchAnimator,
|
||||||
notificationAnimationProvider
|
notificationAnimationProvider,
|
||||||
|
mLaunchEventsEmitter
|
||||||
);
|
);
|
||||||
|
|
||||||
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
|
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
|
||||||
doAnswer(mCallOnDismiss).when(mActivityStarter).dismissKeyguardThenExecute(
|
doAnswer(mCallOnDismiss).when(mActivityStarter).dismissKeyguardThenExecute(
|
||||||
any(ActivityStarter.OnDismissAction.class), any(), anyBoolean());
|
any(OnDismissAction.class), any(), anyBoolean());
|
||||||
|
|
||||||
// set up addAfterKeyguardGoneRunnable to synchronously invoke the Runnable arg
|
// set up addAfterKeyguardGoneRunnable to synchronously invoke the Runnable arg
|
||||||
doAnswer(answerVoid(Runnable::run))
|
doAnswer(answerVoid(Runnable::run))
|
||||||
@@ -402,4 +403,40 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
// THEN display should try wake up for the full screen intent
|
// THEN display should try wake up for the full screen intent
|
||||||
verify(mCentralSurfaces).wakeUpForFullScreenIntent();
|
verify(mCentralSurfaces).wakeUpForFullScreenIntent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotifActivityStarterEventSourceStartEvent_onNotificationClicked() {
|
||||||
|
NotifActivityLaunchEvents.Listener listener =
|
||||||
|
mock(NotifActivityLaunchEvents.Listener.class);
|
||||||
|
mLaunchEventsEmitter.registerListener(listener);
|
||||||
|
mNotificationActivityStarter
|
||||||
|
.onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
|
||||||
|
verify(listener).onStartLaunchNotifActivity(mNotificationRow.getEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotifActivityStarterEventSourceFinishEvent_dismissKeyguardCancelled() {
|
||||||
|
NotifActivityLaunchEvents.Listener listener =
|
||||||
|
mock(NotifActivityLaunchEvents.Listener.class);
|
||||||
|
mLaunchEventsEmitter.registerListener(listener);
|
||||||
|
// set up dismissKeyguardThenExecute to synchronously invoke the cancel runnable arg
|
||||||
|
doAnswer(answerVoid(
|
||||||
|
(OnDismissAction dismissAction, Runnable cancel, Boolean afterKeyguardGone) ->
|
||||||
|
cancel.run()))
|
||||||
|
.when(mActivityStarter)
|
||||||
|
.dismissKeyguardThenExecute(any(OnDismissAction.class), any(), anyBoolean());
|
||||||
|
mNotificationActivityStarter
|
||||||
|
.onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
|
||||||
|
verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse() {
|
||||||
|
NotifActivityLaunchEvents.Listener listener =
|
||||||
|
mock(NotifActivityLaunchEvents.Listener.class);
|
||||||
|
mLaunchEventsEmitter.registerListener(listener);
|
||||||
|
mNotificationActivityStarter
|
||||||
|
.onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
|
||||||
|
verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user