diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 13c3ededbcd7421bc67324cf8cdaa54ec1e2fe8f..7505372fe295e27f5fa6f0c9794488a481d91c70 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6558,6 +6558,13 @@ public abstract class Context {
     @SystemApi
     public static final String ECM_ENHANCED_CONFIRMATION_SERVICE = "ecm_enhanced_confirmation";
 
+    /**
+     * Service to protect sensitive content during screen share.
+     * @hide
+     */
+    public static final String SENSITIVE_CONTENT_PROTECTION_SERVICE =
+            "sensitive_content_protection_service";
+
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.provider.ContactKeysManager} to managing contact keys.
diff --git a/core/java/android/view/ISensitiveContentProtectionManager.aidl b/core/java/android/view/ISensitiveContentProtectionManager.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..c135ae4b6a9550fcf84b5c213f3a4f9ef4c772c6
--- /dev/null
+++ b/core/java/android/view/ISensitiveContentProtectionManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 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 android.view;
+
+import android.os.IBinder;
+
+/**
+ * @hide
+ */
+oneway interface ISensitiveContentProtectionManager {
+    /**
+     * Block projection for a package's window when the window is showing sensitive content on
+     * the screen, the projection is unblocked when the window no more shows sensitive content.
+     *
+     * @param windowToken window where the content is shown.
+     * @param packageName package name.
+     * @param isShowingSensitiveContent whether the window is showing sensitive content.
+     */
+    void setSensitiveContentProtection(in IBinder windowToken, in String packageName,
+            in boolean isShowingSensitiveContent);
+}
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
index fff283dd41bcaf7677e9db3c57ccbe64b2d20e23..0904c47b61f235a7f36348846ffbefcf339d0f10 100644
--- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
+++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
@@ -18,14 +18,17 @@ package com.android.server;
 
 import static android.permission.flags.Flags.sensitiveNotificationAppProtection;
 import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;
-import static com.android.internal.util.Preconditions.checkNotNull;
+import static android.view.flags.Flags.sensitiveContentAppProtection;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManagerInternal;
 import android.media.projection.MediaProjectionInfo;
 import android.media.projection.MediaProjectionManager;
