diff options
3 files changed, 102 insertions, 18 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java index 0d53277e51dc..40bb67f2e746 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java @@ -34,6 +34,7 @@ import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.service.notification.StatusBarNotification; +import android.telephony.TelephonyManager; import android.util.ArraySet; import android.util.Log; @@ -62,7 +63,10 @@ public class SensitiveNotificationProtectionControllerImpl private static final String LOG_TAG = "SNPC"; private final SensitiveNotificationProtectionControllerLogger mLogger; private final PackageManager mPackageManager; - private final ArraySet<String> mExemptPackages = new ArraySet<>(); + // Packages exempt from projection session protections (if they start a projection session) + private final ArraySet<String> mSessionProtectionExemptPackages = new ArraySet<>(); + // Packages exempt from individual notification protections (if they post a notification) + private final ArraySet<String> mNotificationProtectionExemptPackages = new ArraySet<>(); private final ListenerSet<Runnable> mListeners = new ListenerSet<>(); private volatile MediaProjectionInfo mProjection; private SensitiveNotificatioMediaProjectionSession mActiveMediaProjectionSession; @@ -161,6 +165,7 @@ public class SensitiveNotificationProtectionControllerImpl MediaProjectionManager mediaProjectionManager, IActivityManager activityManager, PackageManager packageManager, + TelephonyManager telephonyManager, @Main Handler mainHandler, @Background Executor bgExecutor, SensitiveNotificationProtectionControllerLogger logger) { @@ -191,26 +196,18 @@ public class SensitiveNotificationProtectionControllerImpl bgExecutor.execute(() -> developerOptionsObserver.onChange(true)); bgExecutor.execute(() -> { - ArraySet<String> exemptPackages = new ArraySet<>(); - // Exempt SystemUI - exemptPackages.add(context.getPackageName()); + ArraySet<String> sessionProtectionExemptPackages = + getSessionProtectionExemptPackages(context, activityManager); - // Exempt approved bug report handlers - try { - exemptPackages.addAll(activityManager.getBugreportWhitelistedPackages()); - } catch (RemoteException e) { - Log.e( - LOG_TAG, - "Error adding bug report handlers to exemption, continuing without", - e); - // silent failure, skip adding packages to exemption - } + ArraySet<String> notificationProtectionExemptPackages = + getNotificationProtectionExemptPackages(telephonyManager); // if currently projecting, notify listeners of exemption changes mainHandler.post(() -> { Trace.beginSection("SNPC.exemptPackagesUpdated"); try { - updateExemptPackagesAndNotifyListeners(exemptPackages); + updateExemptPackagesAndNotifyListeners(sessionProtectionExemptPackages, + notificationProtectionExemptPackages); } finally { Trace.endSection(); } @@ -220,15 +217,66 @@ public class SensitiveNotificationProtectionControllerImpl mediaProjectionManager.addCallback(mMediaProjectionCallback, mainHandler); } + @NonNull + private static ArraySet<String> getSessionProtectionExemptPackages(Context context, + IActivityManager activityManager) { + ArraySet<String> sessionProtectionExemptPackages = new ArraySet<>(); + // Exempt SystemUI + sessionProtectionExemptPackages.add(context.getPackageName()); + + // Exempt approved bug report handlers + try { + sessionProtectionExemptPackages.addAll( + activityManager.getBugreportWhitelistedPackages()); + } catch (RemoteException e) { + Log.w( + LOG_TAG, + "Error adding bug report handlers to exemption, continuing without", + e); + // silent failure, skip adding packages to exemption + } + return sessionProtectionExemptPackages; + } + + @NonNull + private static ArraySet<String> getNotificationProtectionExemptPackages( + TelephonyManager telephonyManager) { + ArraySet<String> notificationProtectionExemptPackages = new ArraySet<>(); + + // Get Emergency Assistance Package, all notifications from this package should not be + // hidden/redacted. + if (screenshareNotificationHidingBugFix()) { + try { + String emergencyAssistancePackageName = + telephonyManager.getEmergencyAssistancePackageName(); + if (emergencyAssistancePackageName != null) { + notificationProtectionExemptPackages.add(emergencyAssistancePackageName); + } + } catch (IllegalStateException e) { + Log.w( + LOG_TAG, + "Error adding emergency assistance package to exemption", + e); + // silent failure, skip adding packages to exemption + } + } + return notificationProtectionExemptPackages; + } + /** * Notify listeners of possible ProjectionState change regardless of current * isSensitiveStateActive value. Method used to ensure updates occur after mExemptPackages gets * updated, which directly changes the outcome of isSensitiveStateActive */ @MainThread - private void updateExemptPackagesAndNotifyListeners(ArraySet<String> exemptPackages) { + private void updateExemptPackagesAndNotifyListeners( + ArraySet<String> sessionProtectionExemptPackages, + ArraySet<String> notificationProtectionExemptPackages) { Assert.isMainThread(); - mExemptPackages.addAll(exemptPackages); + mSessionProtectionExemptPackages.addAll(sessionProtectionExemptPackages); + if (screenshareNotificationHidingBugFix()) { + mNotificationProtectionExemptPackages.addAll(notificationProtectionExemptPackages); + } if (mProjection != null) { updateProjectionStateAndNotifyListeners(mProjection); @@ -258,7 +306,8 @@ public class SensitiveNotificationProtectionControllerImpl if (mDisableScreenShareProtections) { Log.w(LOG_TAG, "Screen share protections disabled"); return null; - } else if (info != null && mExemptPackages.contains(info.getPackageName())) { + } else if (info != null + && mSessionProtectionExemptPackages.contains(info.getPackageName())) { Log.w(LOG_TAG, "Screen share protections exempt for package " + info.getPackageName()); return null; } else if (info != null && canRecordSensitiveContent(info.getPackageName())) { @@ -322,6 +371,11 @@ public class SensitiveNotificationProtectionControllerImpl return false; // do not hide/redact notifications from system uid } + if (screenshareNotificationHidingBugFix() + && mNotificationProtectionExemptPackages.contains(sbn.getPackageName())) { + return false; // do not hide/redact notifications from emergency app + } + // Only protect/redact notifications if the developer has not explicitly set notification // visibility as public and users has not adjusted default channel visibility to private boolean notificationRequestsRedaction = entry.isNotificationVisibilityPrivate(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt index 358709f48ea8..3e20f689569e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt @@ -21,6 +21,7 @@ import android.content.pm.PackageManager import android.media.projection.MediaProjectionManager import android.os.Handler import android.platform.test.annotations.DisableFlags +import android.telephony.TelephonyManager import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.server.notification.Flags @@ -46,6 +47,7 @@ class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase( @Mock private lateinit var activityManager: IActivityManager @Mock private lateinit var mediaProjectionManager: MediaProjectionManager @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var telephonyManager: TelephonyManager private lateinit var controller: SensitiveNotificationProtectionControllerImpl @Before @@ -59,6 +61,7 @@ class SensitiveNotificationProtectionControllerFlagDisabledTest : SysuiTestCase( mediaProjectionManager, activityManager, packageManager, + telephonyManager, handler, FakeExecutor(FakeSystemClock()), logger diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt index 4ace163164f1..2127057522a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt @@ -37,6 +37,7 @@ import android.platform.test.annotations.RequiresFlagsDisabled import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS +import android.telephony.TelephonyManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest @@ -89,6 +90,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { @Mock private lateinit var activityManager: IActivityManager @Mock private lateinit var mediaProjectionManager: MediaProjectionManager @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var telephonyManager: TelephonyManager @Mock private lateinit var listener1: Runnable @Mock private lateinit var listener2: Runnable @Mock private lateinit var listener3: Runnable @@ -141,6 +143,9 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { whenever(packageManager.checkPermission(anyString(), anyString())) .thenReturn(PackageManager.PERMISSION_DENIED) + whenever(telephonyManager.getEmergencyAssistancePackageName()) + .thenReturn(EMERGENCY_ASSISTANCE_PACKAGE_NAME) + executor = FakeExecutor(FakeSystemClock()) globalSettings = FakeGlobalSettings() controller = @@ -150,6 +155,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { mediaProjectionManager, activityManager, packageManager, + telephonyManager, mockExecutorHandler(executor), executor, logger @@ -407,6 +413,26 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { } @Test + @DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX) + fun shouldProtectNotification_projectionActive_isFromEmergencyPackage_fixDisabled_true() { + mediaProjectionCallback.onStart(mediaProjectionInfo) + + val notificationEntry = setupNotificationEntry(EMERGENCY_ASSISTANCE_PACKAGE_NAME) + + assertTrue(controller.shouldProtectNotification(notificationEntry)) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX) + fun shouldProtectNotification_projectionActive_isFromEmergencyPackage_false() { + mediaProjectionCallback.onStart(mediaProjectionInfo) + + val notificationEntry = setupNotificationEntry(EMERGENCY_ASSISTANCE_PACKAGE_NAME) + + assertFalse(controller.shouldProtectNotification(notificationEntry)) + } + + @Test fun shouldProtectNotification_projectionActive_sysuiExempt_false() { // SystemUi context package name is exempt, but in test scenarios its // com.android.systemui.tests so use that instead of hardcoding @@ -742,6 +768,7 @@ class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { private const val TEST_PROJECTION_PACKAGE_NAME = "com.android.systemui.statusbar.policy.projectionpackage" private const val TEST_PACKAGE_NAME = "com.android.systemui.statusbar.policy.testpackage" + private const val EMERGENCY_ASSISTANCE_PACKAGE_NAME = "com.android.test.emergencyassistance" private const val BUGREPORT_PACKAGE_NAME = "com.android.test.bugreporthandler" } } |