Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b2331cb authored by Mark Renouf's avatar Mark Renouf
Browse files

Adds StatusBarNotificationActivityStarterTest

This change includes a refactoring to extract static methods from
PreviewInflater into a seperate class to allow for easier testing.

This allows tests to bypas interaction with package manager.

Test: atest SystemUITests
Change-Id: I3211395e7eb78351106cabd8c473f11f06bb0f97
parent e05cda09
Loading
Loading
Loading
Loading
+119 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+8 −4
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
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 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
    private boolean mDozing;
    private int mIndicationBottomMargin;
    private float mDarkAmount;
    private ActivityIntentHelper mActivityIntentHelper;

    public KeyguardBottomAreaView(Context context) {
        this(context, null);
@@ -235,6 +237,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
    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 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
        mLockIcon.update();
        setClipChildren(false);
        setClipToPadding(false);
        mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
        inflateCameraPreview();
        mLockIcon.setOnClickListener(this);
        mLockIcon.setOnLongClickListener(this);
@@ -266,6 +269,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
        mAccessibilityController = Dependency.get(AccessibilityController.class);
        mAssistManager = Dependency.get(AssistManager.class);
        mLockIcon.setAccessibilityController(mAccessibilityController);
        mActivityIntentHelper = new ActivityIntentHelper(getContext());
        updateLeftAffordance();
    }

@@ -459,7 +463,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL

    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 class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
    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
+10 −6
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.app.StatusBarManager.WindowVisibleState;
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.internal.widget.LockPatternUtils;
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.KeyguardMonitor;
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 @@ public class StatusBar extends SystemUI implements DemoMode,
                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 @@ public class StatusBar extends SystemUI implements DemoMode,
        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 @@ public class StatusBar extends SystemUI implements DemoMode,
                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 @@ public class StatusBar extends SystemUI implements DemoMode,
            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 class StatusBar extends SystemUI implements DemoMode,
    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(() -> {
+14 −9
Original line number Diff line number Diff line
@@ -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.app.TaskStackBuilder;
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.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.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.UiOffloadThread;
@@ -65,7 +66,6 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger;
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 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
    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 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
            KeyguardMonitor keyguardMonitor,
            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
            MetricsLogger metricsLogger,
            LockPatternUtils lockPatternUtils) {
            LockPatternUtils lockPatternUtils,
            Handler mainThreadHandler,
            ActivityIntentHelper activityIntentHelper) {
        mContext = context;
        mNotificationPanel = panel;
        mPresenter = presenter;
@@ -150,6 +154,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
            }
        });
        mStatusBarRemoteInputCallback = remoteInputCallback;
        mMainThreadHandler = mainThreadHandler;
        mActivityIntentHelper = activityIntentHelper;
    }

    /**
@@ -176,12 +182,11 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit

        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 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
                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 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
        if (Looper.getMainLooper().isCurrentThread()) {
            mShadeController.collapsePanel();
        } else {
            Dependency.get(MAIN_HANDLER).post(mShadeController::collapsePanel);
            mMainThreadHandler.post(mShadeController::collapsePanel);
        }
    }

@@ -444,7 +449,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit

    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()) {
+5 −3
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.UserHandle;
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.SysuiStatusBarStateController;
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 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
            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 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
        mKeyguardManager = context.getSystemService(KeyguardManager.class);
        mCommandQueue = getComponent(context, CommandQueue.class);
        mCommandQueue.addCallback(this);
        mActivityIntentHelper = new ActivityIntentHelper(mContext);
    }

    @Override
@@ -220,8 +222,8 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
            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();
Loading