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

Commit af94319d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add a debug mode that allows disabling notifications for all packages that aren't allowed."

parents ea3257d7 115db918
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.provider.DebugModeFilterProvider;

import javax.inject.Inject;

@@ -44,6 +45,7 @@ import javax.inject.Inject;
@SysUISingleton
public class NotificationFilter {

    private final DebugModeFilterProvider mDebugNotificationFilter;
    private final StatusBarStateController mStatusBarStateController;
    private final KeyguardEnvironment mKeyguardEnvironment;
    private final ForegroundServiceController mForegroundServiceController;
@@ -52,11 +54,13 @@ public class NotificationFilter {

    @Inject
    public NotificationFilter(
            DebugModeFilterProvider debugNotificationFilter,
            StatusBarStateController statusBarStateController,
            KeyguardEnvironment keyguardEnvironment,
            ForegroundServiceController foregroundServiceController,
            NotificationLockscreenUserManager userManager,
            MediaFeatureFlag mediaFeatureFlag) {
        mDebugNotificationFilter = debugNotificationFilter;
        mStatusBarStateController = statusBarStateController;
        mKeyguardEnvironment = keyguardEnvironment;
        mForegroundServiceController = foregroundServiceController;
@@ -69,6 +73,10 @@ public class NotificationFilter {
     */
    public boolean shouldFilterOut(NotificationEntry entry) {
        final StatusBarNotification sbn = entry.getSbn();
        if (mDebugNotificationFilter.shouldFilterOut(entry)) {
            return true;
        }

        if (!(mKeyguardEnvironment.isDeviceProvisioned()
                || showNotificationEvenIfUnprovisioned(sbn))) {
            return true;
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.collection.coordinator

import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.provider.DebugModeFilterProvider
import javax.inject.Inject

/** A small coordinator which filters out notifications from non-allowed apps. */
@CoordinatorScope
class DebugModeCoordinator @Inject constructor(
    private val debugModeFilterProvider: DebugModeFilterProvider
) : Coordinator {

    override fun attach(pipeline: NotifPipeline) {
        pipeline.addPreGroupFilter(preGroupFilter)
        debugModeFilterProvider.registerInvalidationListener(preGroupFilter::invalidateList)
    }

    private val preGroupFilter = object : NotifFilter("DebugModeCoordinator") {
        override fun shouldFilterOut(entry: NotificationEntry, now: Long) =
            debugModeFilterProvider.shouldFilterOut(entry)
    }
}
 No newline at end of file
+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ class NotifCoordinatorsImpl @Inject constructor(
    gutsCoordinator: GutsCoordinator,
    communalCoordinator: CommunalCoordinator,
    conversationCoordinator: ConversationCoordinator,
    debugModeCoordinator: DebugModeCoordinator,
    groupCountCoordinator: GroupCountCoordinator,
    mediaCoordinator: MediaCoordinator,
    preparationCoordinator: PreparationCoordinator,
@@ -86,6 +87,7 @@ class NotifCoordinatorsImpl @Inject constructor(
        mCoordinators.add(deviceProvisionedCoordinator)
        mCoordinators.add(bubbleCoordinator)
        mCoordinators.add(communalCoordinator)
        mCoordinators.add(debugModeCoordinator)
        mCoordinators.add(conversationCoordinator)
        mCoordinators.add(groupCountCoordinator)
        mCoordinators.add(mediaCoordinator)
+126 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.collection.provider

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.util.Log
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.util.Assert
import com.android.systemui.util.ListenerSet
import com.android.systemui.util.isNotEmpty
import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject

/**
 * A debug mode provider which is used by both the legacy and new notification pipelines to
 * block unwanted notifications from appearing to the user, primarily for integration testing.
 *
 * The only configuration is a list of allowed packages.  When this list is empty, the feature is
 * disabled.  When SystemUI starts up, this feature is disabled.
 *
 * To enabled filtering, provide the list of packages in a comma-separated list using the command:
 *
 * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE
 *          --esal allowed_packages <comma-separated-packages>`
 *
 * To disable filtering, send the action without a list:
 *
 * `$ adb shell am broadcast -a com.android.systemui.action.SET_NOTIF_DEBUG_MODE`
 *
 * NOTE: this feature only works on debug builds, and when the broadcaster is root.
 */
@SysUISingleton
class DebugModeFilterProvider @Inject constructor(
    private val context: Context,
    dumpManager: DumpManager
) : Dumpable {
    private var allowedPackages: List<String> = emptyList()
    private val listeners = ListenerSet<Runnable>()

    init {
        dumpManager.registerDumpable(this)
    }

    /**
     * Register a runnable to be invoked when the allowed packages changes, which would mean the
     * result of [shouldFilterOut] may have changed for some entries.
     */
    fun registerInvalidationListener(listener: Runnable) {
        Assert.isMainThread()
        if (!Build.isDebuggable()) {
            return
        }
        val needsInitialization = listeners.isEmpty()
        listeners.addIfAbsent(listener)
        if (needsInitialization) {
            val filter = IntentFilter().apply { addAction(ACTION_SET_NOTIF_DEBUG_MODE) }
            val permission = NOTIF_DEBUG_MODE_PERMISSION
            context.registerReceiver(mReceiver, filter, permission, null)
            Log.d(TAG, "Registered: $mReceiver")
        }
    }

    /**
     * Determine if the given entry should be hidden from the user in debug mode.
     * Will always return false in release.
     */
    fun shouldFilterOut(entry: NotificationEntry): Boolean {
        if (allowedPackages.isEmpty()) {
            return false
        }
        return entry.sbn.packageName !in allowedPackages
    }

    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
        pw.println("initialized: ${listeners.isNotEmpty()}")
        pw.println("allowedPackages: ${allowedPackages.size}")
        allowedPackages.forEachIndexed { i, pkg ->
            pw.println("  [$i]: $pkg")
        }
    }

    private val mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent?) {
            val action = intent?.action
            if (ACTION_SET_NOTIF_DEBUG_MODE == action) {
                allowedPackages = intent.extras?.getStringArrayList(EXTRA_ALLOWED_PACKAGES)
                    ?: emptyList()
                Log.d(TAG, "Updated allowedPackages: $allowedPackages")
                listeners.forEach(Runnable::run)
            } else {
                Log.d(TAG, "Malformed intent: $intent")
            }
        }
    }

    companion object {
        private const val TAG = "DebugModeFilterProvider"
        private const val ACTION_SET_NOTIF_DEBUG_MODE =
            "com.android.systemui.action.SET_NOTIF_DEBUG_MODE"
        private const val NOTIF_DEBUG_MODE_PERMISSION =
            "com.android.systemui.permission.NOTIF_DEBUG_MODE"
        private const val EXTRA_ALLOWED_PACKAGES = "allowed_packages"
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.provider.DebugModeFilterProvider
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.interruption.HeadsUpController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
@@ -65,6 +66,7 @@ class NotificationsControllerImpl @Inject constructor(
    private val notifPipelineFlags: NotifPipelineFlags,
    private val notificationListener: NotificationListener,
    private val entryManager: NotificationEntryManager,
    private val debugModeFilterProvider: DebugModeFilterProvider,
    private val legacyRanker: NotificationRankingManager,
    private val commonNotifCollection: Lazy<CommonNotifCollection>,
    private val notifPipeline: Lazy<NotifPipeline>,
@@ -134,6 +136,9 @@ class NotificationsControllerImpl @Inject constructor(
            headsUpController.attach(entryManager, headsUpManager)
            groupManagerLegacy.get().setHeadsUpManager(headsUpManager)
            groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
            debugModeFilterProvider.registerInvalidationListener {
                entryManager.updateNotifications("debug mode filter changed")
            }

            entryManager.initialize(notificationListener, legacyRanker)
        }
Loading