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

Commit 25dbc2cb authored by Richard MacGregor's avatar Richard MacGregor
Browse files

Use dev option to disable notification protections

Bug: 316955558
Bug: 316954829
Flag: ACONFIG com.android.server.notification.sensitive_notification_app_protection DISABLED
Flag: ACONFIG com.android.server.notification.screenshare_notification_hiding DISABLED
Test: atest SensitiveContentProtectionManagerServiceTest
Test: atest SensitiveNotificationProtectionControllerTest
Change-Id: Ie84e64414b952cea89fe01f3311de0d4af0a92fe
parent 8f5970f5
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.policy;

import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;

import static com.android.server.notification.Flags.screenshareNotificationHiding;

import android.annotation.MainThread;
@@ -37,6 +39,7 @@ import com.android.systemui.dagger.qualifiers.Main;
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.settings.GlobalSettings;

import java.util.concurrent.Executor;

@@ -47,6 +50,7 @@ import javax.inject.Inject;
public class SensitiveNotificationProtectionControllerImpl
        implements SensitiveNotificationProtectionController {
    private static final String LOG_TAG = "SNPC";
    private final GlobalSettings mGlobalSettings;
    private final ArraySet<String> mExemptPackages = new ArraySet<>();
    private final ListenerSet<Runnable> mListeners = new ListenerSet<>();
    private volatile MediaProjectionInfo mProjection;
@@ -58,6 +62,17 @@ public class SensitiveNotificationProtectionControllerImpl
                public void onStart(MediaProjectionInfo info) {
                    Trace.beginSection("SNPC.onProjectionStart");
                    try {
                        // TODO(b/324447419): move GlobalSettings lookup to background thread
                        boolean disableScreenShareProtections =
                                mGlobalSettings.getInt(
                                        DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
                                        0) != 0;
                        if (disableScreenShareProtections) {
                            Log.w(LOG_TAG,
                                    "Screen share protections disabled, ignoring projectionstart");
                            return;
                        }

                        // Only enable sensitive content protection if sharing full screen
                        // Launch cookie only set (non-null) if sharing single app/task
                        updateProjectionStateAndNotifyListeners(
@@ -81,10 +96,13 @@ public class SensitiveNotificationProtectionControllerImpl
    @Inject
    public SensitiveNotificationProtectionControllerImpl(
            Context context,
            GlobalSettings settings,
            MediaProjectionManager mediaProjectionManager,
            IActivityManager activityManager,
            @Main Handler mainHandler,
            @Background Executor bgExecutor) {
        mGlobalSettings = settings;

        if (!screenshareNotificationHiding()) {
            return;
        }
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest
import com.android.server.notification.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.settings.FakeGlobalSettings
import com.android.systemui.util.time.FakeSystemClock
import org.junit.Before
import org.junit.Test
@@ -49,6 +50,7 @@ class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase(
        controller =
            SensitiveNotificationProtectionControllerImpl(
                mContext,
                FakeGlobalSettings(),
                mediaProjectionManager,
                activityManager,
                handler,
+23 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.app.Notification
import android.media.projection.MediaProjectionInfo
import android.media.projection.MediaProjectionManager
import android.platform.test.annotations.EnableFlags
import android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS
import android.service.notification.StatusBarNotification
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -33,6 +34,7 @@ import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.concurrency.mockExecutorHandler
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.settings.FakeGlobalSettings
import com.android.systemui.util.time.FakeSystemClock
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
@@ -61,6 +63,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
    @Mock private lateinit var listener2: Runnable
    @Mock private lateinit var listener3: Runnable

    private lateinit var globalSettings: FakeGlobalSettings
    private lateinit var mediaProjectionCallback: MediaProjectionManager.Callback
    private lateinit var controller: SensitiveNotificationProtectionControllerImpl

@@ -74,10 +77,11 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
            .thenReturn(listOf(BUGREPORT_PACKAGE_NAME))

        val executor = FakeExecutor(FakeSystemClock())

        globalSettings = FakeGlobalSettings()
        controller =
            SensitiveNotificationProtectionControllerImpl(
                mContext,
                globalSettings,
                mediaProjectionManager,
                activityManager,
                mockExecutorHandler(executor),
@@ -228,6 +232,14 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
        assertFalse(controller.isSensitiveStateActive)
    }

    @Test
    fun isSensitiveStateActive_projectionActive_disabledViaDevOption_false() {
        globalSettings.putInt(DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 1)
        mediaProjectionCallback.onStart(mediaProjectionInfo)

        assertFalse(controller.isSensitiveStateActive)
    }

    @Test
    fun shouldProtectNotification_projectionInactive_false() {
        val notificationEntry = mock(NotificationEntry::class.java)
@@ -294,6 +306,16 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() {
        assertFalse(controller.shouldProtectNotification(notificationEntry))
    }

    @Test
    fun shouldProtectNotification_projectionActive_disabledViaDevOption_false() {
        globalSettings.putInt(DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 1)
        mediaProjectionCallback.onStart(mediaProjectionInfo)

        val notificationEntry = setupNotificationEntry(TEST_PROJECTION_PACKAGE_NAME)

        assertFalse(controller.shouldProtectNotification(notificationEntry))
    }

    private fun setShareFullScreen() {
        whenever(mediaProjectionInfo.packageName).thenReturn(TEST_PROJECTION_PACKAGE_NAME)
        whenever(mediaProjectionInfo.launchCookie).thenReturn(null)
+13 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server;

import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.NonNull;
@@ -24,11 +26,10 @@ import android.content.ComponentName;
import android.content.Context;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
@@ -117,7 +118,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic

        // TODO(b/317250444): use MediaProjectionManagerService directly, reduces unnecessary
        //  handler, delegate, and binder death recipient
        mProjectionManager.addCallback(mProjectionCallback, new Handler(Looper.getMainLooper()));
        mProjectionManager.addCallback(mProjectionCallback, getContext().getMainThreadHandler());

        try {
            mNotificationListener.registerAsSystemService(
@@ -148,6 +149,15 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
    }

    private void onProjectionStart() {
        // TODO(b/324447419): move GlobalSettings lookup to background thread
        boolean disableScreenShareProtections =
                Settings.Global.getInt(getContext().getContentResolver(),
                        DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 0) != 0;
        if (disableScreenShareProtections) {
            Log.w(TAG, "Screen share protections disabled, ignoring projection start");
            return;
        }

        synchronized (mSensitiveContentProtectionLock) {
            mProjectionActive = true;
            updateAppsThatShouldBlockScreenCapture();
+58 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;

import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
import android.provider.Settings;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
@@ -390,6 +391,16 @@ public class SensitiveContentProtectionManagerServiceTest {
        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
    }

    @Test
    public void mediaProjectionOnStart_disabledViaDevOption_noBlockedPackages() {
        mockDisabledViaDevelopOption();
        setupSensitiveNotification();

        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));

        verifyZeroInteractions(mWindowManager);
    }

    @Test
    public void nlsOnListenerConnected_projectionNotStarted_noop() {
        // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
@@ -483,6 +494,18 @@ public class SensitiveContentProtectionManagerServiceTest {
        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
    }

    @Test
    public void nlsOnListenerConnected_disabledViaDevOption_noBlockedPackages() {
        mockDisabledViaDevelopOption();
        // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
        // as non-sensitive
        setupSensitiveNotification();
        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
        mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected();

        verifyZeroInteractions(mWindowManager);
    }

    @Test
    public void nlsOnNotificationRankingUpdate_projectionNotStarted_noop() {
        // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
@@ -598,6 +621,19 @@ public class SensitiveContentProtectionManagerServiceTest {
        verify(mWindowManager).addBlockScreenCaptureForApps(EMPTY_SET);
    }

    @Test
    public void nlsOnNotificationRankingUpdate_disabledViaDevOption_noBlockedPackages() {
        mockDisabledViaDevelopOption();
        // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
        // as non-sensitive
        setupSensitiveNotification();
        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
        mSensitiveContentProtectionManagerService.mNotificationListener
                .onNotificationRankingUpdate(mRankingMap);

        verifyZeroInteractions(mWindowManager);
    }

    @Test
    public void nlsOnNotificationPosted_projectionNotStarted_noop() {
        // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
@@ -697,4 +733,26 @@ public class SensitiveContentProtectionManagerServiceTest {

        verifyZeroInteractions(mWindowManager);
    }

    @Test
    public void nlsOnNotificationPosted_disabledViaDevOption_noBlockedPackages() {
        mockDisabledViaDevelopOption();
        // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2
        // as non-sensitive
        setupSensitiveNotification();
        mMediaProjectionCallbackCaptor.getValue().onStart(mock(MediaProjectionInfo.class));
        mSensitiveContentProtectionManagerService.mNotificationListener
                .onNotificationPosted(mNotification1, mRankingMap);

        verifyZeroInteractions(mWindowManager);
    }

    private void mockDisabledViaDevelopOption() {
        // mContext (TestableContext) uses [TestableSettingsProvider] and it will be cleared after
        // the test
        Settings.Global.putInt(
                mContext.getContentResolver(),
                Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
                1);
    }
}