Merge "Adds StatusBarNotificationActivityStarterTest"
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java
new file mode 100644
index 0000000..2b62e04
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 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;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import java.util.List;
+
+/**
+ * Contains useful methods for querying properties of an Activity Intent.
+ */
+public class ActivityIntentHelper {
+
+ private final Context mContext;
+
+ public ActivityIntentHelper(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Determines if sending the given intent would result in starting an Intent resolver activity,
+ * instead of resolving to a specific component.
+ *
+ * @param intent the intent
+ * @param currentUserId the id for the user to resolve as
+ * @return true if the intent would launch a resolver activity
+ */
+ public boolean wouldLaunchResolverActivity(Intent intent, int currentUserId) {
+ ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, currentUserId,
+ false /* onlyDirectBootAware */);
+ return targetActivityInfo == null;
+ }
+
+ /**
+ * Returns info about the target Activity of a given intent, or null if the intent does not
+ * resolve to a specific component meeting the requirements.
+ *
+ * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must
+ * be direct boot aware when in direct boot mode if false, all packages are considered
+ * a match even if they are not aware.
+ * @return the target activity info of the intent it resolves to a specific package or
+ * {@code null} if it resolved to the resolver activity
+ */
+ public ActivityInfo getTargetActivityInfo(Intent intent, int currentUserId,
+ boolean onlyDirectBootAware) {
+ PackageManager packageManager = mContext.getPackageManager();
+ int flags = PackageManager.MATCH_DEFAULT_ONLY;
+ if (!onlyDirectBootAware) {
+ flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+ }
+ final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
+ intent, flags, currentUserId);
+ if (appList.size() == 0) {
+ return null;
+ }
+ ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
+ flags | PackageManager.GET_META_DATA, currentUserId);
+ if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
+ return null;
+ } else {
+ return resolved.activityInfo;
+ }
+ }
+
+ /**
+ * Determines if the given intent resolves to an Activity which is allowed to appear above
+ * the lock screen.
+ *
+ * @param intent the intent to resolve
+ * @return true if the launched Activity would appear above the lock screen
+ */
+ public boolean wouldShowOverLockscreen(Intent intent, int currentUserId) {
+ ActivityInfo targetActivityInfo = getTargetActivityInfo(intent,
+ currentUserId, false /* onlyDirectBootAware */);
+ return targetActivityInfo != null
+ && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED
+ | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0;
+ }
+
+ /**
+ * Determines if sending the given intent would result in starting an Intent resolver activity,
+ * instead of resolving to a specific component.
+ *
+ * @param resolved the resolveInfo for the intent as returned by resolveActivityAsUser
+ * @param appList a list of resolveInfo as returned by queryIntentActivitiesAsUser
+ * @return true if the intent would launch a resolver activity
+ */
+ public boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
+ // If the list contains the above resolved activity, then it can't be
+ // ResolverActivity itself.
+ for (int i = 0; i < appList.size(); i++) {
+ ResolveInfo tmp = appList.get(i);
+ if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
+ && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 847f3ff..800ae58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -67,6 +67,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -170,6 +171,7 @@
private boolean mDozing;
private int mIndicationBottomMargin;
private float mDarkAmount;
+ private ActivityIntentHelper mActivityIntentHelper;
public KeyguardBottomAreaView(Context context) {
this(context, null);
@@ -235,6 +237,8 @@
protected void onFinishInflate() {
super.onFinishInflate();
mLockPatternUtils = new LockPatternUtils(mContext);
+ mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
+ new ActivityIntentHelper(mContext));
mPreviewContainer = findViewById(R.id.preview_container);
mOverlayContainer = findViewById(R.id.overlay_container);
mRightAffordanceView = findViewById(R.id.camera_button);
@@ -254,7 +258,6 @@
mLockIcon.update();
setClipChildren(false);
setClipToPadding(false);
- mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
inflateCameraPreview();
mLockIcon.setOnClickListener(this);
mLockIcon.setOnLongClickListener(this);
@@ -266,6 +269,7 @@
mAccessibilityController = Dependency.get(AccessibilityController.class);
mAssistManager = Dependency.get(AssistManager.class);
mLockIcon.setAccessibilityController(mAccessibilityController);
+ mActivityIntentHelper = new ActivityIntentHelper(getContext());
updateLeftAffordance();
}
@@ -459,7 +463,7 @@
public void bindCameraPrewarmService() {
Intent intent = getCameraIntent();
- ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
+ ActivityInfo targetInfo = mActivityIntentHelper.getTargetActivityInfo(intent,
KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
if (targetInfo != null && targetInfo.metaData != null) {
String clazz = targetInfo.metaData.getString(
@@ -500,8 +504,8 @@
public void launchCamera(String source) {
final Intent intent = getCameraIntent();
intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
- boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
- mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
+ boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity(
+ intent, KeyguardUpdateMonitor.getCurrentUser());
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
AsyncTask.execute(new Runnable() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 319a504..5d52359 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -25,6 +25,7 @@
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
@@ -126,6 +127,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.AutoReinflateContainer;
import com.android.systemui.DemoMode;
@@ -219,7 +221,6 @@
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
@@ -586,11 +587,12 @@
mEntryManager.updateNotifications();
updateScrimController();
};
+ private ActivityIntentHelper mActivityIntentHelper;
@Override
public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
- Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
+ Dependency.get(MAIN_HANDLER).post(() -> {
mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active);
});
}
@@ -635,6 +637,7 @@
mNavigationBarController = Dependency.get(NavigationBarController.class);
mBubbleController = Dependency.get(BubbleController.class);
mBubbleController.setExpandListener(mBubbleExpandListener);
+ mActivityIntentHelper = new ActivityIntentHelper(mContext);
KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
if (sliceProvider != null) {
sliceProvider.initDependencies(mMediaManager, mStatusBarStateController);
@@ -1069,7 +1072,8 @@
mRemoteInputManager, mStatusBarRemoteInputCallback, mGroupManager,
mLockscreenUserManager, shadeController, mKeyguardMonitor,
mNotificationInterruptionStateProvider, mMetricsLogger,
- new LockPatternUtils(mContext));
+ new LockPatternUtils(mContext), Dependency.get(MAIN_HANDLER),
+ mActivityIntentHelper);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
@@ -2449,8 +2453,8 @@
final Callback callback, int flags) {
if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
- final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
- mContext, intent, mLockscreenUserManager.getCurrentUserId());
+ final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
+ intent, mLockscreenUserManager.getCurrentUserId());
Runnable runnable = () -> {
mAssistManager.hideAssist();
intent.setFlags(
@@ -4315,7 +4319,7 @@
public void startPendingIntentDismissingKeyguard(
final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) {
final boolean afterKeyguardGone = intent.isActivity()
- && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+ && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
executeActionDismissingKeyguard(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 7e45507..215f5c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
import android.app.ActivityManager;
@@ -29,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
+import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -43,6 +43,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.UiOffloadThread;
@@ -65,7 +66,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.PreviewInflater;
/**
* Status bar implementation of {@link NotificationActivityStarter}.
@@ -97,6 +97,8 @@
private final IStatusBarService mBarService;
private final CommandQueue mCommandQueue;
private final IDreamManager mDreamManager;
+ private final Handler mMainThreadHandler;
+ private final ActivityIntentHelper mActivityIntentHelper;
private boolean mIsCollapsingToShowActivityOverLockscreen;
@@ -121,7 +123,9 @@
KeyguardMonitor keyguardMonitor,
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
MetricsLogger metricsLogger,
- LockPatternUtils lockPatternUtils) {
+ LockPatternUtils lockPatternUtils,
+ Handler mainThreadHandler,
+ ActivityIntentHelper activityIntentHelper) {
mContext = context;
mNotificationPanel = panel;
mPresenter = presenter;
@@ -150,6 +154,8 @@
}
});
mStatusBarRemoteInputCallback = remoteInputCallback;
+ mMainThreadHandler = mainThreadHandler;
+ mActivityIntentHelper = activityIntentHelper;
}
/**
@@ -176,12 +182,11 @@
boolean isActivityIntent = intent.isActivity();
final boolean afterKeyguardGone = isActivityIntent
- && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+ && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
final boolean wasOccluded = mShadeController.isOccluded();
boolean showOverLockscreen = mKeyguardMonitor.isShowing()
- && PreviewInflater.wouldShowOverLockscreen(mContext,
- intent.getIntent(),
+ && mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction =
() -> handleNotificationClickAfterKeyguardDismissed(
@@ -358,7 +363,7 @@
mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
if (shouldCollapse()) {
// Putting it back on the main thread, since we're touching views
- Dependency.get(MAIN_HANDLER).post(() -> mCommandQueue.animateCollapsePanels(
+ mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
}
});
@@ -425,7 +430,7 @@
if (Looper.getMainLooper().isCurrentThread()) {
mShadeController.collapsePanel();
} else {
- Dependency.get(MAIN_HANDLER).post(mShadeController::collapsePanel);
+ mMainThreadHandler.post(mShadeController::collapsePanel);
}
}
@@ -444,7 +449,7 @@
private void removeNotification(StatusBarNotification notification) {
// We have to post it to the UI thread for synchronization
- Dependency.get(MAIN_HANDLER).post(() -> {
+ mMainThreadHandler.post(() -> {
Runnable removeRunnable =
() -> mEntryManager.performRemoveNotification(notification);
if (mPresenter.isCollapsing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 21d9dcc..471d511 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -33,6 +33,7 @@
import android.view.View;
import android.view.ViewParent;
+import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -46,7 +47,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.PreviewInflater;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -64,6 +64,7 @@
Dependency.get(NotificationLockscreenUserManager.class);
private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
private final Context mContext;
+ private final ActivityIntentHelper mActivityIntentHelper;
private View mPendingWorkRemoteInputView;
private View mPendingRemoteInputView;
private final ShadeController mShadeController = Dependency.get(ShadeController.class);
@@ -83,6 +84,7 @@
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mCommandQueue = getComponent(context, CommandQueue.class);
mCommandQueue.addCallback(this);
+ mActivityIntentHelper = new ActivityIntentHelper(mContext);
}
@Override
@@ -220,8 +222,8 @@
NotificationRemoteInputManager.ClickHandler defaultHandler) {
final boolean isActivity = pendingIntent.isActivity();
if (isActivity) {
- final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
- mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
+ final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
+ pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
mActivityStarter.dismissKeyguardThenExecute(() -> {
try {
ActivityManager.getService().resumeAppSwitches();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index 92034b2..3d31714 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -19,7 +19,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
@@ -29,6 +28,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
import java.util.List;
@@ -41,13 +41,16 @@
private static final String TAG = "PreviewInflater";
private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
+ private final ActivityIntentHelper mActivityIntentHelper;
private Context mContext;
private LockPatternUtils mLockPatternUtils;
- public PreviewInflater(Context context, LockPatternUtils lockPatternUtils) {
+ public PreviewInflater(Context context, LockPatternUtils lockPatternUtils,
+ ActivityIntentHelper activityIntentHelper) {
mContext = context;
mLockPatternUtils = lockPatternUtils;
+ mActivityIntentHelper = activityIntentHelper;
}
public View inflatePreview(Intent intent) {
@@ -130,7 +133,7 @@
ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
flags | PackageManager.GET_META_DATA,
KeyguardUpdateMonitor.getCurrentUser());
- if (wouldLaunchResolverActivity(resolved, appList)) {
+ if (mActivityIntentHelper.wouldLaunchResolverActivity(resolved, appList)) {
return null;
}
if (resolved == null || resolved.activityInfo == null) {
@@ -140,63 +143,6 @@
resolved.activityInfo.metaData);
}
- public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
- int currentUserId) {
- return getTargetActivityInfo(ctx, intent, currentUserId, false /* onlyDirectBootAware */)
- == null;
- }
-
- public static boolean wouldShowOverLockscreen(Context ctx, Intent intent, int currentUserId) {
- ActivityInfo targetActivityInfo = getTargetActivityInfo(ctx, intent, currentUserId,
- false /* onlyDirectBootAware */);
- return targetActivityInfo != null
- && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED
- | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0;
- }
-
- /**
- * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must
- * be direct boot aware when in direct boot mode if false, all
- * packages are considered a match even if they are not aware.
- * @return the target activity info of the intent it resolves to a specific package or
- * {@code null} if it resolved to the resolver activity
- */
- public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent,
- int currentUserId, boolean onlyDirectBootAware) {
- PackageManager packageManager = ctx.getPackageManager();
- int flags = PackageManager.MATCH_DEFAULT_ONLY;
- if (!onlyDirectBootAware) {
- flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
- }
- final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
- intent, flags, currentUserId);
- if (appList.size() == 0) {
- return null;
- }
- ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- flags | PackageManager.GET_META_DATA, currentUserId);
- if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
- return null;
- } else {
- return resolved.activityInfo;
- }
- }
-
- private static boolean wouldLaunchResolverActivity(
- ResolveInfo resolved, List<ResolveInfo> appList) {
- // If the list contains the above resolved activity, then it can't be
- // ResolverActivity itself.
- for (int i = 0; i < appList.size(); i++) {
- ResolveInfo tmp = appList.get(i);
- if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
- && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
- return false;
- }
- }
- return true;
- }
-
private static class WidgetInfo {
String contextPackage;
int layoutId;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 63b6673..c9b550c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -35,6 +35,7 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -89,6 +90,8 @@
private BubbleController.BubbleStateChangeListener mBubbleStateChangeListener;
@Mock
private BubbleController.BubbleExpandListener mBubbleExpandListener;
+ @Mock
+ NotificationVisibility mNotificationVisibility;
@Mock
private PendingIntent mDeleteIntent;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
new file mode 100644
index 0000000..20af1ac
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2019 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 static org.mockito.AdditionalAnswers.answerVoid;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.dreams.IDreamManager;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.ActivityIntentHelper;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
+
+ @Mock
+ private AssistManager mAssistManager;
+ @Mock
+ private NotificationEntryManager mEntryManager;
+ @Mock
+ private ActivityStarter mActivityStarter;
+ @Mock
+ private IStatusBarService mStatusBarService;
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
+ @Mock
+ private NotificationRemoteInputManager mRemoteInputManager;
+ @Mock
+ private RemoteInputController mRemoteInputController;
+ @Mock
+ private ShadeController mShadeController;
+ @Mock
+ private KeyguardMonitor mKeyguardMonitor;
+ @Mock
+ private Handler mHandler;
+
+ @Mock
+ private ActivityIntentHelper mActivityIntentHelper;
+ @Mock
+ private PendingIntent mContentIntent;
+ @Mock
+ private NotificationData mNotificationData;
+ @Mock
+ private NotificationEntry mNotificationEntry;
+ @Mock
+ private NotificationEntry mBubbleEntry;
+
+ private NotificationActivityStarter mNotificationActivityStarter;
+
+ private NotificationTestHelper mNotificationTestHelper;
+ ExpandableNotificationRow mNotificationRow;
+
+ private final Answer<Void> mCallOnDismiss = answerVoid(
+ (ActivityStarter.OnDismissAction dismissAction, Runnable cancel,
+ Boolean afterKeyguardGone) -> dismissAction.onDismiss());
+ private ArrayList<NotificationEntry> mActiveNotifications;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
+ when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+
+ mActiveNotifications = new ArrayList<>();
+ mActiveNotifications.add(mNotificationEntry);
+ mActiveNotifications.add(mBubbleEntry);
+ when(mNotificationData.getActiveNotifications()).thenReturn(mActiveNotifications);
+ when(mNotificationEntry.getRow()).thenReturn(mNotificationRow);
+
+ mNotificationTestHelper = new NotificationTestHelper(mContext);
+ mNotificationRow = mNotificationTestHelper.createRow();
+
+ mNotificationActivityStarter = new StatusBarNotificationActivityStarter(getContext(),
+ mock(CommandQueue.class), mAssistManager, mock(NotificationPanelView.class),
+ mock(NotificationPresenter.class), mEntryManager, mock(HeadsUpManagerPhone.class),
+ mActivityStarter, mock(ActivityLaunchAnimator.class), mStatusBarService,
+ mock(StatusBarStateController.class), mock(KeyguardManager.class),
+ mock(IDreamManager.class), mRemoteInputManager,
+ mock(StatusBarRemoteInputCallback.class), mock(NotificationGroupManager.class),
+ mock(NotificationLockscreenUserManager.class), mShadeController, mKeyguardMonitor,
+ mock(NotificationInterruptionStateProvider.class), mock(MetricsLogger.class),
+ mock(LockPatternUtils.class), mHandler, mActivityIntentHelper);
+
+
+ when(mContentIntent.isActivity()).thenReturn(true);
+ when(mContentIntent.getCreatorUserHandle()).thenReturn(UserHandle.of(1));
+
+ // SBNActivityStarter expects contentIntent or fullScreenIntent to be set
+ mNotificationRow.getEntry().notification.getNotification().contentIntent = mContentIntent;
+
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+
+ // set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
+ doAnswer(mCallOnDismiss).when(mActivityStarter).dismissKeyguardThenExecute(
+ any(ActivityStarter.OnDismissAction.class), any(), anyBoolean());
+
+ // set up addAfterKeyguardGoneRunnable to synchronously invoke the Runnable arg
+ doAnswer(answerVoid(Runnable::run))
+ .when(mShadeController).addAfterKeyguardGoneRunnable(any(Runnable.class));
+
+ // set up addPostCollapseAction to synchronously invoke the Runnable arg
+ doAnswer(answerVoid(Runnable::run))
+ .when(mShadeController).addPostCollapseAction(any(Runnable.class));
+
+ // set up Handler to synchronously invoke the Runnable arg
+ doAnswer(answerVoid(Runnable::run))
+ .when(mHandler).post(any(Runnable.class));
+ }
+
+ @Test
+ public void testOnNotificationClicked_whileKeyguardVisible()
+ throws PendingIntent.CanceledException, RemoteException {
+ // Given
+ when(mKeyguardMonitor.isShowing()).thenReturn(true);
+ when(mShadeController.isOccluded()).thenReturn(true);
+ when(mContentIntent.isActivity()).thenReturn(true);
+ when(mActivityIntentHelper.wouldShowOverLockscreen(any(Intent.class), anyInt()))
+ .thenReturn(false);
+ when(mActivityIntentHelper.wouldLaunchResolverActivity(any(Intent.class), anyInt()))
+ .thenReturn(false);
+
+ StatusBarNotification statusBarNotification = mNotificationRow.getEntry().notification;
+ statusBarNotification.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
+
+ // When
+ mNotificationActivityStarter.onNotificationClicked(statusBarNotification,
+ mNotificationRow);
+
+ // Then
+ verify(mActivityStarter).dismissKeyguardThenExecute(
+ any(ActivityStarter.OnDismissAction.class),
+ any() /* cancel */,
+ anyBoolean() /* afterKeyguardGone */);
+
+ verify(mShadeController, atLeastOnce()).collapsePanel();
+
+ verify(mContentIntent).sendAndReturnResult(
+ any(Context.class),
+ anyInt() /* code */,
+ any() /* fillInIntent */,
+ any() /* PendingIntent.OnFinished */,
+ any() /* Handler */,
+ any() /* requiredPermission */,
+ any() /* Bundle options */);
+
+ verify(mAssistManager).hideAssist();
+
+ verify(mStatusBarService).onNotificationClick(
+ eq(mNotificationRow.getEntry().key), any(NotificationVisibility.class));
+
+ // Notification is removed due to FLAG_AUTO_CANCEL
+ verify(mEntryManager).performRemoveNotification(eq(statusBarNotification));
+ }
+}