summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt867
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt255
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java8
24 files changed, 1470 insertions, 143 deletions
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index 6d4dbf632d76..33c7c117dc95 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -102,6 +102,33 @@ public interface ActivityStarter {
void dismissKeyguardThenExecute(OnDismissAction action, @Nullable Runnable cancel,
boolean afterKeyguardGone, @Nullable String customMessage);
+ /** Starts an activity and dismisses keyguard. */
+ void startActivityDismissingKeyguard(Intent intent,
+ boolean onlyProvisioned,
+ boolean dismissShade,
+ boolean disallowEnterPictureInPictureWhileLaunching,
+ Callback callback,
+ int flags,
+ @Nullable ActivityLaunchAnimator.Controller animationController,
+ UserHandle userHandle);
+
+ /** Execute a runnable after dismissing keyguard. */
+ void executeRunnableDismissingKeyguard(Runnable runnable,
+ Runnable cancelAction,
+ boolean dismissShade,
+ boolean afterKeyguardGone,
+ boolean deferred);
+
+ /** Execute a runnable after dismissing keyguard. */
+ void executeRunnableDismissingKeyguard(
+ Runnable runnable,
+ Runnable cancelAction,
+ boolean dismissShade,
+ boolean afterKeyguardGone,
+ boolean deferred,
+ boolean willAnimateOnKeyguard,
+ @Nullable String customMessage);
+
interface Callback {
void onActivityStarted(int resultCode);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index 401f6c9c747d..bf84f8af02fe 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -35,6 +35,8 @@ import javax.inject.Inject;
/**
* Single common instance of ActivityStarter that can be gotten and referenced from anywhere, but
* delegates to an actual implementation (CentralSurfaces).
+ *
+ * @deprecated Migrating to ActivityStarterImpl
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@SysUISingleton
@@ -92,6 +94,14 @@ public class ActivityStarterDelegate implements ActivityStarter {
}
@Override
+ public void startActivity(Intent intent,
+ boolean dismissShade,
+ @Nullable ActivityLaunchAnimator.Controller animationController) {
+ mActualStarterOptionalLazy.get().ifPresent(
+ starter -> starter.startActivity(intent, dismissShade, animationController));
+ }
+
+ @Override
public void startActivity(Intent intent, boolean dismissShade,
@Nullable ActivityLaunchAnimator.Controller animationController,
boolean showOverLockscreenWhenLocked) {
@@ -177,4 +187,35 @@ public class ActivityStarterDelegate implements ActivityStarter {
starter -> starter.dismissKeyguardThenExecute(action, cancel, afterKeyguardGone,
customMessage));
}
+
+ @Override
+ public void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
+ boolean dismissShade, boolean disallowEnterPictureInPictureWhileLaunching,
+ Callback callback, int flags,
+ @Nullable ActivityLaunchAnimator.Controller animationController,
+ UserHandle userHandle) {
+ mActualStarterOptionalLazy.get().ifPresent(
+ starter -> starter.startActivityDismissingKeyguard(intent, onlyProvisioned,
+ dismissShade, disallowEnterPictureInPictureWhileLaunching, callback,
+ flags, animationController, userHandle));
+ }
+
+ @Override
+ public void executeRunnableDismissingKeyguard(Runnable runnable,
+ Runnable cancelAction, boolean dismissShade,
+ boolean afterKeyguardGone, boolean deferred) {
+ mActualStarterOptionalLazy.get().ifPresent(
+ starter -> starter.executeRunnableDismissingKeyguard(runnable, cancelAction,
+ dismissShade, afterKeyguardGone, deferred));
+ }
+
+ @Override
+ public void executeRunnableDismissingKeyguard(Runnable runnable, Runnable cancelAction,
+ boolean dismissShade, boolean afterKeyguardGone, boolean deferred,
+ boolean willAnimateOnKeyguard, @Nullable String customMessage) {
+ mActualStarterOptionalLazy.get().ifPresent(
+ starter -> starter.executeRunnableDismissingKeyguard(runnable, cancelAction,
+ dismissShade, afterKeyguardGone, deferred, willAnimateOnKeyguard,
+ customMessage));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
index 67ad3db74f8a..8764297c1b5d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
@@ -18,6 +18,8 @@ package com.android.systemui.dagger;
import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.classifier.FalsingManagerProxy;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.globalactions.GlobalActionsImpl;
import com.android.systemui.plugins.ActivityStarter;
@@ -28,6 +30,7 @@ import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.phone.ActivityStarterImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.volume.VolumeDialogControllerImpl;
@@ -46,7 +49,11 @@ public abstract class PluginModule {
/** */
@Provides
static ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate,
- PluginDependencyProvider dependencyProvider) {
+ PluginDependencyProvider dependencyProvider, ActivityStarterImpl activityStarterImpl,
+ FeatureFlags featureFlags) {
+ if (featureFlags.isEnabled(Flags.USE_NEW_ACTIVITY_STARTER)) {
+ return activityStarterImpl;
+ }
dependencyProvider.allowPluginDependency(ActivityStarter.class, delegate);
return delegate;
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 2ecb0a0043a2..17e66a74927b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -675,4 +675,8 @@ object Flags {
@JvmField
val ADVANCED_VPN_ENABLED = unreleasedFlag(2800, name = "AdvancedVpn__enable_feature",
namespace = "vpn", teamfood = true)
+
+ // TODO(b/278761837): Tracking Bug
+ @JvmField
+ val USE_NEW_ACTIVITY_STARTER = unreleasedFlag(2801, name = "use_new_activity_starter")
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 5ea1c0b4ce85..4b22edcc29ad 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -23,15 +23,16 @@ import android.os.RemoteException;
import android.util.Log;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import dagger.Lazy;
+
import java.util.Optional;
import javax.inject.Inject;
-import dagger.Lazy;
-
/**
* An implementation of the Recents interface which proxies to the OverviewProxyService.
*/
@@ -44,13 +45,15 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
private Handler mHandler;
private final OverviewProxyService mOverviewProxyService;
+ private final ActivityStarter mActivityStarter;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyRecentsImpl(Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
- OverviewProxyService overviewProxyService) {
+ OverviewProxyService overviewProxyService, ActivityStarter activityStarter) {
mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
mOverviewProxyService = overviewProxyService;
+ mActivityStarter = activityStarter;
}
@Override
@@ -101,7 +104,7 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
final Optional<CentralSurfaces> centralSurfacesOptional =
mCentralSurfacesOptionalLazy.get();
if (centralSurfacesOptional.map(CentralSurfaces::isKeyguardShowing).orElse(false)) {
- centralSurfacesOptional.get().executeRunnableDismissingKeyguard(
+ mActivityStarter.executeRunnableDismissingKeyguard(
() -> mHandler.post(toggleRecents), null, true /* dismissShade */,
false /* afterKeyguardGone */,
true /* deferred */);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java
index 4f5cb72438bc..3aefcb3d2976 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java
@@ -33,11 +33,9 @@ import android.util.Log;
import android.view.RemoteAnimationAdapter;
import android.view.WindowManagerGlobal;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-
-import java.util.Optional;
import javax.inject.Inject;
@@ -48,20 +46,20 @@ import javax.inject.Inject;
public class ActionProxyReceiver extends BroadcastReceiver {
private static final String TAG = "ActionProxyReceiver";
- private final CentralSurfaces mCentralSurfaces;
private final ActivityManagerWrapper mActivityManagerWrapper;
private final ScreenshotSmartActions mScreenshotSmartActions;
private final DisplayTracker mDisplayTracker;
+ private final ActivityStarter mActivityStarter;
@Inject
- public ActionProxyReceiver(Optional<CentralSurfaces> centralSurfacesOptional,
- ActivityManagerWrapper activityManagerWrapper,
+ public ActionProxyReceiver(ActivityManagerWrapper activityManagerWrapper,
ScreenshotSmartActions screenshotSmartActions,
- DisplayTracker displayTracker) {
- mCentralSurfaces = centralSurfacesOptional.orElse(null);
+ DisplayTracker displayTracker,
+ ActivityStarter activityStarter) {
mActivityManagerWrapper = activityManagerWrapper;
mScreenshotSmartActions = screenshotSmartActions;
mDisplayTracker = displayTracker;
+ mActivityStarter = activityStarter;
}
@Override
@@ -92,13 +90,9 @@ public class ActionProxyReceiver extends BroadcastReceiver {
};
- if (mCentralSurfaces != null) {
- mCentralSurfaces.executeRunnableDismissingKeyguard(startActivityRunnable, null,
- true /* dismissShade */, true /* afterKeyguardGone */,
- true /* deferred */);
- } else {
- startActivityRunnable.run();
- }
+ mActivityStarter.executeRunnableDismissingKeyguard(startActivityRunnable, null,
+ true /* dismissShade */, true /* afterKeyguardGone */,
+ true /* deferred */);
if (intent.getBooleanExtra(EXTRA_SMART_ACTIONS_ENABLED, false)) {
String actionType = Intent.ACTION_EDIT.equals(intent.getAction())
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
index 4cb91e134003..14e875d28f8f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
@@ -21,53 +21,44 @@ import android.util.Log
import androidx.lifecycle.LifecycleService
import androidx.lifecycle.lifecycleScope
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.statusbar.phone.CentralSurfaces
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import java.util.Optional
-import javax.inject.Inject
-/**
- * Provides state from the main SystemUI process on behalf of the Screenshot process.
- */
-internal class ScreenshotProxyService @Inject constructor(
+/** Provides state from the main SystemUI process on behalf of the Screenshot process. */
+internal class ScreenshotProxyService
+@Inject
+constructor(
private val mExpansionMgr: ShadeExpansionStateManager,
- private val mCentralSurfacesOptional: Optional<CentralSurfaces>,
@Main private val mMainDispatcher: CoroutineDispatcher,
+ private val activityStarter: ActivityStarter,
) : LifecycleService() {
- private val mBinder: IBinder = object : IScreenshotProxy.Stub() {
- /**
- * @return true when the notification shade is partially or fully expanded.
- */
- override fun isNotificationShadeExpanded(): Boolean {
- val expanded = !mExpansionMgr.isClosed()
- Log.d(TAG, "isNotificationShadeExpanded(): $expanded")
- return expanded
- }
+ private val mBinder: IBinder =
+ object : IScreenshotProxy.Stub() {
+ /** @return true when the notification shade is partially or fully expanded. */
+ override fun isNotificationShadeExpanded(): Boolean {
+ val expanded = !mExpansionMgr.isClosed()
+ Log.d(TAG, "isNotificationShadeExpanded(): $expanded")
+ return expanded
+ }
- override fun dismissKeyguard(callback: IOnDoneCallback) {
- lifecycleScope.launch {
- executeAfterDismissing(callback)
+ override fun dismissKeyguard(callback: IOnDoneCallback) {
+ lifecycleScope.launch { executeAfterDismissing(callback) }
}
}
- }
private suspend fun executeAfterDismissing(callback: IOnDoneCallback) =
withContext(mMainDispatcher) {
- mCentralSurfacesOptional.ifPresentOrElse(
- {
- it.executeRunnableDismissingKeyguard(
- Runnable {
- callback.onDone(true)
- }, null,
- true /* dismissShade */, true /* afterKeyguardGone */,
- true /* deferred */
- )
- },
- { callback.onDone(false) }
+ activityStarter.executeRunnableDismissingKeyguard(
+ Runnable { callback.onDone(true) },
+ null,
+ true /* dismissShade */,
+ true /* afterKeyguardGone */,
+ true /* deferred */
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index be92bd48a619..dfc9bcf593f0 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -4086,7 +4086,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
if (!mFalsingManager.isUnlockingDisabled() && qsFullyExpanded
&& mFalsingCollector.shouldEnforceBouncer()) {
- mCentralSurfaces.executeRunnableDismissingKeyguard(null, null,
+ mActivityStarter.executeRunnableDismissingKeyguard(null, null,
false, true, false);
}
if (DEBUG_DRAWABLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 22589686520b..88d9d8fb14a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -26,6 +26,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.media.controls.ui.MediaHierarchyManager
+import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter.OnDismissAction
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
@@ -62,11 +63,12 @@ class LockscreenShadeTransitionController @Inject constructor(
private val mediaHierarchyManager: MediaHierarchyManager,
private val scrimTransitionController: LockscreenShadeScrimTransitionController,
private val keyguardTransitionControllerFactory:
- LockscreenShadeKeyguardTransitionController.Factory,
+ LockscreenShadeKeyguardTransitionController.Factory,
private val depthController: NotificationShadeDepthController,
private val context: Context,
private val splitShadeOverScrollerFactory: SplitShadeLockScreenOverScroller.Factory,
private val singleShadeOverScrollerFactory: SingleShadeLockScreenOverScroller.Factory,
+ private val activityStarter: ActivityStarter,
wakefulnessLifecycle: WakefulnessLifecycle,
configurationController: ConfigurationController,
falsingManager: FalsingManager,
@@ -305,7 +307,7 @@ class LockscreenShadeTransitionController @Inject constructor(
if (nsslController.isInLockedDownShade()) {
logger.logDraggedDownLockDownShade(startingChild)
statusBarStateController.setLeaveOpenOnKeyguardHide(true)
- centralSurfaces.dismissKeyguardThenExecute(OnDismissAction {
+ activityStarter.dismissKeyguardThenExecute(OnDismissAction {
nextHideKeyguardNeedsNoAnimation = true
false
}, cancelRunnable, false /* afterKeyguardGone */)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index e6e6b9950d40..0c4b0927a906 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -49,6 +49,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserContextProvider;
@@ -73,8 +74,6 @@ import java.util.Optional;
import javax.inject.Inject;
-import dagger.Lazy;
-
/**
* Handles various NotificationGuts related tasks, such as binding guts to a row, opening and
* closing guts, and keeping track of the currently exposed notification guts.
@@ -107,7 +106,6 @@ public class NotificationGutsManager implements NotifGutsViewManager {
private NotificationListContainer mListContainer;
private OnSettingsClickListener mOnSettingsClickListener;
- private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
private final Handler mMainHandler;
private final Handler mBgHandler;
private final Optional<BubblesManager> mBubblesManagerOptional;
@@ -121,10 +119,10 @@ public class NotificationGutsManager implements NotifGutsViewManager {
private final ShadeController mShadeController;
private NotifGutsViewListener mGutsListener;
private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+ private final ActivityStarter mActivityStarter;
@Inject
public NotificationGutsManager(Context context,
- Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
@Main Handler mainHandler,
@Background Handler bgHandler,
AccessibilityManager accessibilityManager,
@@ -144,9 +142,9 @@ public class NotificationGutsManager implements NotifGutsViewManager {
StatusBarStateController statusBarStateController,
DeviceProvisionedController deviceProvisionedController,
MetricsLogger metricsLogger,
- HeadsUpManagerPhone headsUpManagerPhone) {
+ HeadsUpManagerPhone headsUpManagerPhone,
+ ActivityStarter activityStarter) {
mContext = context;
- mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
mMainHandler = mainHandler;
mBgHandler = bgHandler;
mAccessibilityManager = accessibilityManager;
@@ -167,6 +165,7 @@ public class NotificationGutsManager implements NotifGutsViewManager {
mDeviceProvisionedController = deviceProvisionedController;
mMetricsLogger = metricsLogger;
mHeadsUpManagerPhone = headsUpManagerPhone;
+ mActivityStarter = activityStarter;
}
public void setUpWithPresenter(NotificationPresenter presenter,
@@ -551,19 +550,15 @@ public class NotificationGutsManager implements NotifGutsViewManager {
.setLeaveOpenOnKeyguardHide(true);
}
- Optional<CentralSurfaces> centralSurfacesOptional =
- mCentralSurfacesOptionalLazy.get();
- if (centralSurfacesOptional.isPresent()) {
- Runnable r = () -> mMainHandler.post(
- () -> openGutsInternal(view, x, y, menuItem));
- centralSurfacesOptional.get().executeRunnableDismissingKeyguard(
- r,
- null /* cancelAction */,
- false /* dismissShade */,
- true /* afterKeyguardGone */,
- true /* deferred */);
- return true;
- }
+ Runnable r = () -> mMainHandler.post(
+ () -> openGutsInternal(view, x, y, menuItem));
+ mActivityStarter.executeRunnableDismissingKeyguard(
+ r,
+ null /* cancelAction */,
+ false /* dismissShade */,
+ true /* afterKeyguardGone */,
+ true /* deferred */);
+ return true;
/**
* When {@link CentralSurfaces} doesn't exist, falling through to call
* {@link #openGutsInternal(View,int,int,NotificationMenuRowPlugin.MenuItem)}.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 82608b1b1c7d..4a9bf4eb91ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -89,6 +89,7 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.CommandQueue;
@@ -319,6 +320,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
};
private NotificationStackScrollLogger mLogger;
private CentralSurfaces mCentralSurfaces;
+ private ActivityStarter mActivityStarter;
private final int[] mTempInt2 = new int[2];
private boolean mGenerateChildOrderChangedEvent;
private final HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
@@ -4814,6 +4816,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
this.mCentralSurfaces = centralSurfaces;
}
+ public void setActivityStarter(ActivityStarter activityStarter) {
+ mActivityStarter = activityStarter;
+ }
+
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
void requestAnimateEverything() {
if (mIsExpanded && mAnimationsEnabled) {
@@ -5579,7 +5585,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
Intent intent = showHistory
? new Intent(Settings.ACTION_NOTIFICATION_HISTORY)
: new Intent(Settings.ACTION_NOTIFICATION_SETTINGS);
- mCentralSurfaces.startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ mActivityStarter.startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
});
setEmptyShadeView(view);
updateEmptyShadeView(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index b69ce3861342..4751fb68697b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -63,6 +63,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.KeyguardMediaController;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
@@ -198,6 +199,7 @@ public class NotificationStackScrollLayoutController {
private final NotificationTargetsHelper mNotificationTargetsHelper;
private final SecureSettings mSecureSettings;
private final NotificationDismissibilityProvider mDismissibilityProvider;
+ private final ActivityStarter mActivityStarter;
private View mLongPressedView;
@@ -487,7 +489,7 @@ public class NotificationStackScrollLayoutController {
mView.addSwipedOutView(view);
mFalsingCollector.onNotificationDismissed();
if (mFalsingCollector.shouldEnforceBouncer()) {
- mCentralSurfaces.executeRunnableDismissingKeyguard(
+ mActivityStarter.executeRunnableDismissingKeyguard(
null,
null /* cancelAction */,
false /* dismissShade */,
@@ -678,7 +680,8 @@ public class NotificationStackScrollLayoutController {
FeatureFlags featureFlags,
NotificationTargetsHelper notificationTargetsHelper,
SecureSettings secureSettings,
- NotificationDismissibilityProvider dismissibilityProvider) {
+ NotificationDismissibilityProvider dismissibilityProvider,
+ ActivityStarter activityStarter) {
mView = view;
mStackStateLogger = stackLogger;
mLogger = logger;
@@ -724,6 +727,7 @@ public class NotificationStackScrollLayoutController {
mNotificationTargetsHelper = notificationTargetsHelper;
mSecureSettings = secureSettings;
mDismissibilityProvider = dismissibilityProvider;
+ mActivityStarter = activityStarter;
updateResources();
setUpView();
}
@@ -734,6 +738,7 @@ public class NotificationStackScrollLayoutController {
mView.setLogger(mLogger);
mView.setTouchHandler(new TouchHandler());
mView.setCentralSurfaces(mCentralSurfaces);
+ mView.setActivityStarter(mActivityStarter);
mView.setClearAllAnimationListener(this::onAnimationEnd);
mView.setClearAllListener((selection) -> mUiEventLogger.log(
NotificationPanelEvent.fromSelection(selection)));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
new file mode 100644
index 000000000000..d9dc8878fa61
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
@@ -0,0 +1,867 @@
+/*
+ * 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.statusbar.phone
+
+import android.app.ActivityManager
+import android.app.ActivityOptions
+import android.app.ActivityTaskManager
+import android.app.PendingIntent
+import android.app.TaskStackBuilder
+import android.content.Context
+import android.content.Intent
+import android.os.RemoteException
+import android.os.UserHandle
+import android.provider.Settings
+import android.util.Log
+import android.view.RemoteAnimationAdapter
+import android.view.View
+import android.view.WindowManager
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.R
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.animation.ActivityLaunchAnimator.PendingIntentStarter
+import com.android.systemui.animation.DelegateLaunchAnimatorController
+import com.android.systemui.assist.AssistManager
+import com.android.systemui.camera.CameraIntents.Companion.isInsecureCameraIntent
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.kotlin.getOrNull
+import dagger.Lazy
+import java.util.Optional
+import javax.inject.Inject
+
+/** Handles start activity logic in SystemUI. */
+@SysUISingleton
+class ActivityStarterImpl
+@Inject
+constructor(
+ private val centralSurfacesOptLazy: Lazy<Optional<CentralSurfaces>>,
+ private val assistManagerLazy: Lazy<AssistManager>,
+ private val dozeServiceHostLazy: Lazy<DozeServiceHost>,
+ private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
+ private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>,
+ private val shadeControllerLazy: Lazy<ShadeController>,
+ private val statusBarKeyguardViewManagerLazy: Lazy<StatusBarKeyguardViewManager>,
+ private val activityLaunchAnimator: ActivityLaunchAnimator,
+ private val context: Context,
+ private val lockScreenUserManager: NotificationLockscreenUserManager,
+ private val statusBarWindowController: StatusBarWindowController,
+ private val wakefulnessLifecycle: WakefulnessLifecycle,
+ private val keyguardStateController: KeyguardStateController,
+ private val statusBarStateController: SysuiStatusBarStateController,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val deviceProvisionedController: DeviceProvisionedController,
+ private val userTracker: UserTracker,
+ private val activityIntentHelper: ActivityIntentHelper,
+ @Main private val mainExecutor: DelayableExecutor,
+) : ActivityStarter {
+ companion object {
+ const val TAG = "ActivityStarterImpl"
+ }
+
+ private val centralSurfaces: CentralSurfaces?
+ get() = centralSurfacesOptLazy.get().getOrNull()
+
+ private val activityStarterInternal = ActivityStarterInternal()
+
+ override fun startPendingIntentDismissingKeyguard(intent: PendingIntent) {
+ activityStarterInternal.startPendingIntentDismissingKeyguard(intent = intent)
+ }
+
+ override fun startPendingIntentDismissingKeyguard(
+ intent: PendingIntent,
+ intentSentUiThreadCallback: Runnable?,
+ ) {
+ activityStarterInternal.startPendingIntentDismissingKeyguard(
+ intent = intent,
+ intentSentUiThreadCallback = intentSentUiThreadCallback,
+ )
+ }
+
+ override fun startPendingIntentDismissingKeyguard(
+ intent: PendingIntent,
+ intentSentUiThreadCallback: Runnable?,
+ associatedView: View?,
+ ) {
+ activityStarterInternal.startPendingIntentDismissingKeyguard(
+ intent = intent,
+ intentSentUiThreadCallback = intentSentUiThreadCallback,
+ associatedView = associatedView,
+ )
+ }
+
+ override fun startPendingIntentDismissingKeyguard(
+ intent: PendingIntent,
+ intentSentUiThreadCallback: Runnable?,
+ animationController: ActivityLaunchAnimator.Controller?,
+ ) {
+ activityStarterInternal.startPendingIntentDismissingKeyguard(
+ intent = intent,
+ intentSentUiThreadCallback = intentSentUiThreadCallback,
+ animationController = animationController,
+ )
+ }
+
+ /**
+ * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate
+ * this.
+ */
+ override fun startActivity(intent: Intent, dismissShade: Boolean) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ dismissShade = dismissShade,
+ )
+ }
+
+ /**
+ * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate
+ * this.
+ */
+ override fun startActivity(intent: Intent, onlyProvisioned: Boolean, dismissShade: Boolean) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ onlyProvisioned = onlyProvisioned,
+ dismissShade = dismissShade,
+ )
+ }
+
+ /**
+ * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate
+ * this.
+ */
+ override fun startActivity(
+ intent: Intent,
+ dismissShade: Boolean,
+ callback: ActivityStarter.Callback?,
+ ) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ dismissShade = dismissShade,
+ callback = callback,
+ )
+ }
+
+ /**
+ * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate
+ * this.
+ */
+ override fun startActivity(
+ intent: Intent,
+ onlyProvisioned: Boolean,
+ dismissShade: Boolean,
+ flags: Int,
+ ) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ onlyProvisioned = onlyProvisioned,
+ dismissShade = dismissShade,
+ flags = flags,
+ )
+ }
+
+ override fun startActivity(
+ intent: Intent,
+ dismissShade: Boolean,
+ animationController: ActivityLaunchAnimator.Controller?,
+ showOverLockscreenWhenLocked: Boolean,
+ ) {
+ activityStarterInternal.startActivity(
+ intent = intent,
+ dismissShade = dismissShade,
+ animationController = animationController,
+ showOverLockscreenWhenLocked = showOverLockscreenWhenLocked,
+ )
+ }
+ override fun startActivity(
+ intent: Intent,
+ dismissShade: Boolean,
+ animationController: ActivityLaunchAnimator.Controller?,
+ showOverLockscreenWhenLocked: Boolean,
+ userHandle: UserHandle?,
+ ) {
+ activityStarterInternal.startActivity(
+ intent = intent,
+ dismissShade = dismissShade,
+ animationController = animationController,
+ showOverLockscreenWhenLocked = showOverLockscreenWhenLocked,
+ userHandle = userHandle,
+ )
+ }
+
+ override fun postStartActivityDismissingKeyguard(intent: PendingIntent) {
+ postOnUiThread {
+ activityStarterInternal.startPendingIntentDismissingKeyguard(
+ intent = intent,
+ )
+ }
+ }
+
+ override fun postStartActivityDismissingKeyguard(
+ intent: PendingIntent,
+ animationController: ActivityLaunchAnimator.Controller?
+ ) {
+ postOnUiThread {
+ activityStarterInternal.startPendingIntentDismissingKeyguard(
+ intent = intent,
+ animationController = animationController,
+ )
+ }
+ }
+
+ override fun postStartActivityDismissingKeyguard(intent: Intent, delay: Int) {
+ postOnUiThread(delay) {
+ activityStarterInternal.startActivityDismissingKeyguard(intent = intent)
+ }
+ }
+
+ override fun postStartActivityDismissingKeyguard(
+ intent: Intent,
+ delay: Int,
+ animationController: ActivityLaunchAnimator.Controller?,
+ ) {
+ postOnUiThread(delay) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ animationController = animationController,
+ )
+ }
+ }
+
+ override fun postStartActivityDismissingKeyguard(
+ intent: Intent,
+ delay: Int,
+ animationController: ActivityLaunchAnimator.Controller?,
+ customMessage: String?,
+ ) {
+ postOnUiThread(delay) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ animationController = animationController,
+ customMessage = customMessage,
+ )
+ }
+ }
+
+ override fun dismissKeyguardThenExecute(
+ action: OnDismissAction,
+ cancel: Runnable?,
+ afterKeyguardGone: Boolean,
+ ) {
+ activityStarterInternal.dismissKeyguardThenExecute(
+ action = action,
+ cancel = cancel,
+ afterKeyguardGone = afterKeyguardGone,
+ )
+ }
+
+ override fun dismissKeyguardThenExecute(
+ action: OnDismissAction,
+ cancel: Runnable?,
+ afterKeyguardGone: Boolean,
+ customMessage: String?,
+ ) {
+ activityStarterInternal.dismissKeyguardThenExecute(
+ action = action,
+ cancel = cancel,
+ afterKeyguardGone = afterKeyguardGone,
+ customMessage = customMessage,
+ )
+ }
+
+ override fun startActivityDismissingKeyguard(
+ intent: Intent,
+ onlyProvisioned: Boolean,
+ dismissShade: Boolean,
+ disallowEnterPictureInPictureWhileLaunching: Boolean,
+ callback: ActivityStarter.Callback?,
+ flags: Int,
+ animationController: ActivityLaunchAnimator.Controller?,
+ userHandle: UserHandle?,
+ ) {
+ activityStarterInternal.startActivityDismissingKeyguard(
+ intent = intent,
+ onlyProvisioned = onlyProvisioned,
+ dismissShade = dismissShade,
+ disallowEnterPictureInPictureWhileLaunching =
+ disallowEnterPictureInPictureWhileLaunching,
+ callback = callback,
+ flags = flags,
+ animationController = animationController,
+ userHandle = userHandle,
+ )
+ }
+
+ override fun executeRunnableDismissingKeyguard(
+ runnable: Runnable?,
+ cancelAction: Runnable?,
+ dismissShade: Boolean,
+ afterKeyguardGone: Boolean,
+ deferred: Boolean,
+ ) {
+ activityStarterInternal.executeRunnableDismissingKeyguard(
+ runnable = runnable,
+ cancelAction = cancelAction,
+ dismissShade = dismissShade,
+ afterKeyguardGone = afterKeyguardGone,
+ deferred = deferred,
+ )
+ }
+
+ override fun executeRunnableDismissingKeyguard(
+ runnable: Runnable?,
+ cancelAction: Runnable?,
+ dismissShade: Boolean,
+ afterKeyguardGone: Boolean,
+ deferred: Boolean,
+ willAnimateOnKeyguard: Boolean,
+ customMessage: String?,
+ ) {
+ activityStarterInternal.executeRunnableDismissingKeyguard(
+ runnable = runnable,
+ cancelAction = cancelAction,
+ dismissShade = dismissShade,
+ afterKeyguardGone = afterKeyguardGone,
+ deferred = deferred,
+ willAnimateOnKeyguard = willAnimateOnKeyguard,
+ customMessage = customMessage,
+ )
+ }
+
+ override fun postQSRunnableDismissingKeyguard(runnable: Runnable?) {
+ postOnUiThread {
+ statusBarStateController.setLeaveOpenOnKeyguardHide(true)
+ activityStarterInternal.executeRunnableDismissingKeyguard(
+ runnable = { runnable?.let { postOnUiThread(runnable = it) } },
+ )
+ }
+ }
+
+ private fun postOnUiThread(delay: Int = 0, runnable: Runnable) {
+ mainExecutor.executeDelayed(runnable, delay.toLong())
+ }
+
+ /**
+ * Encapsulates the activity logic for activity starter.
+ *
+ * Logic is duplicated in {@link CentralSurfacesImpl}
+ */
+ private inner class ActivityStarterInternal {
+ /** Starts an activity after dismissing keyguard. */
+ fun startActivityDismissingKeyguard(
+ intent: Intent,
+ onlyProvisioned: Boolean = false,
+ dismissShade: Boolean = false,
+ disallowEnterPictureInPictureWhileLaunching: Boolean = false,
+ callback: ActivityStarter.Callback? = null,
+ flags: Int = 0,
+ animationController: ActivityLaunchAnimator.Controller? = null,
+ userHandle: UserHandle? = null,
+ customMessage: String? = null,
+ ) {
+ val userHandle: UserHandle = userHandle ?: getActivityUserHandle(intent)
+
+ if (onlyProvisioned && !deviceProvisionedController.isDeviceProvisioned) return
+
+ val willLaunchResolverActivity: Boolean =
+ activityIntentHelper.wouldLaunchResolverActivity(
+ intent,
+ lockScreenUserManager.currentUserId
+ )
+
+ val animate =
+ animationController != null &&
+ !willLaunchResolverActivity &&
+ centralSurfaces?.shouldAnimateLaunch(true /* isActivityIntent */) == true
+ val animController =
+ wrapAnimationController(
+ animationController = animationController,
+ dismissShade = dismissShade,
+ isLaunchForActivity = true,
+ )
+
+ // If we animate, we will dismiss the shade only once the animation is done. This is
+ // taken care of by the StatusBarLaunchAnimationController.
+ val dismissShadeDirectly = dismissShade && animController == null
+
+ val runnable = Runnable {
+ assistManagerLazy.get().hideAssist()
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
+ intent.addFlags(flags)
+ val result = intArrayOf(ActivityManager.START_CANCELED)
+ activityLaunchAnimator.startIntentWithAnimation(
+ animController,
+ animate,
+ intent.getPackage()
+ ) { adapter: RemoteAnimationAdapter? ->
+ val options =
+ ActivityOptions(
+ CentralSurfaces.getActivityOptions(centralSurfaces!!.displayId, adapter)
+ )
+
+ // We know that the intent of the caller is to dismiss the keyguard and
+ // this runnable is called right after the keyguard is solved, so we tell
+ // WM that we should dismiss it to avoid flickers when opening an activity
+ // that can also be shown over the keyguard.
+ options.setDismissKeyguard()
+ options.setDisallowEnterPictureInPictureWhileLaunching(
+ disallowEnterPictureInPictureWhileLaunching
+ )
+ if (isInsecureCameraIntent(intent)) {
+ // Normally an activity will set it's requested rotation
+ // animation on its window. However when launching an activity
+ // causes the orientation to change this is too late. In these cases
+ // the default animation is used. This doesn't look good for
+ // the camera (as it rotates the camera contents out of sync
+ // with physical reality). So, we ask the WindowManager to
+ // force the cross fade animation if an orientation change
+ // happens to occur during the launch.
+ options.rotationAnimationHint =
+ WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
+ }
+ if (Settings.Panel.ACTION_VOLUME == intent.action) {
+ // Settings Panel is implemented as activity(not a dialog), so
+ // underlying app is paused and may enter picture-in-picture mode
+ // as a result.
+ // So we need to disable picture-in-picture mode here
+ // if it is volume panel.
+ options.setDisallowEnterPictureInPictureWhileLaunching(true)
+ }
+ try {
+ result[0] =
+ ActivityTaskManager.getService()
+ .startActivityAsUser(
+ null,
+ context.basePackageName,
+ context.attributionTag,
+ intent,
+ intent.resolveTypeIfNeeded(context.contentResolver),
+ null,
+ null,
+ 0,
+ Intent.FLAG_ACTIVITY_NEW_TASK,
+ null,
+ options.toBundle(),
+ userHandle.identifier,
+ )
+ } catch (e: RemoteException) {
+ Log.w(TAG, "Unable to start activity", e)
+ }
+ result[0]
+ }
+ callback?.onActivityStarted(result[0])
+ }
+ val cancelRunnable = Runnable {
+ callback?.onActivityStarted(ActivityManager.START_CANCELED)
+ }
+ // Do not deferKeyguard when occluded because, when keyguard is occluded,
+ // we do not launch the activity until keyguard is done.
+ val occluded = (keyguardStateController.isShowing && keyguardStateController.isOccluded)
+ val deferred = !occluded
+ executeRunnableDismissingKeyguard(
+ runnable,
+ cancelRunnable,
+ dismissShadeDirectly,
+ willLaunchResolverActivity,
+ deferred,
+ animate,
+ customMessage,
+ )
+ }
+
+ /** Starts a pending intent after dismissing keyguard. */
+ fun startPendingIntentDismissingKeyguard(
+ intent: PendingIntent,
+ intentSentUiThreadCallback: Runnable? = null,
+ associatedView: View? = null,
+ animationController: ActivityLaunchAnimator.Controller? = null,
+ ) {
+ val animationController =
+ if (associatedView is ExpandableNotificationRow) {
+ centralSurfaces?.getAnimatorControllerFromNotification(associatedView)
+ } else animationController
+
+ val willLaunchResolverActivity =
+ (intent.isActivity &&
+ activityIntentHelper.wouldPendingLaunchResolverActivity(
+ intent,
+ lockScreenUserManager.currentUserId,
+ ))
+
+ val animate =
+ !willLaunchResolverActivity &&
+ animationController != null &&
+ centralSurfaces?.shouldAnimateLaunch(intent.isActivity) == true
+
+ // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we
+ // run the animation on the keyguard). The animation will take care of (instantly)
+ // collapsing the shade and hiding the keyguard once it is done.
+ val collapse = !animate
+ executeRunnableDismissingKeyguard(
+ runnable = {
+ try {
+ // We wrap animationCallback with a StatusBarLaunchAnimatorController so
+ // that the shade is collapsed after the animation (or when it is cancelled,
+ // aborted, etc).
+ val controller: ActivityLaunchAnimator.Controller? =
+ wrapAnimationController(
+ animationController = animationController,
+ dismissShade = true,
+ isLaunchForActivity = intent.isActivity,
+ )
+ activityLaunchAnimator.startPendingIntentWithAnimation(
+ controller,
+ animate,
+ intent.creatorPackage,
+ object : PendingIntentStarter {
+ override fun startPendingIntent(
+ animationAdapter: RemoteAnimationAdapter?
+ ): Int {
+ val options =
+ ActivityOptions(
+ CentralSurfaces.getActivityOptions(
+ centralSurfaces!!.displayId,
+ animationAdapter
+ )
+ )
+ // TODO b/221255671: restrict this to only be set for
+ // notifications
+ options.isEligibleForLegacyPermissionPrompt = true
+ return intent.sendAndReturnResult(
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ options.toBundle()
+ )
+ }
+ },
+ )
+ } catch (e: PendingIntent.CanceledException) {
+ // the stack trace isn't very helpful here.
+ // Just log the exception message.
+ Log.w(TAG, "Sending intent failed: $e")
+ if (!collapse) {
+ // executeRunnableDismissingKeyguard did not collapse for us already.
+ centralSurfaces?.collapsePanelOnMainThread()
+ }
+ // TODO: Dismiss Keyguard.
+ }
+ if (intent.isActivity) {
+ assistManagerLazy.get().hideAssist()
+ }
+ intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) }
+ },
+ afterKeyguardGone = willLaunchResolverActivity,
+ dismissShade = collapse,
+ willAnimateOnKeyguard = animate,
+ )
+ }
+
+ /** Starts an Activity. */
+ fun startActivity(
+ intent: Intent,
+ dismissShade: Boolean = false,
+ animationController: ActivityLaunchAnimator.Controller? = null,
+ showOverLockscreenWhenLocked: Boolean = false,
+ userHandle: UserHandle? = null,
+ ) {
+ val userHandle = userHandle ?: getActivityUserHandle(intent)
+ // Make sure that we dismiss the keyguard if it is directly dismissible or when we don't
+ // want to show the activity above it.
+ if (keyguardStateController.isUnlocked || !showOverLockscreenWhenLocked) {
+ startActivityDismissingKeyguard(
+ intent = intent,
+ onlyProvisioned = false,
+ dismissShade = dismissShade,
+ disallowEnterPictureInPictureWhileLaunching = false,
+ callback = null,
+ flags = 0,
+ animationController = animationController,
+ userHandle = userHandle,
+ )
+ return
+ }
+
+ val animate =
+ animationController != null &&
+ centralSurfaces?.shouldAnimateLaunch(
+ /* isActivityIntent= */ true,
+ showOverLockscreenWhenLocked
+ ) == true
+
+ var controller: ActivityLaunchAnimator.Controller? = null
+ if (animate) {
+ // Wrap the animation controller to dismiss the shade and set
+ // mIsLaunchingActivityOverLockscreen during the animation.
+ val delegate =
+ wrapAnimationController(
+ animationController = animationController,
+ dismissShade = dismissShade,
+ isLaunchForActivity = true,
+ )
+ delegate?.let {
+ controller =
+ object : DelegateLaunchAnimatorController(delegate) {
+ override fun onIntentStarted(willAnimate: Boolean) {
+ delegate?.onIntentStarted(willAnimate)
+ if (willAnimate) {
+ centralSurfaces?.setIsLaunchingActivityOverLockscreen(true)
+ }
+ }
+
+ override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
+ super.onLaunchAnimationStart(isExpandingFullyAbove)
+
+ // Double check that the keyguard is still showing and not going
+ // away, but if so set the keyguard occluded. Typically, WM will let
+ // KeyguardViewMediator know directly, but we're overriding that to
+ // play the custom launch animation, so we need to take care of that
+ // here. The unocclude animation is not overridden, so WM will call
+ // KeyguardViewMediator's unocclude animation runner when the
+ // activity is exited.
+ if (
+ keyguardStateController.isShowing &&
+ !keyguardStateController.isKeyguardGoingAway
+ ) {
+ Log.d(TAG, "Setting occluded = true in #startActivity.")
+ keyguardViewMediatorLazy
+ .get()
+ .setOccluded(true /* isOccluded */, true /* animate */)
+ }
+ }
+
+ override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
+ // Set mIsLaunchingActivityOverLockscreen to false before actually
+ // finishing the animation so that we can assume that
+ // mIsLaunchingActivityOverLockscreen being true means that we will
+ // collapse the shade (or at least run the post collapse runnables)
+ // later on.
+ centralSurfaces?.setIsLaunchingActivityOverLockscreen(false)
+ delegate?.onLaunchAnimationEnd(isExpandingFullyAbove)
+ }
+
+ override fun onLaunchAnimationCancelled(
+ newKeyguardOccludedState: Boolean?
+ ) {
+ if (newKeyguardOccludedState != null) {
+ keyguardViewMediatorLazy
+ .get()
+ .setOccluded(newKeyguardOccludedState, false /* animate */)
+ }
+
+ // Set mIsLaunchingActivityOverLockscreen to false before actually
+ // finishing the animation so that we can assume that
+ // mIsLaunchingActivityOverLockscreen being true means that we will
+ // collapse the shade (or at least run the // post collapse
+ // runnables) later on.
+ centralSurfaces?.setIsLaunchingActivityOverLockscreen(false)
+ delegate.onLaunchAnimationCancelled(newKeyguardOccludedState)
+ }
+ }
+ }
+ } else if (dismissShade) {
+ // The animation will take care of dismissing the shade at the end of the animation.
+ // If we don't animate, collapse it directly.
+ centralSurfaces?.collapseShade()
+ }
+
+ // We should exit the dream to prevent the activity from starting below the
+ // dream.
+ if (keyguardUpdateMonitor.isDreaming) {
+ centralSurfaces?.awakenDreams()
+ }
+
+ activityLaunchAnimator.startIntentWithAnimation(
+ controller,
+ animate,
+ intent.getPackage(),
+ showOverLockscreenWhenLocked
+ ) { adapter: RemoteAnimationAdapter? ->
+ TaskStackBuilder.create(context)
+ .addNextIntent(intent)
+ .startActivities(
+ CentralSurfaces.getActivityOptions(centralSurfaces!!.displayId, adapter),
+ userHandle
+ )
+ }
+ }
+
+ /** Executes an action after dismissing keyguard. */
+ fun dismissKeyguardThenExecute(
+ action: OnDismissAction,
+ cancel: Runnable? = null,
+ afterKeyguardGone: Boolean = false,
+ customMessage: String? = null,
+ ) {
+ if (
+ !action.willRunAnimationOnKeyguard() &&
+ wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP &&
+ keyguardStateController.canDismissLockScreen() &&
+ !statusBarStateController.leaveOpenOnKeyguardHide() &&
+ dozeServiceHostLazy.get().isPulsing
+ ) {
+ // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a
+ // pulse.
+ // TODO: Factor this transition out of BiometricUnlockController.
+ biometricUnlockControllerLazy
+ .get()
+ .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
+ }
+ if (keyguardStateController.isShowing) {
+ statusBarKeyguardViewManagerLazy
+ .get()
+ .dismissWithAction(action, cancel, afterKeyguardGone, customMessage)
+ } else {
+ // If the keyguard isn't showing but the device is dreaming, we should exit the
+ // dream.
+ if (keyguardUpdateMonitor.isDreaming) {
+ centralSurfaces?.awakenDreams()
+ }
+ action.onDismiss()
+ }
+ }
+
+ /** Executes an action after dismissing keyguard. */
+ fun executeRunnableDismissingKeyguard(
+ runnable: Runnable? = null,
+ cancelAction: Runnable? = null,
+ dismissShade: Boolean = false,
+ afterKeyguardGone: Boolean = false,
+ deferred: Boolean = false,
+ willAnimateOnKeyguard: Boolean = false,
+ customMessage: String? = null,
+ ) {
+ val onDismissAction: OnDismissAction =
+ object : OnDismissAction {
+ override fun onDismiss(): Boolean {
+ if (runnable != null) {
+ if (
+ keyguardStateController.isShowing &&
+ keyguardStateController.isOccluded
+ ) {
+ statusBarKeyguardViewManagerLazy
+ .get()
+ .addAfterKeyguardGoneRunnable(runnable)
+ } else {
+ mainExecutor.execute(runnable)
+ }
+ }
+ if (dismissShade) {
+ if (
+ shadeControllerLazy.get().isExpandedVisible &&
+ !statusBarKeyguardViewManagerLazy.get().isBouncerShowing
+ ) {
+ shadeControllerLazy.get().animateCollapseShadeDelayed()
+ } else {
+ // Do it after DismissAction has been processed to conserve the
+ // needed ordering.
+ postOnUiThread {
+ shadeControllerLazy.get().runPostCollapseRunnables()
+ }
+ }
+ }
+ return deferred
+ }
+
+ override fun willRunAnimationOnKeyguard(): Boolean {
+ return willAnimateOnKeyguard
+ }
+ }
+ dismissKeyguardThenExecute(
+ onDismissAction,
+ cancelAction,
+ afterKeyguardGone,
+ customMessage,
+ )
+ }
+
+ /**
+ * Return a [ActivityLaunchAnimator.Controller] wrapping `animationController` so that:
+ * - if it launches in the notification shade window and `dismissShade` is true, then the
+ * shade will be instantly dismissed at the end of the animation.
+ * - if it launches in status bar window, it will make the status bar window match the
+ * device size during the animation (that way, the animation won't be clipped by the
+ * status bar size).
+ *
+ * @param animationController the controller that is wrapped and will drive the main
+ * animation.
+ * @param dismissShade whether the notification shade will be dismissed at the end of the
+ * animation. This is ignored if `animationController` is not animating in the shade
+ * window.
+ * @param isLaunchForActivity whether the launch is for an activity.
+ */
+ private fun wrapAnimationController(
+ animationController: ActivityLaunchAnimator.Controller?,
+ dismissShade: Boolean,
+ isLaunchForActivity: Boolean,
+ ): ActivityLaunchAnimator.Controller? {
+ if (animationController == null) {
+ return null
+ }
+ val rootView = animationController.launchContainer.rootView
+ val controllerFromStatusBar: Optional<ActivityLaunchAnimator.Controller> =
+ statusBarWindowController.wrapAnimationControllerIfInStatusBar(
+ rootView,
+ animationController
+ )
+ if (controllerFromStatusBar.isPresent) {
+ return controllerFromStatusBar.get()
+ }
+
+ centralSurfaces?.let {
+ // If the view is not in the status bar, then we are animating a view in the shade.
+ // We have to make sure that we collapse it when the animation ends or is cancelled.
+ if (dismissShade) {
+ return StatusBarLaunchAnimatorController(
+ animationController,
+ it,
+ isLaunchForActivity
+ )
+ }
+ }
+
+ return animationController
+ }
+
+ /** Retrieves the current user handle to start the Activity. */
+ private fun getActivityUserHandle(intent: Intent): UserHandle {
+ val packages: Array<String> =
+ context.resources.getStringArray(R.array.system_ui_packages)
+ for (pkg in packages) {
+ if (intent.component == null) break
+ if (pkg == intent.component.packageName) {
+ return UserHandle(UserHandle.myUserId())
+ }
+ }
+ return userTracker.userHandle
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index f579d304b268..4e690696b5d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -45,7 +45,8 @@ import com.android.systemui.Dumpable;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.RemoteTransitionAdapter;
import com.android.systemui.navigationbar.NavigationBarView;
-import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.ActivityStarter.Callback;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.shade.NotificationShadeWindowView;
@@ -53,11 +54,13 @@ import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.LightRevealScrim;
import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.util.Compile;
import java.io.PrintWriter;
-public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwner {
+/** */
+public interface CentralSurfaces extends Dumpable, LifecycleOwner {
boolean MULTIUSER_DEBUG = false;
// Should match the values in PhoneWindowManager
String SYSTEM_DIALOG_REASON_KEY = "reason";
@@ -230,29 +233,33 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
boolean isShadeDisabled();
- @Override
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
int flags);
- @Override
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
void startActivity(Intent intent, boolean dismissShade);
- @Override
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
+ void startActivity(Intent intent, boolean dismissShade,
+ @Nullable ActivityLaunchAnimator.Controller animationController);
+
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
void startActivity(Intent intent, boolean dismissShade,
@Nullable ActivityLaunchAnimator.Controller animationController,
boolean showOverLockscreenWhenLocked);
- @Override
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
void startActivity(Intent intent, boolean dismissShade,
@Nullable ActivityLaunchAnimator.Controller animationController,
boolean showOverLockscreenWhenLocked, UserHandle userHandle);
boolean isLaunchingActivityOverLockscreen();
- @Override
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade);
- @Override
+ /** Starts an activity. Please use ActivityStarter instead of using these methods directly. */
void startActivity(Intent intent, boolean dismissShade, Callback callback);
boolean isWakeUpComingFromTouch();
@@ -315,19 +322,34 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
float getDisplayHeight();
+ /** Starts an activity intent that dismisses keyguard.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
boolean dismissShade, int flags);
+ /** Starts an activity intent that dismisses keyguard.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
boolean dismissShade);
+ /** Starts an activity intent that dismisses keyguard.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
boolean dismissShade, boolean disallowEnterPictureInPictureWhileLaunching,
Callback callback, int flags,
@Nullable ActivityLaunchAnimator.Controller animationController,
UserHandle userHandle);
- /** Starts an activity intent that dismisses keyguard. */
+ /** Starts an activity intent that dismisses keyguard.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
boolean dismissShade, boolean disallowEnterPictureInPictureWhileLaunching,
Callback callback, int flags,
@@ -352,29 +374,70 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
void resetUserExpandedStates();
- @Override
+ /**
+ * Dismisses Keyguard and executes an action afterwards.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone);
+ /**
+ * Dismisses Keyguard and executes an action afterwards.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
+ void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
+ boolean afterKeyguardGone, @Nullable String customMessage);
+
void setLockscreenUser(int newUserId);
- @Override
+ /**
+ * Starts a QS runnable on the main thread and dismisses keyguard.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void postQSRunnableDismissingKeyguard(Runnable runnable);
- @Override
+ /**
+ * Starts an activity on the main thread with a delay.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void postStartActivityDismissingKeyguard(PendingIntent intent);
- @Override
+ /**
+ * Starts an activity on the main thread with a delay.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void postStartActivityDismissingKeyguard(PendingIntent intent,
@Nullable ActivityLaunchAnimator.Controller animationController);
- @Override
+ /**
+ * Starts an activity on the main thread with a delay.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void postStartActivityDismissingKeyguard(Intent intent, int delay);
- @Override
+ /**
+ * Starts an activity on the main thread with a delay.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
void postStartActivityDismissingKeyguard(Intent intent, int delay,
@Nullable ActivityLaunchAnimator.Controller animationController);
+ /**
+ * Starts an activity on the main thread with a delay.
+ *
+ * Please use ActivityStarter instead of using these methods directly.
+ */
+ void postStartActivityDismissingKeyguard(Intent intent, int delay,
+ @Nullable ActivityLaunchAnimator.Controller animationController,
+ @Nullable String customMessage);
+
void showKeyguard();
boolean hideKeyguard();
@@ -468,18 +531,14 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
void awakenDreams();
- @Override
void startPendingIntentDismissingKeyguard(PendingIntent intent);
- @Override
void startPendingIntentDismissingKeyguard(
PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback);
- @Override
void startPendingIntentDismissingKeyguard(PendingIntent intent,
Runnable intentSentUiThreadCallback, View associatedView);
- @Override
void startPendingIntentDismissingKeyguard(
PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback,
@Nullable ActivityLaunchAnimator.Controller animationController);
@@ -554,4 +613,15 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
mDeviceId = deviceId;
}
}
+
+ /**
+ * Sets launching activity over LS state in central surfaces.
+ */
+ void setIsLaunchingActivityOverLockscreen(boolean isLaunchingActivityOverLockscreen);
+
+ /**
+ * Gets an animation controller from a notification row.
+ */
+ ActivityLaunchAnimator.Controller getAnimatorControllerFromNotification(
+ ExpandableNotificationRow associatedView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index c0a7a34a3a1e..37e77766c889 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -50,6 +50,7 @@ import com.android.systemui.camera.CameraIntents;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.settings.UserTracker;
@@ -102,6 +103,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
private final boolean mVibrateOnOpening;
private final VibrationEffect mCameraLaunchGestureVibrationEffect;
private final SystemBarAttributesListener mSystemBarAttributesListener;
+ private final ActivityStarter mActivityStarter;
private final Lazy<CameraLauncher> mCameraLauncherLazy;
private final QuickSettingsController mQsController;
private final QSHost mQSHost;
@@ -138,7 +140,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
SystemBarAttributesListener systemBarAttributesListener,
Lazy<CameraLauncher> cameraLauncherLazy,
UserTracker userTracker,
- QSHost qsHost) {
+ QSHost qsHost,
+ ActivityStarter activityStarter) {
mCentralSurfaces = centralSurfaces;
mQsController = quickSettingsController;
mContext = context;
@@ -170,6 +173,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
mVibratorOptional, resources);
mSystemBarAttributesListener = systemBarAttributesListener;
+ mActivityStarter = activityStarter;
}
@Override
@@ -375,7 +379,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
if (!mKeyguardStateController.isShowing()) {
final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
cameraIntent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source);
- mCentralSurfaces.startActivityDismissingKeyguard(cameraIntent,
+ mActivityStarter.startActivityDismissingKeyguard(cameraIntent,
false /* onlyProvisioned */, true /* dismissShade */,
true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
null /* animationController */, mUserTracker.getUserHandle());
@@ -432,7 +436,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
// app-side haptic experimentation.
if (!mKeyguardStateController.isShowing()) {
- mCentralSurfaces.startActivityDismissingKeyguard(emergencyIntent,
+ mActivityStarter.startActivityDismissingKeyguard(emergencyIntent,
false /* onlyProvisioned */, true /* dismissShade */,
true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
null /* animationController */, mUserTracker.getUserHandle());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index e1c806401ea4..aa5aed7451f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -168,6 +168,8 @@ import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.notetask.NoteTaskController;
+import com.android.systemui.plugins.ActivityStarter.Callback;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.OverlayPlugin;
@@ -281,6 +283,9 @@ import javax.inject.Provider;
* <b>If at all possible, please avoid adding additional code to this monstrous class! Our goal is
* to break up this class into many small classes, and any code added here will slow down that goal.
* </b>
+ *
+ * Note that ActivityStarter logic here is deprecated and should be added here as well as
+ * {@link ActivityStarterImpl}
*/
@SysUISingleton
public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
@@ -1790,17 +1795,27 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
int flags) {
startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivity(Intent intent, boolean dismissShade) {
startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
+ @Override
+ public void startActivity(Intent intent, boolean dismissShade,
+ @androidx.annotation.Nullable ActivityLaunchAnimator.Controller animationController) {
+ startActivity(intent, dismissShade, animationController, false);
+ }
+
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivity(Intent intent, boolean dismissShade,
@Nullable ActivityLaunchAnimator.Controller animationController,
@@ -1809,6 +1824,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
getActivityUserHandle(intent));
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivity(Intent intent, boolean dismissShade,
@Nullable ActivityLaunchAnimator.Controller animationController,
@@ -2406,6 +2422,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
return mDisplayId;
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
boolean dismissShade, int flags) {
@@ -2414,12 +2431,14 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
flags, null /* animationController */, getActivityUserHandle(intent));
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
boolean dismissShade) {
startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
boolean dismissShade, boolean disallowEnterPictureInPictureWhileLaunching,
@@ -2431,6 +2450,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
userHandle, null /* customMessage */);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
@@ -2541,6 +2561,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
* animation. This is ignored if {@code animationController} is not
* animating in the shade window.
* @param isLaunchForActivity whether the launch is for an activity.
+ *
+ * Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too.
*/
@Nullable
private ActivityLaunchAnimator.Controller wrapAnimationController(
@@ -2570,6 +2592,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mStatusBarKeyguardViewManager.readyForKeyguardDone();
}
+
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void executeRunnableDismissingKeyguard(final Runnable runnable,
final Runnable cancelAction,
@@ -2580,6 +2604,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
deferred, false /* willAnimateOnKeyguard */, null /* customMessage */);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void executeRunnableDismissingKeyguard(final Runnable runnable,
final Runnable cancelAction,
@@ -2690,16 +2715,19 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
afterKeyguardGone /* afterKeyguardGone */);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
dismissKeyguardThenExecute(action, cancelAction, afterKeyguardGone, null);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone, String customMessage) {
@@ -2901,6 +2929,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
| ((currentlyInsecure ? 1 : 0) << 12);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
mMainExecutor.execute(() -> {
@@ -2910,11 +2939,13 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
});
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void postStartActivityDismissingKeyguard(PendingIntent intent) {
postStartActivityDismissingKeyguard(intent, null /* animationController */);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void postStartActivityDismissingKeyguard(final PendingIntent intent,
@Nullable ActivityLaunchAnimator.Controller animationController) {
@@ -2922,11 +2953,13 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
null /* intentSentUiThreadCallback */, animationController));
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
postStartActivityDismissingKeyguard(intent, delay, null /* animationController */);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void postStartActivityDismissingKeyguard(Intent intent, int delay,
@Nullable ActivityLaunchAnimator.Controller animationController) {
@@ -2934,6 +2967,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
null /* customMessage */);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void postStartActivityDismissingKeyguard(Intent intent, int delay,
@Nullable ActivityLaunchAnimator.Controller animationController,
@@ -4081,11 +4115,13 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
startPendingIntentDismissingKeyguard(intent, null);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startPendingIntentDismissingKeyguard(
final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) {
@@ -4093,6 +4129,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
(ActivityLaunchAnimator.Controller) null);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent,
Runnable intentSentUiThreadCallback, View associatedView) {
@@ -4106,6 +4143,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
animationController);
}
+ /** Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too. */
@Override
public void startPendingIntentDismissingKeyguard(
final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
@@ -4529,6 +4567,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
* launched as user of the current process.
* @param intent
* @return UserHandle
+ *
+ * Logic is duplicated in {@link ActivityStarterImpl}. Please add it there too.
*/
private UserHandle getActivityUserHandle(Intent intent) {
String[] packages = mContext.getResources().getStringArray(R.array.system_ui_packages);
@@ -4551,4 +4591,15 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
&& mBiometricUnlockController.getMode()
!= BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
}
+
+ @Override
+ public void setIsLaunchingActivityOverLockscreen(boolean isLaunchingActivityOverLockscreen) {
+ mIsLaunchingActivityOverLockscreen = isLaunchingActivityOverLockscreen;
+ }
+
+ @Override
+ public ActivityLaunchAnimator.Controller getAnimatorControllerFromNotification(
+ ExpandableNotificationRow associatedView) {
+ return mNotificationAnimationProvider.getAnimatorController(associatedView);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f7646d718dc6..89dddbf1f573 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -68,6 +68,7 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.TaskbarDelegate;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
@@ -284,6 +285,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean mIsBackAnimationEnabled;
private final boolean mUdfpsNewTouchDetectionEnabled;
private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
+ private final ActivityStarter mActivityStarter;
private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction;
@@ -339,7 +341,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
PrimaryBouncerInteractor primaryBouncerInteractor,
BouncerView primaryBouncerView,
AlternateBouncerInteractor alternateBouncerInteractor,
- UdfpsOverlayInteractor udfpsOverlayInteractor
+ UdfpsOverlayInteractor udfpsOverlayInteractor,
+ ActivityStarter activityStarter
) {
mContext = context;
mViewMediatorCallback = callback;
@@ -367,6 +370,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
mUdfpsNewTouchDetectionEnabled = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION);
mUdfpsOverlayInteractor = udfpsOverlayInteractor;
+ mActivityStarter = activityStarter;
}
@Override
@@ -1006,7 +1010,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void dismissAndCollapse() {
- mCentralSurfaces.executeRunnableDismissingKeyguard(null, null, true, false, true);
+ mActivityStarter.executeRunnableDismissingKeyguard(
+ /* runnable= */ null,
+ /* cancelAction= */ null,
+ /* dismissShade= */ true,
+ /* afterKeyguardGone= */ false,
+ /* deferred= */ true
+ );
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java
index 7d583258e4e5..9ea30d676dc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java
@@ -39,9 +39,9 @@ import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import org.junit.Before;
import org.junit.Test;
@@ -50,22 +50,20 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
-import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@RunWith(AndroidTestingRunner.class)
@SmallTest
public class ActionProxyReceiverTest extends SysuiTestCase {
-
- @Mock
- private CentralSurfaces mMockCentralSurfaces;
@Mock
private ActivityManagerWrapper mMockActivityManagerWrapper;
@Mock
private ScreenshotSmartActions mMockScreenshotSmartActions;
@Mock
private PendingIntent mMockPendingIntent;
+ @Mock
+ private ActivityStarter mActivityStarter;
private Intent mIntent;
private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
@@ -78,32 +76,19 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
}
@Test
- public void testPendingIntentSentWithoutStatusBar() throws PendingIntent.CanceledException {
- ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver(false);
-
- actionProxyReceiver.onReceive(mContext, mIntent);
-
- verify(mMockActivityManagerWrapper).closeSystemWindows(SYSTEM_DIALOG_REASON_SCREENSHOT);
- verify(mMockCentralSurfaces, never()).executeRunnableDismissingKeyguard(
- any(Runnable.class), any(Runnable.class), anyBoolean(), anyBoolean(), anyBoolean());
- verify(mMockPendingIntent).send(
- eq(mContext), anyInt(), isNull(), isNull(), isNull(), isNull(), any(Bundle.class));
- }
-
- @Test
public void testPendingIntentSentWithStatusBar() throws PendingIntent.CanceledException {
- ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver(true);
+ ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver();
// ensure that the pending intent call is passed through
doAnswer((Answer<Object>) invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
- }).when(mMockCentralSurfaces).executeRunnableDismissingKeyguard(
+ }).when(mActivityStarter).executeRunnableDismissingKeyguard(
any(Runnable.class), isNull(), anyBoolean(), anyBoolean(), anyBoolean());
actionProxyReceiver.onReceive(mContext, mIntent);
verify(mMockActivityManagerWrapper).closeSystemWindows(SYSTEM_DIALOG_REASON_SCREENSHOT);
- verify(mMockCentralSurfaces).executeRunnableDismissingKeyguard(
+ verify(mActivityStarter).executeRunnableDismissingKeyguard(
any(Runnable.class), isNull(), eq(true), eq(true), eq(true));
verify(mMockPendingIntent).send(
eq(mContext), anyInt(), isNull(), isNull(), isNull(), isNull(), any(Bundle.class));
@@ -111,7 +96,7 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
@Test
public void testSmartActionsNotNotifiedByDefault() {
- ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver(true);
+ ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver();
actionProxyReceiver.onReceive(mContext, mIntent);
@@ -122,7 +107,7 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
@Test
public void testSmartActionsNotifiedIfEnabled() {
- ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver(true);
+ ActionProxyReceiver actionProxyReceiver = constructActionProxyReceiver();
mIntent.putExtra(EXTRA_SMART_ACTIONS_ENABLED, true);
String testId = "testID";
mIntent.putExtra(EXTRA_ID, testId);
@@ -133,15 +118,12 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
testId, ACTION_TYPE_SHARE, false, null);
}
- private ActionProxyReceiver constructActionProxyReceiver(boolean withStatusBar) {
- if (withStatusBar) {
- return new ActionProxyReceiver(
- Optional.of(mMockCentralSurfaces), mMockActivityManagerWrapper,
- mMockScreenshotSmartActions, mDisplayTracker);
- } else {
- return new ActionProxyReceiver(
- Optional.empty(), mMockActivityManagerWrapper, mMockScreenshotSmartActions,
- mDisplayTracker);
- }
+ private ActionProxyReceiver constructActionProxyReceiver() {
+ return new ActionProxyReceiver(
+ mMockActivityManagerWrapper,
+ mMockScreenshotSmartActions,
+ mDisplayTracker,
+ mActivityStarter
+ );
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index d017ffd08a4b..2106da887b44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -11,6 +11,7 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.media.controls.ui.MediaHierarchyManager
+import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
import com.android.systemui.shade.ShadeViewController
@@ -79,6 +80,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
@Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
@Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
+ @Mock lateinit var activityStarter: ActivityStarter
@Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
@JvmField @Rule val mockito = MockitoJUnit.rule()
@@ -124,6 +126,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
dumpManager)
},
qsTransitionControllerFactory = { qsTransitionController },
+ activityStarter = activityStarter,
)
transitionController.addCallback(transitionControllerCallback)
whenever(nsslController.view).thenReturn(stackscroller)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 4bb2c8740d44..3cefc9973d09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -67,6 +67,7 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserContextProvider;
@@ -80,7 +81,6 @@ import com.android.systemui.statusbar.notification.collection.provider.HighPrior
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.wmshell.BubblesManager;
@@ -120,7 +120,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private NotificationListContainer mNotificationListContainer;
@Mock private OnSettingsClickListener mOnSettingsClickListener;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
- @Mock private CentralSurfaces mCentralSurfaces;
@Mock private AccessibilityManager mAccessibilityManager;
@Mock private HighPriorityProvider mHighPriorityProvider;
@Mock private INotificationManager mINotificationManager;
@@ -136,6 +135,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private HeadsUpManagerPhone mHeadsUpManagerPhone;
+ @Mock private ActivityStarter mActivityStarter;
@Before
public void setUp() {
@@ -145,8 +145,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
- mGutsManager = new NotificationGutsManager(mContext,
- () -> Optional.of(mCentralSurfaces), mHandler, mHandler, mAccessibilityManager,
+ mGutsManager = new NotificationGutsManager(mContext, mHandler, mHandler,
+ mAccessibilityManager,
mHighPriorityProvider, mINotificationManager,
mPeopleSpaceWidgetManager, mLauncherApps, mShortcutManager,
mChannelEditorDialogController, mContextTracker, mAssistantFeedbackController,
@@ -156,7 +156,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mStatusBarStateController,
mDeviceProvisionedController,
mMetricsLogger,
- mHeadsUpManagerPhone);
+ mHeadsUpManagerPhone, mActivityStarter);
mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
mOnSettingsClickListener);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 420c7ae3d2ec..6a0e3c6d51eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -48,6 +48,7 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.controls.ui.KeyguardMediaController;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -143,6 +144,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
@Mock private NotificationTargetsHelper mNotificationTargetsHelper;
@Mock private SecureSettings mSecureSettings;
@Mock private NotificationIconAreaController mIconAreaController;
+ @Mock private ActivityStarter mActivityStarter;
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
@@ -491,7 +493,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
mFeatureFlags,
mNotificationTargetsHelper,
mSecureSettings,
- mock(NotificationDismissibilityProvider.class)
+ mock(NotificationDismissibilityProvider.class),
+ mActivityStarter
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
new file mode 100644
index 000000000000..b6b28c9e4527
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
@@ -0,0 +1,255 @@
+/*
+ * 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.statusbar.phone
+
+import android.app.PendingIntent
+import android.content.Intent
+import android.os.RemoteException
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.assist.AssistManager
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import dagger.Lazy
+import java.util.Optional
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ActivityStarterImplTest : SysuiTestCase() {
+ @Mock private lateinit var centralSurfaces: CentralSurfaces
+ @Mock private lateinit var assistManager: AssistManager
+ @Mock private lateinit var dozeServiceHost: DozeServiceHost
+ @Mock private lateinit var biometricUnlockController: BiometricUnlockController
+ @Mock private lateinit var keyguardViewMediator: KeyguardViewMediator
+ @Mock private lateinit var shadeController: ShadeController
+ @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
+ @Mock private lateinit var lockScreenUserManager: NotificationLockscreenUserManager
+ @Mock private lateinit var statusBarWindowController: StatusBarWindowController
+ @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var activityIntentHelper: ActivityIntentHelper
+ private lateinit var underTest: ActivityStarterImpl
+ private val mainExecutor = FakeExecutor(FakeSystemClock())
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ ActivityStarterImpl(
+ Lazy { Optional.of(centralSurfaces) },
+ Lazy { assistManager },
+ Lazy { dozeServiceHost },
+ Lazy { biometricUnlockController },
+ Lazy { keyguardViewMediator },
+ Lazy { shadeController },
+ Lazy { statusBarKeyguardViewManager },
+ activityLaunchAnimator,
+ context,
+ lockScreenUserManager,
+ statusBarWindowController,
+ wakefulnessLifecycle,
+ keyguardStateController,
+ statusBarStateController,
+ keyguardUpdateMonitor,
+ deviceProvisionedController,
+ userTracker,
+ activityIntentHelper,
+ mainExecutor,
+ )
+ }
+
+ @Test
+ fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() {
+ val pendingIntent = mock(PendingIntent::class.java)
+ whenever(keyguardStateController.isShowing).thenReturn(true)
+ whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+
+ underTest.startPendingIntentDismissingKeyguard(pendingIntent)
+
+ verify(statusBarKeyguardViewManager)
+ .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null))
+ }
+
+ @Test
+ fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() {
+ val pendingIntent = mock(PendingIntent::class.java)
+ val associatedView = mock(ExpandableNotificationRow::class.java)
+
+ underTest.startPendingIntentDismissingKeyguard(
+ intent = pendingIntent,
+ intentSentUiThreadCallback = null,
+ associatedView = associatedView,
+ )
+
+ verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView)
+ }
+
+ @Test
+ fun startActivity_noUserHandleProvided_getUserHandle() {
+ val intent = mock(Intent::class.java)
+
+ underTest.startActivity(intent, false)
+
+ verify(userTracker).userHandle
+ }
+
+ @Test
+ fun postStartActivityDismissingKeyguard_pendingIntent_postsOnMain() {
+ val intent = mock(PendingIntent::class.java)
+
+ underTest.postStartActivityDismissingKeyguard(intent)
+
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ }
+
+ @Test
+ fun postStartActivityDismissingKeyguard_intent_postsOnMain() {
+ val intent = mock(Intent::class.java)
+
+ underTest.postStartActivityDismissingKeyguard(intent, 0)
+
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ }
+
+ @Test
+ fun dismissKeyguardThenExecute_startWakeAndUnlock() {
+ whenever(wakefulnessLifecycle.wakefulness)
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP)
+ whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true)
+ whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+ whenever(dozeServiceHost.isPulsing).thenReturn(true)
+
+ underTest.dismissKeyguardThenExecute({ true }, {}, false)
+
+ verify(biometricUnlockController)
+ .startWakeAndUnlock(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
+ }
+
+ @Test
+ fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() {
+ val customMessage = "Enter your pin."
+ whenever(keyguardStateController.isShowing).thenReturn(true)
+
+ underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage)
+
+ verify(statusBarKeyguardViewManager)
+ .dismissWithAction(
+ any(OnDismissAction::class.java),
+ any(Runnable::class.java),
+ eq(false),
+ eq(customMessage)
+ )
+ }
+
+ @Test
+ fun dismissKeyguardThenExecute_awakeDreams() {
+ val customMessage = "Enter your pin."
+ var dismissActionExecuted = false
+ whenever(keyguardStateController.isShowing).thenReturn(false)
+ whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true)
+
+ underTest.dismissKeyguardThenExecute(
+ {
+ dismissActionExecuted = true
+ true
+ },
+ {},
+ false,
+ customMessage
+ )
+
+ verify(centralSurfaces).awakenDreams()
+ assertThat(dismissActionExecuted).isTrue()
+ }
+
+ @Test
+ @Throws(RemoteException::class)
+ fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() {
+ whenever(keyguardStateController.isShowing).thenReturn(false)
+ whenever(keyguardStateController.isOccluded).thenReturn(false)
+ whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true)
+
+ underTest.executeRunnableDismissingKeyguard(
+ runnable = {},
+ cancelAction = null,
+ dismissShade = false,
+ afterKeyguardGone = false,
+ deferred = false
+ )
+
+ verify(centralSurfaces, times(1)).awakenDreams()
+ }
+
+ @Test
+ @Throws(RemoteException::class)
+ fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() {
+ whenever(keyguardStateController.isShowing).thenReturn(false)
+ whenever(keyguardStateController.isOccluded).thenReturn(false)
+ whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false)
+
+ underTest.executeRunnableDismissingKeyguard(
+ runnable = {},
+ cancelAction = null,
+ dismissShade = false,
+ afterKeyguardGone = false,
+ deferred = false
+ )
+
+ verify(centralSurfaces, never()).awakenDreams()
+ }
+
+ @Test
+ fun postQSRunnableDismissingKeyguard_leaveOpenStatusBarState() {
+ underTest.postQSRunnableDismissingKeyguard {}
+
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ mainExecutor.runAllReady()
+ verify(statusBarStateController).setLeaveOpenOnKeyguardHide(true)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index 872c5603b7a5..3870d996d2ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -43,6 +43,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
@@ -96,6 +97,7 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
@Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
@Mock private UserTracker mUserTracker;
@Mock private QSHost mQSHost;
+ @Mock private ActivityStarter mActivityStarter;
CentralSurfacesCommandQueueCallbacks mSbcqCallbacks;
@@ -131,7 +133,8 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
mSystemBarAttributesListener,
mCameraLauncherLazy,
mUserTracker,
- mQSHost);
+ mQSHost,
+ mActivityStarter);
when(mUserTracker.getUserHandle()).thenReturn(
UserHandle.of(ActivityManager.getCurrentUser()));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 4ff225cc7f3f..6be0e2deaf35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -72,6 +72,7 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.TaskbarDelegate;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
@@ -129,6 +130,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private UdfpsOverlayInteractor mUdfpsOverlayInteractor;
+ @Mock private ActivityStarter mActivityStarter;
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
@@ -192,7 +194,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mPrimaryBouncerInteractor,
mBouncerView,
mAlternateBouncerInteractor,
- mUdfpsOverlayInteractor) {
+ mUdfpsOverlayInteractor,
+ mActivityStarter) {
@Override
public ViewRootImpl getViewRootImpl() {
return mViewRootImpl;
@@ -680,7 +683,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mPrimaryBouncerInteractor,
mBouncerView,
mAlternateBouncerInteractor,
- mUdfpsOverlayInteractor) {
+ mUdfpsOverlayInteractor,
+ mActivityStarter) {
@Override
public ViewRootImpl getViewRootImpl() {
return mViewRootImpl;