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

Commit 29d7eab0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Log clicks on notification actions" into rvc-dev am: 906f8000

Change-Id: Ib94f5c7273a56658c8b90530c57d850c2b68b1b4
parents 605b0f8b 906f8000
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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

import android.app.PendingIntent
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.NotifInteractionLog
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import javax.inject.Inject

/**
 * Logger class for events related to the user clicking on notification actions
 */
class ActionClickLogger @Inject constructor(
    @NotifInteractionLog private val buffer: LogBuffer
) {
    fun logInitialClick(
        entry: NotificationEntry?,
        pendingIntent: PendingIntent
    ) {
        buffer.log(TAG, LogLevel.DEBUG, {
            str1 = entry?.key
            str2 = entry?.ranking?.channel?.id
            str3 = pendingIntent.intent.toString()
        }, {
            "ACTION CLICK $str1 (channel=$str2) for pending intent $str3"
        })
    }

    fun logRemoteInputWasHandled(
        entry: NotificationEntry?
    ) {
        buffer.log(TAG, LogLevel.DEBUG, {
            str1 = entry?.key
        }, {
            "  [Action click] Triggered remote input (for $str1))"
        })
    }

    fun logStartingIntentWithDefaultHandler(
        entry: NotificationEntry?,
        pendingIntent: PendingIntent
    ) {
        buffer.log(TAG, LogLevel.DEBUG, {
            str1 = entry?.key
            str2 = pendingIntent.intent.toString()
        }, {
            "  [Action click] Launching intent $str2 via default handler (for $str1)"
        })
    }

    fun logWaitingToCloseKeyguard(
        pendingIntent: PendingIntent
    ) {
        buffer.log(TAG, LogLevel.DEBUG, {
            str1 = pendingIntent.intent.toString()
        }, {
            "  [Action click] Intent $str1 launches an activity, dismissing keyguard first..."
        })
    }

    fun logKeyguardGone(
        pendingIntent: PendingIntent
    ) {
        buffer.log(TAG, LogLevel.DEBUG, {
            str1 = pendingIntent.intent.toString()
        }, {
            "  [Action click] Keyguard dismissed, calling default handler for intent $str1"
        })
    }
}

private const val TAG = "ActionClickLogger"
 No newline at end of file
