From d40067dc50e6ae6f0bbfc0ee307f9c506284a40e Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Fri, 10 Jan 2025 17:06:27 +0100 Subject: Stop contextual search showing in its own screenshots Test: ContextualSearchManagerTest Test: GtsInteractiveContextualSearchIntentTestCases Bug: 390176823 Flag: android.app.contextualsearch.flags.contextual_search_window_layer Change-Id: I1fc7c9ed8b742f3e55bf6cf929aa3de5debad80d --- .../android/app/contextualsearch/flags.aconfig | 7 ++-- .../ContextualSearchManagerService.java | 38 ++++++++-------------- .../java/com/android/server/wm/DisplayContent.java | 17 +++++----- .../android/server/wm/WindowManagerInternal.java | 13 ++++++-- .../android/server/wm/WindowManagerService.java | 31 ++++++++++++++---- .../VoiceInteractionManagerService.java | 3 +- 6 files changed, 64 insertions(+), 45 deletions(-) diff --git a/core/java/android/app/contextualsearch/flags.aconfig b/core/java/android/app/contextualsearch/flags.aconfig index c19921dcdc61..d81ec1e8b883 100644 --- a/core/java/android/app/contextualsearch/flags.aconfig +++ b/core/java/android/app/contextualsearch/flags.aconfig @@ -27,7 +27,10 @@ flag { name: "contextual_search_window_layer" namespace: "sysui_integrations" description: "Identify live contextual search UI to exclude from contextual search screenshot." - bug: "372510690" + bug: "390176823" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { @@ -35,4 +38,4 @@ flag { namespace: "sysui_integrations" description: "Add audio playing status to the contextual search invocation intent." bug: "372935419" -} \ No newline at end of file +} diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java index df47c98d6433..89c9d690a82c 100644 --- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java +++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java @@ -27,10 +27,6 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; -import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; -import static android.view.WindowManager.LayoutParams.TYPE_POINTER; -import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE; @@ -74,6 +70,7 @@ import android.util.Log; import android.util.Slog; import android.view.IWindowManager; import android.window.ScreenCapture; +import android.window.ScreenCapture.ScreenshotHardwareBuffer; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; @@ -333,10 +330,10 @@ public class ContextualSearchManagerService extends SystemService { isManagedProfileVisible = true; } } + final String csPackage = Objects.requireNonNull(launchIntent.getPackage()); + final int csUid = mPackageManager.getPackageUid(csPackage, /* flags */ 0L, userId); if (isAssistDataAllowed) { try { - final String csPackage = Objects.requireNonNull(launchIntent.getPackage()); - final int csUid = mPackageManager.getPackageUid(csPackage, 0, 0); mAssistDataRequester.requestAssistData( activityTokens, /* fetchData */ true, @@ -350,17 +347,8 @@ public class ContextualSearchManagerService extends SystemService { Log.e(TAG, "Could not request assist data", e); } } - final ScreenCapture.ScreenshotHardwareBuffer shb; - if (mWmInternal != null) { - shb = mWmInternal.takeAssistScreenshot(Set.of( - TYPE_STATUS_BAR, - TYPE_NAVIGATION_BAR, - TYPE_NAVIGATION_BAR_PANEL, - TYPE_POINTER)); - } else { - if (DEBUG) Log.w(TAG, "Can't capture contextual screenshot: mWmInternal is null"); - shb = null; - } + final ScreenshotHardwareBuffer shb = mWmInternal.takeContextualSearchScreenshot( + (Flags.contextualSearchWindowLayer() ? csUid : -1)); final Bitmap bm = shb != null ? shb.asBitmap() : null; // Now that everything is fetched, putting it in the launchIntent. if (bm != null) { @@ -509,15 +497,17 @@ public class ContextualSearchManagerService extends SystemService { bundle.putParcelable(ContextualSearchManager.EXTRA_TOKEN, mToken); // We get take the screenshot with the system server's identity because the system // server has READ_FRAME_BUFFER permission to get the screenshot. + final int callingUid = Binder.getCallingUid(); Binder.withCleanCallingIdentity(() -> { - if (mWmInternal != null) { + final ScreenshotHardwareBuffer shb = + mWmInternal.takeContextualSearchScreenshot( + (Flags.contextualSearchWindowLayer() ? callingUid : -1)); + final Bitmap bm = shb != null ? shb.asBitmap() : null; + if (bm != null) { bundle.putParcelable(ContextualSearchManager.EXTRA_SCREENSHOT, - mWmInternal.takeAssistScreenshot(Set.of( - TYPE_STATUS_BAR, - TYPE_NAVIGATION_BAR, - TYPE_NAVIGATION_BAR_PANEL, - TYPE_POINTER)) - .asBitmap().asShared()); + bm.asShared()); + bundle.putBoolean(ContextualSearchManager.EXTRA_FLAG_SECURE_FOUND, + shb.containsSecureLayers()); } try { callback.onResult( diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5435d8f164da..674c564d3699 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5255,7 +5255,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** * Creates a LayerCaptureArgs object to represent the entire DisplayContent */ - LayerCaptureArgs getLayerCaptureArgs(Set windowTypesToExclude) { + LayerCaptureArgs getLayerCaptureArgs(@Nullable ToBooleanFunction predicate) { if (!mWmService.mPolicy.isScreenOn()) { if (DEBUG_SCREENSHOT) { Slog.i(TAG_WM, "Attempted to take screenshot while display was off."); @@ -5268,17 +5268,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp LayerCaptureArgs.Builder builder = new LayerCaptureArgs.Builder(getSurfaceControl()) .setSourceCrop(mTmpRect); - if (!windowTypesToExclude.isEmpty()) { - ArrayList surfaceControls = new ArrayList<>(); + if (predicate != null) { + ArrayList excludeLayers = new ArrayList<>(); forAllWindows( window -> { - if (windowTypesToExclude.contains(window.getWindowType())) { - surfaceControls.add(window.mSurfaceControl); + if (!predicate.apply(window)) { + excludeLayers.add(window.mSurfaceControl); } - }, true - ); - if (!surfaceControls.isEmpty()) { - builder.setExcludeLayers(surfaceControls.toArray(new SurfaceControl[0])); + }, true); + if (!excludeLayers.isEmpty()) { + builder.setExcludeLayers(excludeLayers.toArray(new SurfaceControl[0])); } } return builder.build(); diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index c77b1d9a7bcf..6e224f07fcdc 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -1137,6 +1137,15 @@ public abstract class WindowManagerInternal { * Returns an instance of {@link ScreenshotHardwareBuffer} containing the current * screenshot. */ - public abstract ScreenshotHardwareBuffer takeAssistScreenshot( - Set windowTypesToExclude); + public abstract ScreenshotHardwareBuffer takeAssistScreenshot(); + + /** + * Returns an instance of {@link ScreenshotHardwareBuffer} containing the current + * screenshot, excluding layers that are not appropriate to pass to contextual search + * services - such as the cursor or any current contextual search window. + * + * @param uid the UID of the contextual search application. System alert windows belonging + * to this UID will be excluded from the screenshot. + */ + public abstract ScreenshotHardwareBuffer takeContextualSearchScreenshot(int uid); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 36d52ddb40e6..21ace50cbd6c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -329,6 +329,7 @@ import android.window.WindowContainerToken; import android.window.WindowContextInfo; import com.android.internal.R; +import com.android.internal.util.ToBooleanFunction; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; @@ -4232,7 +4233,8 @@ public class WindowManagerService extends IWindowManager.Stub } @Nullable - private ScreenshotHardwareBuffer takeAssistScreenshot(Set windowTypesToExclude) { + private ScreenshotHardwareBuffer takeAssistScreenshot( + @Nullable ToBooleanFunction predicate) { if (!checkCallingPermission(READ_FRAME_BUFFER, "requestAssistScreenshot()")) { throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } @@ -4247,7 +4249,7 @@ public class WindowManagerService extends IWindowManager.Stub } captureArgs = null; } else { - captureArgs = displayContent.getLayerCaptureArgs(windowTypesToExclude); + captureArgs = displayContent.getLayerCaptureArgs(predicate); } } @@ -4277,8 +4279,7 @@ public class WindowManagerService extends IWindowManager.Stub */ @Override public boolean requestAssistScreenshot(final IAssistDataReceiver receiver) { - final ScreenshotHardwareBuffer shb = - takeAssistScreenshot(/* windowTypesToExclude= */ Set.of()); + final ScreenshotHardwareBuffer shb = takeAssistScreenshot(/* predicate= */ null); final Bitmap bm = shb != null ? shb.asBitmap() : null; FgThread.getHandler().post(() -> { try { @@ -8935,9 +8936,27 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public ScreenshotHardwareBuffer takeAssistScreenshot(Set windowTypesToExclude) { + public ScreenshotHardwareBuffer takeAssistScreenshot() { // WMS.takeAssistScreenshot takes care of the locking. - return WindowManagerService.this.takeAssistScreenshot(windowTypesToExclude); + return WindowManagerService.this.takeAssistScreenshot(/* predicate */ null); + } + + @Override + public ScreenshotHardwareBuffer takeContextualSearchScreenshot(int uid) { + // WMS.takeAssistScreenshot takes care of the locking. + return WindowManagerService.this.takeAssistScreenshot(win -> { + switch (win.getWindowType()) { + case LayoutParams.TYPE_STATUS_BAR: + case LayoutParams.TYPE_NAVIGATION_BAR: + case LayoutParams.TYPE_NAVIGATION_BAR_PANEL: + case LayoutParams.TYPE_POINTER: + return false; + case LayoutParams.TYPE_APPLICATION_OVERLAY: + return uid != win.getOwningUid(); + default: + return true; + } + }); } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 7e7a53148603..cd1c48554be9 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -2747,8 +2747,7 @@ public class VoiceInteractionManagerService extends SystemService { isManagedProfileVisible = true; } } - final ScreenCapture.ScreenshotHardwareBuffer shb = - mWmInternal.takeAssistScreenshot(/* windowTypesToExclude= */ Set.of()); + final ScreenCapture.ScreenshotHardwareBuffer shb = mWmInternal.takeAssistScreenshot(); final Bitmap bm = shb != null ? shb.asBitmap() : null; // Now that everything is fetched, putting it in the launchIntent. if (bm != null) { -- cgit v1.2.3-59-g8ed1b