+import android.os.Binder;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -35,29 +38,30 @@ import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 import android.util.Log;
+import android.view.ISensitiveContentProtectionManager;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.wm.SensitiveContentPackages.PackageInfo;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.util.Objects;
 import java.util.Set;
 
 /**
- * Service that monitors for notifications with sensitive content and protects content from screen
- * sharing
+ * This service protects sensitive content from screen sharing. The service monitors notifications
+ * for sensitive content and protects from screen share. The service also protects sensitive
+ * content rendered on screen during screen share.
  */
 public final class SensitiveContentProtectionManagerService extends SystemService {
     private static final String TAG = "SensitiveContentProtect";
     private static final boolean DEBUG = false;
-    private static final boolean sNotificationProtectionEnabled =
-            sensitiveNotificationAppProtection();
 
     @VisibleForTesting
     @Nullable
     NotificationListener mNotificationListener;
-    private @Nullable MediaProjectionManager mProjectionManager;
-    private @Nullable WindowManagerInternal mWindowManager;
+    @Nullable private MediaProjectionManager mProjectionManager;
+    @Nullable private WindowManagerInternal mWindowManager;
 
     final Object mSensitiveContentProtectionLock = new Object();
 
@@ -92,7 +96,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
 
     public SensitiveContentProtectionManagerService(@NonNull Context context) {
         super(context);
-        if (sNotificationProtectionEnabled) {
+        if (sensitiveNotificationAppProtection()) {
             mNotificationListener = new NotificationListener();
         }
     }
@@ -110,14 +114,18 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
 
         init(getContext().getSystemService(MediaProjectionManager.class),
                 LocalServices.getService(WindowManagerInternal.class));
+        if (sensitiveContentAppProtection()) {
+            publishBinderService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE,
+                    new SensitiveContentProtectionManagerServiceBinder());
+        }
     }
 
     @VisibleForTesting
     void init(MediaProjectionManager projectionManager, WindowManagerInternal windowManager) {
         if (DEBUG) Log.d(TAG, "init");
 
-        checkNotNull(projectionManager, "Failed to get valid MediaProjectionManager");
-        checkNotNull(windowManager, "Failed to get valid WindowManagerInternal");
+        Objects.requireNonNull(projectionManager);
+        Objects.requireNonNull(windowManager);
 
         mProjectionManager = projectionManager;
         mWindowManager = windowManager;
@@ -126,7 +134,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
         //  handler, delegate, and binder death recipient
         mProjectionManager.addCallback(mProjectionCallback, getContext().getMainThreadHandler());
 
-        if (sNotificationProtectionEnabled) {
+        if (sensitiveNotificationAppProtection()) {
             try {
                 mNotificationListener.registerAsSystemService(
                         getContext(),
@@ -144,7 +152,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
         if (mProjectionManager != null) {
             mProjectionManager.removeCallback(mProjectionCallback);
         }
-        if (sNotificationProtectionEnabled) {
+        if (sensitiveNotificationAppProtection()) {
             try {
                 mNotificationListener.unregisterAsSystemService();
             } catch (RemoteException e) {
@@ -169,7 +177,7 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
 
         synchronized (mSensitiveContentProtectionLock) {
             mProjectionActive = true;
-            if (sNotificationProtectionEnabled) {
+            if (sensitiveNotificationAppProtection()) {
                 updateAppsThatShouldBlockScreenCapture();
             }
         }
@@ -305,4 +313,74 @@ public final class SensitiveContentProtectionManagerService extends SystemServic
             }
         }
     }
+
+    /**
+     * Block projection for a package window when the window is showing sensitive content on
+     * the screen, the projection is unblocked when window no more shows sensitive content.
+     *
+     * @param windowToken window where the content is shown.
+     * @param packageName package name.
+     * @param uid uid of the package.
+     * @param isShowingSensitiveContent whether the window is showing sensitive content.
+     */
+    @VisibleForTesting
+    void setSensitiveContentProtection(IBinder windowToken, String packageName, int uid,
+            boolean isShowingSensitiveContent) {
+        synchronized (mSensitiveContentProtectionLock) {
+            if (!mProjectionActive) {
+                return;
+            }
+            if (DEBUG) {
+                Log.d(TAG, "setSensitiveContentProtection - windowToken=" + windowToken
+                        + ", package=" + packageName + ", uid=" + uid
+                        + ", isShowingSensitiveContent=" + isShowingSensitiveContent);
+            }
+
+            // The window token distinguish this package from packages added for notifications.
+            PackageInfo packageInfo = new PackageInfo(packageName, uid, windowToken);
+            ArraySet<PackageInfo> packageInfos = new ArraySet<>();
+            packageInfos.add(packageInfo);
+            if (isShowingSensitiveContent) {
+                mWindowManager.addBlockScreenCaptureForApps(packageInfos);
+            } else {
+                mWindowManager.removeBlockScreenCaptureForApps(packageInfos);
+            }
+        }
+    }
+
+    private final class SensitiveContentProtectionManagerServiceBinder
+            extends ISensitiveContentProtectionManager.Stub {
+        private final PackageManagerInternal mPackageManagerInternal;
+
+        SensitiveContentProtectionManagerServiceBinder() {
+            mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+        }
+
+        public void setSensitiveContentProtection(IBinder windowToken, String packageName,
+                boolean isShowingSensitiveContent) {
+            Trace.beginSection(
+                    "SensitiveContentProtectionManagerService.setSensitiveContentProtection");
+            try {
+                int callingUid = Binder.getCallingUid();
+                verifyCallingPackage(callingUid, packageName);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    SensitiveContentProtectionManagerService.this.setSensitiveContentProtection(
+                            windowToken, packageName, callingUid, isShowingSensitiveContent);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            } finally {
+                Trace.endSection();
+            }
+        }
+
+        private void verifyCallingPackage(int callingUid, String callingPackage) {
+            if (mPackageManagerInternal.getPackageUid(
+                    callingPackage, 0, UserHandle.getUserId(callingUid)) != callingUid) {
+                throw new SecurityException("Specified calling package [" + callingPackage
+                        + "] does not match the calling uid " + callingUid);
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/SensitiveContentPackages.java b/services/core/java/com/android/server/wm/SensitiveContentPackages.java
index 5fe48d12d4988e312504d737daec050429f93c36..9ab11b8059a75e8ce3eaa6f7e3f10d27fdfe9322 100644
--- a/services/core/java/com/android/server/wm/SensitiveContentPackages.java
+++ b/services/core/java/com/android/server/wm/SensitiveContentPackages.java
@@ -16,9 +16,16 @@
 
 package com.android.server.wm;
 
+import static android.permission.flags.Flags.sensitiveNotificationAppProtection;
+import static android.view.flags.Flags.sensitiveContentAppProtection;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
 import android.util.ArraySet;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.PrintWriter;
 import java.util.Objects;
 
@@ -29,12 +36,26 @@ import java.util.Objects;
 public class SensitiveContentPackages {
     private final ArraySet<PackageInfo> mProtectedPackages = new ArraySet<>();
 
-    /** Returns {@code true} if package/uid pair should be blocked from screen capture */
-    public boolean shouldBlockScreenCaptureForApp(String pkg, int uid) {
+    /**
+     * Returns {@code true} if package/uid/window combination should be blocked
+     * from screen capture.
+     */
+    public boolean shouldBlockScreenCaptureForApp(String pkg, int uid, IBinder windowToken) {
+        if (!(sensitiveContentAppProtection() || sensitiveNotificationAppProtection())) {
+            return false;
+        }
+
         for (int i = 0; i < mProtectedPackages.size(); i++) {
             PackageInfo info = mProtectedPackages.valueAt(i);
             if (info != null && info.mPkg.equals(pkg) && info.mUid == uid) {
-                return true;
+                // sensitiveContentAppProtection blocks specific window where sensitive content
+                // is rendered, whereas sensitiveNotificationAppProtection blocks the package
+                // if the package has a sensitive notification.
+                if ((sensitiveContentAppProtection() && windowToken == info.getWindowToken())
+                        || (sensitiveNotificationAppProtection() && info.getWindowToken() == null)
+                ) {
+                    return true;
+                }
             }
         }
         return false;
@@ -73,31 +94,50 @@ public class SensitiveContentPackages {
      */
     public boolean clearBlockedApps() {
         if (mProtectedPackages.isEmpty()) {
-            // set was already empty
             return false;
         }
         mProtectedPackages.clear();
         return true;
     }
 
+    /**
+     * @return the size of protected packages.
+     */
+    @VisibleForTesting
+    public int size() {
+        return mProtectedPackages.size();
+    }
+
     void dump(PrintWriter pw) {
         final String innerPrefix = "  ";
         pw.println("SensitiveContentPackages:");
         pw.println(innerPrefix + "Packages that should block screen capture ("
                 + mProtectedPackages.size() + "):");
         for (PackageInfo info : mProtectedPackages) {
-            pw.println(innerPrefix + "  package=" + info.mPkg + "  uid=" + info.mUid);
+            pw.println(innerPrefix + "  package=" + info.mPkg + "  uid=" + info.mUid
+                    + " windowToken=" + info.mWindowToken);
         }
     }
 
-    /** Helper class that represents a package/uid pair */
+    /**
+     * Helper class that represents a package, uid, and window token combination, window token
+     * is set to block screen capture at window level.
+     */
     public static class PackageInfo {
-        private String mPkg;
-        private int mUid;
+        private final String mPkg;
+        private final int mUid;
+
+        @Nullable
+        private final IBinder mWindowToken;
 
         public PackageInfo(String pkg, int uid) {
+            this(pkg, uid, null);
+        }
+
+        public PackageInfo(String pkg, int uid, IBinder windowToken) {
             this.mPkg = pkg;
             this.mUid = uid;
+            this.mWindowToken = windowToken;
         }
 
         @Override
@@ -105,12 +145,30 @@ public class SensitiveContentPackages {
             if (this == o) return true;
             if (!(o instanceof PackageInfo)) return false;
             PackageInfo that = (PackageInfo) o;
-            return mUid == that.mUid && Objects.equals(mPkg, that.mPkg);
+            return mUid == that.mUid && Objects.equals(mPkg, that.mPkg)
+                    && Objects.equals(mWindowToken, that.mWindowToken);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mPkg, mUid);
+            return Objects.hash(mPkg, mUid, mWindowToken);
+        }
+
+        public IBinder getWindowToken() {
+            return mWindowToken;
+        }
+
+        public int getUid() {
+            return mUid;
+        }
+
+        public String getPkg() {
+            return mPkg;
+        }
+
+        @Override
+        public String toString() {
+            return "package=" + mPkg + "  uid=" + mUid + " windowToken=" + mWindowToken;
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 934f8a73a19d92c5ec1eb41886ad5aa094cd515c..0e1641a0edbd0f4602a0172272518db0d3c66582 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1897,11 +1897,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
             return true;
         }
 
-        if (android.permission.flags.Flags.sensitiveNotificationAppProtection()) {
-            if (mWmService.mSensitiveContentPackages
-                    .shouldBlockScreenCaptureForApp(getOwningPackage(), getOwningUid())) {
-                return true;
-            }
+        // block screen capture to protect sensitive notifications or content on the screen.
+        if (mWmService.mSensitiveContentPackages.shouldBlockScreenCaptureForApp(
+                getOwningPackage(), getOwningUid(), getWindowToken())) {
+            return true;
         }
 
         return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId);
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..dad36e787360d22ea9b56368a50f235ecc3a3ed3
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceContentTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2024 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.server;
+
+import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.media.projection.MediaProjectionInfo;
+import android.media.projection.MediaProjectionManager;
+import android.os.Binder;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wm.SensitiveContentPackages.PackageInfo;
+import com.android.server.wm.WindowManagerInternal;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_APP_PROTECTION)
+/**
+ * Test {@link SensitiveContentProtectionManagerService} for sensitive on screen content
+ * protection, the service protects sensitive content during screen share.
+ */
+public class SensitiveContentProtectionManagerServiceContentTest {
+    private final PackageInfo mPackageInfo =
+            new PackageInfo("test.package", 12345, new Binder());
+    private SensitiveContentProtectionManagerService mSensitiveContentProtectionManagerService;
+    private MediaProjectionManager.Callback mMediaPorjectionCallback;
+
+    @Mock private WindowManagerInternal mWindowManager;
+    @Mock private MediaProjectionManager mProjectionManager;
+    @Mock private MediaProjectionInfo mMediaProjectionInfo;
+
+    @Captor
+    private ArgumentCaptor<MediaProjectionManager.Callback> mMediaProjectionCallbackCaptor;
+    @Captor
+    private ArgumentCaptor<ArraySet<PackageInfo>> mPackageInfoCaptor;
+
+    @Rule
+    public final TestableContext mContext =
+            new TestableContext(getInstrumentation().getTargetContext(), null);
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mSensitiveContentProtectionManagerService =
+                new SensitiveContentProtectionManagerService(mContext);
+        mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager);
+        verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any());
+        mMediaPorjectionCallback = mMediaProjectionCallbackCaptor.getValue();
+    }
+
+    @Test
+    public void testBlockAppWindowForScreenCapture() {
+        mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
+        mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+                mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
+        verify(mWindowManager, atLeast(1))
+                .addBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+        assertThat(mPackageInfoCaptor.getValue()).containsExactly(mPackageInfo);
+    }
+
+    @Test
+    public void testUnblockAppWindowForScreenCapture() {
+        mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
+        mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+                mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), false);
+        verify(mWindowManager).removeBlockScreenCaptureForApps(mPackageInfoCaptor.capture());
+        assertThat(mPackageInfoCaptor.getValue()).containsExactly(mPackageInfo);
+    }
+
+    @Test
+    public void testAppWindowIsUnblockedBeforeScreenCapture() {
+        // when screen sharing is not active, no app window should be blocked.
+        mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+                mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
+        verifyZeroInteractions(mWindowManager);
+    }
+
+    @Test
+    public void testAppWindowsAreUnblockedOnScreenCaptureEnd() {
+        mMediaPorjectionCallback.onStart(mMediaProjectionInfo);
+        mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+                mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
+        // when screen sharing ends, all blocked app windows should be cleared.
+        mMediaPorjectionCallback.onStop(mMediaProjectionInfo);
+        verify(mWindowManager).clearBlockedApps();
+    }
+
+    @Test
+    public void testDeveloperOptionDisableFeature() {
+        mockDisabledViaDeveloperOption();
+        mMediaProjectionCallbackCaptor.getValue().onStart(mMediaProjectionInfo);
+        mSensitiveContentProtectionManagerService.setSensitiveContentProtection(
+                mPackageInfo.getWindowToken(), mPackageInfo.getPkg(), mPackageInfo.getUid(), true);
+        verifyZeroInteractions(mWindowManager);
+    }
+
+    private void mockDisabledViaDeveloperOption() {
+        Settings.Global.putInt(
+                mContext.getContentResolver(),
+                Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS,
+                1);
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
similarity index 99%
rename from services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceTest.java
rename to services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
index c298d516c89e6f64f843a09e6c757928ba3bb019..08050a9b30e0fd0cca16ce745499f92f1ae3314e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
@@ -16,10 +16,10 @@
 
 package com.android.server;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
 import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
 
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doCallRealMethod;
@@ -67,7 +67,11 @@ import java.util.Set;
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION)
-public class SensitiveContentProtectionManagerServiceTest {
+/**
+ * Test {@link SensitiveContentProtectionManagerService} for sensitive notification protection,
+ * the service protects sensitive content during screen share.
+ */
+public class SensitiveContentProtectionManagerServiceNotificationTest {
     private static final String NOTIFICATION_KEY_1 = "com.android.server.notification.TEST_KEY_1";
     private static final String NOTIFICATION_KEY_2 = "com.android.server.notification.TEST_KEY_2";
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/SensitiveContentPackagesTest.java b/services/tests/wmtests/src/com/android/server/wm/SensitiveContentPackagesTest.java
index 298637266cc3bda0e5384d1bb83eff43d14df2a6..824b8d7f6727ce9583436967b9115de1883864dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SensitiveContentPackagesTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SensitiveContentPackagesTest.java
@@ -16,10 +16,18 @@
 
 package com.android.server.wm;
 
+import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
+import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.os.Binder;
+import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
@@ -27,6 +35,7 @@ import androidx.test.filters.SmallTest;
 import com.android.server.wm.SensitiveContentPackages.PackageInfo;
 
 import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.Set;
@@ -44,23 +53,30 @@ public class SensitiveContentPackagesTest {
 
     private static final int APP_UID_1 = 5;
     private static final int APP_UID_2 = 6;
-    private static final int APP_UID_3 = 7;
 
+    private static final IBinder WINDOW_TOKEN_1 = new Binder();
+    private static final IBinder WINDOW_TOKEN_2 = new Binder();
 
     private final SensitiveContentPackages mSensitiveContentPackages =
             new SensitiveContentPackages();
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     @After
     public void tearDown() {
         mSensitiveContentPackages.clearBlockedApps();
     }
 
+    private boolean shouldBlockScreenCaptureForApp(String pkg, int uid, IBinder windowToken) {
+        return mSensitiveContentPackages.shouldBlockScreenCaptureForApp(pkg, uid, windowToken);
+    }
+
     @Test
-    public void addBlockScreenCaptureForApps() {
+    @RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION)
+    public void shouldBlockScreenCaptureForNotificationApps() {
         ArraySet<PackageInfo> blockedApps = new ArraySet(
                 Set.of(new PackageInfo(APP_PKG_1, APP_UID_1),
-                        new PackageInfo(APP_PKG_1, APP_UID_2),
-                        new PackageInfo(APP_PKG_2, APP_UID_1),
                         new PackageInfo(APP_PKG_2, APP_UID_2)
                 ));
 
@@ -68,17 +84,50 @@ public class SensitiveContentPackagesTest {
 
         assertTrue(modified);
 
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1));
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_3));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_1));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_2));
+        assertFalse(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_2, WINDOW_TOKEN_2));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_1));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_2));
+        assertFalse(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_1, WINDOW_TOKEN_2));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_APP_PROTECTION)
+    public void shouldBlockScreenCaptureForSensitiveContentOnScreenApps() {
+        ArraySet<PackageInfo> blockedApps = new ArraySet(
+                Set.of(new PackageInfo(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_1),
+                        new PackageInfo(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_2)
+                ));
+
+        boolean modified = mSensitiveContentPackages.addBlockScreenCaptureForApps(blockedApps);
+        assertTrue(modified);
+
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_1));
+        assertFalse(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_2));
+
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_2));
+        assertFalse(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_1));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(
+            {FLAG_SENSITIVE_CONTENT_APP_PROTECTION, FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION})
+    public void shouldBlockScreenCaptureForApps() {
+        ArraySet<PackageInfo> blockedApps = new ArraySet(
+                Set.of(new PackageInfo(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_1),
+                        new PackageInfo(APP_PKG_1, APP_UID_1),
+                        new PackageInfo(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_2)
+                ));
+
+        boolean modified = mSensitiveContentPackages.addBlockScreenCaptureForApps(blockedApps);
+        assertTrue(modified);
 
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_1));
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_3));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_1));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1, WINDOW_TOKEN_2));
 
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_3));
+        assertTrue(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_2));
+        assertFalse(shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_1));
     }
 
     @Test