+19 −8
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -114,6 +114,7 @@ public class NotificationRemoteInputManager implements Dumpable {
    private final SmartReplyController mSmartReplyController;
    private final NotificationEntryManager mEntryManager;
    private final Handler mMainHandler;
    private final ActionClickLogger mLogger;

    private final Lazy<StatusBar> mStatusBarLazy;

@@ -138,14 +139,18 @@ public class NotificationRemoteInputManager implements Dumpable {
            mStatusBarLazy.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view,
                    "NOTIFICATION_CLICK");

            final NotificationEntry entry = getNotificationForParent(view.getParent());
            mLogger.logInitialClick(entry, pendingIntent);

            if (handleRemoteInput(view, pendingIntent)) {
                mLogger.logRemoteInputWasHandled(entry);
                return true;
            }

            if (DEBUG) {
                Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
            }
            logActionClick(view, pendingIntent);
            logActionClick(view, entry, pendingIntent);
            // The intent we are sending is for the application, which
            // won't have permission to immediately start an activity after
            // the user switches to home.  We know it is safe to do at this
@@ -158,11 +163,15 @@ public class NotificationRemoteInputManager implements Dumpable {
                Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view);
                options.second.setLaunchWindowingMode(
                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
                mLogger.logStartingIntentWithDefaultHandler(entry, pendingIntent);
                return RemoteViews.startPendingIntent(view, pendingIntent, options);
            });
        }

        private void logActionClick(View view, PendingIntent actionIntent) {
        private void logActionClick(
                View view,
                NotificationEntry entry,
                PendingIntent actionIntent) {
            Integer actionIndex = (Integer)
                    view.getTag(com.android.internal.R.id.notification_action_index_tag);
            if (actionIndex == null) {
@@ -170,7 +179,7 @@ public class NotificationRemoteInputManager implements Dumpable {
                return;
            }
            ViewParent parent = view.getParent();
            StatusBarNotification statusBarNotification = getNotificationForParent(parent);
            StatusBarNotification statusBarNotification = entry.getSbn();
            if (statusBarNotification == null) {
                Log.w(TAG, "Couldn't determine notification for click.");
                return;
@@ -212,10 +221,10 @@ public class NotificationRemoteInputManager implements Dumpable {
            }
        }

        private StatusBarNotification getNotificationForParent(ViewParent parent) {
        private NotificationEntry getNotificationForParent(ViewParent parent) {
            while (parent != null) {
                if (parent instanceof ExpandableNotificationRow) {
                    return ((ExpandableNotificationRow) parent).getEntry().getSbn();
                    return ((ExpandableNotificationRow) parent).getEntry();
                }
                parent = parent.getParent();
            }
@@ -255,7 +264,7 @@ public class NotificationRemoteInputManager implements Dumpable {
    };

    /**
     * Injected constructor. See {@link StatusBarModule}.
     * Injected constructor. See {@link StatusBarDependenciesModule}.
     */
    public NotificationRemoteInputManager(
            Context context,
@@ -265,13 +274,15 @@ public class NotificationRemoteInputManager implements Dumpable {
            Lazy<StatusBar> statusBarLazy,
            StatusBarStateController statusBarStateController,
            @Main Handler mainHandler,
            RemoteInputUriController remoteInputUriController) {
            RemoteInputUriController remoteInputUriController,
            ActionClickLogger logger) {
        mContext = context;
        mLockscreenUserManager = lockscreenUserManager;
        mSmartReplyController = smartReplyController;
        mEntryManager = notificationEntryManager;
        mStatusBarLazy = statusBarLazy;
        mMainHandler = mainHandler;
        mLogger = logger;
        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+5 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.ActionClickLogger;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.MediaArtworkProcessor;
import com.android.systemui.statusbar.NotificationListener;
@@ -73,7 +74,8 @@ public interface StatusBarDependenciesModule {
            Lazy<StatusBar> statusBarLazy,
            StatusBarStateController statusBarStateController,
            Handler mainHandler,
            RemoteInputUriController remoteInputUriController) {
            RemoteInputUriController remoteInputUriController,
            ActionClickLogger actionClickLogger) {
        return new NotificationRemoteInputManager(
                context,
                lockscreenUserManager,
@@ -82,7 +84,8 @@ public interface StatusBarDependenciesModule {
                statusBarLazy,
                statusBarStateController,
                mainHandler,
                remoteInputUriController);
                remoteInputUriController,
                actionClickLogger);
    }

    /** */
+8 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.view.ViewParent;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.ActionClickLogger;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -73,6 +74,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
    private View mPendingRemoteInputView;
    private KeyguardManager mKeyguardManager;
    private final CommandQueue mCommandQueue;
    private final ActionClickLogger mActionClickLogger;
    private int mDisabled2;
    protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver();
    private Handler mMainHandler = new Handler();
@@ -87,7 +89,8 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
            StatusBarStateController statusBarStateController,
            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
            ActivityStarter activityStarter, ShadeController shadeController,
            CommandQueue commandQueue) {
            CommandQueue commandQueue,
            ActionClickLogger clickLogger) {
        mContext = context;
        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
        mShadeController = shadeController;
@@ -101,6 +104,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
        mKeyguardManager = context.getSystemService(KeyguardManager.class);
        mCommandQueue = commandQueue;
        mCommandQueue.addCallback(this);
        mActionClickLogger = clickLogger;
        mActivityIntentHelper = new ActivityIntentHelper(mContext);
        mGroupManager = groupManager;
        // Listen to onKeyguardShowingChanged in case a managed profile needs to be unlocked
@@ -304,9 +308,12 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
            NotificationRemoteInputManager.ClickHandler defaultHandler) {
        final boolean isActivity = pendingIntent.isActivity();
        if (isActivity) {
            mActionClickLogger.logWaitingToCloseKeyguard(pendingIntent);
            final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
                    pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
            mActivityStarter.dismissKeyguardThenExecute(() -> {
                mActionClickLogger.logKeyguardGone(pendingIntent);

                try {
                    ActivityManager.getService().resumeAppSwitches();
                } catch (RemoteException e) {
+16 −6
Original line number Diff line number Diff line
@@ -82,7 +82,8 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
                () -> mock(StatusBar.class),
                mStateController,
                Handler.createAsync(Looper.myLooper()),
                mRemoteInputUriController);
                mRemoteInputUriController,
                mock(ActionClickLogger.class));
        mEntry = new NotificationEntryBuilder()
                .setPkg(TEST_PACKAGE_NAME)
                .setOpPkg(TEST_PACKAGE_NAME)
@@ -256,17 +257,26 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {

    private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {

        TestableNotificationRemoteInputManager(Context context,
        TestableNotificationRemoteInputManager(
                Context context,
                NotificationLockscreenUserManager lockscreenUserManager,
                SmartReplyController smartReplyController,
                NotificationEntryManager notificationEntryManager,
                Lazy<StatusBar> statusBarLazy,
                StatusBarStateController statusBarStateController,
                Handler mainHandler,
                RemoteInputUriController remoteInputUriController) {
            super(context, lockscreenUserManager, smartReplyController, notificationEntryManager,
                    statusBarLazy, statusBarStateController, mainHandler,
                    remoteInputUriController);
                RemoteInputUriController remoteInputUriController,
                ActionClickLogger actionClickLogger) {
            super(
                    context,
                    lockscreenUserManager,
                    smartReplyController,
                    notificationEntryManager,
                    statusBarLazy,
                    statusBarStateController,
                    mainHandler,
                    remoteInputUriController,
                    actionClickLogger);
        }

        public void setUpWithPresenterForTest(Callback callback,
Loading