@@ -92,20 +141,8 @@ public class SensitiveContentPackagesTest {
 
         mSensitiveContentPackages.addBlockScreenCaptureForApps(blockedApps);
         boolean modified = mSensitiveContentPackages.addBlockScreenCaptureForApps(blockedApps);
-
         assertFalse(modified);
-
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1));
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_3));
-
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_1));
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_3));
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_3));
+        assertTrue(mSensitiveContentPackages.size() == 4);
     }
 
     @Test
@@ -121,65 +158,28 @@ public class SensitiveContentPackagesTest {
         boolean modified = mSensitiveContentPackages
                 .addBlockScreenCaptureForApps(
                         new ArraySet(Set.of(new PackageInfo(APP_PKG_3, APP_UID_1))));
-
         assertTrue(modified);
-
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1));
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_3));
-
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_1));
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_3));
-
-        assertTrue(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_3));
+        assertTrue(mSensitiveContentPackages.size() == 5);
     }
 
     @Test
     public void clearBlockedApps() {
         ArraySet<PackageInfo> blockedApps = new ArraySet(
                 Set.of(new PackageInfo(APP_PKG_1, APP_UID_1),
-                        new PackageInfo(APP_PKG_1, APP_UID_2),
-                        new PackageInfo(APP_PKG_2, APP_UID_1),
-                        new PackageInfo(APP_PKG_2, APP_UID_2)
+                        new PackageInfo(APP_PKG_2, APP_UID_2, WINDOW_TOKEN_2)
                 ));
 
         mSensitiveContentPackages.addBlockScreenCaptureForApps(blockedApps);
         boolean modified = mSensitiveContentPackages.clearBlockedApps();
 
         assertTrue(modified);
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_3));
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_3));
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_3));
+        assertTrue(mSensitiveContentPackages.size() == 0);
     }
 
     @Test
     public void clearBlockedApps_alreadyEmpty() {
         boolean modified = mSensitiveContentPackages.clearBlockedApps();
-
         assertFalse(modified);
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_1, APP_UID_3));
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_2, APP_UID_3));
-
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_1));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_2));
-        assertFalse(mSensitiveContentPackages.shouldBlockScreenCaptureForApp(APP_PKG_3, APP_UID_3));
+        assertTrue(mSensitiveContentPackages.size() == 0);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index c972e518e46dcc869a1e0bcb627115d25760d626..a0e64bf94393df8f4791196167f7efa165020c58 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -21,9 +21,11 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_OWN_FOCUS;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.flags.Flags.FLAG_SENSITIVE_CONTENT_APP_PROTECTION;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
@@ -80,6 +82,7 @@ import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.util.ArraySet;
 import android.util.MergedConfiguration;
 import android.view.ContentRecordingSession;
@@ -840,7 +843,8 @@ public class WindowManagerServiceTests extends WindowTestsBase {
     }
 
     @Test
-    public void addBlockScreenCaptureForApps() {
+    @RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION)
+    public void shouldBlockScreenCaptureForNotificationApps() {
         String testPackage = "test";
         int ownerId1 = 20;
         int ownerId2 = 21;
@@ -850,12 +854,59 @@ public class WindowManagerServiceTests extends WindowTestsBase {
 
         WindowManagerInternal wmInternal = LocalServices.getService(WindowManagerInternal.class);
         wmInternal.addBlockScreenCaptureForApps(blockedPackages);
+        verify(mWm).refreshScreenCaptureDisabled();
 
+        // window client token parameter is ignored for this feature.
         assertTrue(mWm.mSensitiveContentPackages
-                .shouldBlockScreenCaptureForApp(testPackage, ownerId1));
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId1, new Binder()));
         assertFalse(mWm.mSensitiveContentPackages
-                .shouldBlockScreenCaptureForApp(testPackage, ownerId2));
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId2, new Binder()));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_APP_PROTECTION)
+    public void shouldBlockScreenCaptureForSensitiveContentOnScreenApps() {
+        String testPackage = "test";
+        int ownerId1 = 20;
+        final IBinder windowClientToken = new Binder("window client token");
+        PackageInfo blockedPackage = new PackageInfo(testPackage, ownerId1, windowClientToken);
+        ArraySet<PackageInfo> blockedPackages = new ArraySet();
+        blockedPackages.add(blockedPackage);
+
+        WindowManagerInternal wmInternal = LocalServices.getService(WindowManagerInternal.class);
+        wmInternal.addBlockScreenCaptureForApps(blockedPackages);
         verify(mWm).refreshScreenCaptureDisabled();
+
+        assertTrue(mWm.mSensitiveContentPackages
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId1, windowClientToken));
+        assertFalse(mWm.mSensitiveContentPackages
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId1, new Binder()));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(
+            {FLAG_SENSITIVE_CONTENT_APP_PROTECTION, FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION})
+    public void shouldBlockScreenCaptureForApps() {
+        String testPackage = "test";
+        int ownerId1 = 20;
+        int ownerId2 = 21;
+        final IBinder windowClientToken = new Binder("window client token");
+        PackageInfo blockedPackage1 = new PackageInfo(testPackage, ownerId1);
+        PackageInfo blockedPackage2 = new PackageInfo(testPackage, ownerId1, windowClientToken);
+        ArraySet<PackageInfo> blockedPackages = new ArraySet();
+        blockedPackages.add(blockedPackage1);
+        blockedPackages.add(blockedPackage2);
+
+        WindowManagerInternal wmInternal = LocalServices.getService(WindowManagerInternal.class);
+        wmInternal.addBlockScreenCaptureForApps(blockedPackages);
+        verify(mWm).refreshScreenCaptureDisabled();
+
+        assertTrue(mWm.mSensitiveContentPackages
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId1, windowClientToken));
+        assertTrue(mWm.mSensitiveContentPackages
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId1, new Binder()));
+        assertFalse(mWm.mSensitiveContentPackages
+                .shouldBlockScreenCaptureForApp(testPackage, ownerId2, new Binder()));
     }
 
     @Test
@@ -891,10 +942,6 @@ public class WindowManagerServiceTests extends WindowTestsBase {
         wmInternal.addBlockScreenCaptureForApps(blockedPackages);
         wmInternal.addBlockScreenCaptureForApps(blockedPackages2);
 
-        assertTrue(mWm.mSensitiveContentPackages
-                .shouldBlockScreenCaptureForApp(testPackage, ownerId1));
-        assertTrue(mWm.mSensitiveContentPackages
-                .shouldBlockScreenCaptureForApp(testPackage, ownerId2));
         verify(mWm, times(2)).refreshScreenCaptureDisabled();
     }
 
@@ -909,9 +956,6 @@ public class WindowManagerServiceTests extends WindowTestsBase {
         WindowManagerInternal wmInternal = LocalServices.getService(WindowManagerInternal.class);
         wmInternal.addBlockScreenCaptureForApps(blockedPackages);
         wmInternal.clearBlockedApps();
-
-        assertFalse(mWm.mSensitiveContentPackages
-                .shouldBlockScreenCaptureForApp(testPackage, ownerId1));
         verify(mWm, times(2)).refreshScreenCaptureDisabled();
     }