diff options
| author | 2024-12-19 23:57:07 +0000 | |
|---|---|---|
| committer | 2025-02-14 15:23:25 -0800 | |
| commit | 22b4f81bf06b603f029a2b3c80ff68db4a1bd229 (patch) | |
| tree | 5d2ee749360e2aa54eb4e7849f67d2c6f1f63ef3 /services/accessibility/java | |
| parent | c42e473bf66d61267b264e86eb94fcbb600b7201 (diff) | |
Stop blocking preinstalled a11y tools from taking FLAG_SECURE screenshots.
Requires moving the caller of ScreenCapture's screenshot method from the
app process to the system_server process since capturing FLAG_SECURE
content, even for an app capturing its own content, requires permission
CAPTURE_BLACKOUT_CONTENT which is a signature permission.
system_server was already used for full-display accessibility screenshots.
Bug: 373705911
Test: atest AbstractAccessibilityServiceConnectionTest
Test: atest AccessibilityInteractionControllerTest
Test: atest AccessibilityTakeScreenshotTest
Flag: com.android.server.accessibility.allow_secure_screenshots
Change-Id: Ifb711222a42fa18abcabefafdef22daf46402955
Diffstat (limited to 'services/accessibility/java')
2 files changed, 65 insertions, 2 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 9ceca5d1dbfe..4b042489f3eb 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -86,11 +86,13 @@ import android.view.MagnificationSpec; import android.view.MotionEvent; import android.view.SurfaceControl; import android.view.View; +import android.view.WindowManager; import android.view.accessibility.AccessibilityCache; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; +import android.view.accessibility.IWindowSurfaceInfoCallback; import android.view.inputmethod.EditorInfo; import android.window.ScreenCapture; import android.window.ScreenCapture.ScreenshotHardwareBuffer; @@ -343,6 +345,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ SurfaceControl sc, IAccessibilityInteractionConnectionCallback callback); + int performScreenCapture(ScreenCapture.LayerCaptureArgs captureArgs, + ScreenCapture.ScreenCaptureListener captureListener); } public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName, @@ -1456,7 +1460,45 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_WINDOW, interactionId); return; } - connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback); + if (Flags.allowSecureScreenshots()) { + IWindowSurfaceInfoCallback infoCallback = new IWindowSurfaceInfoCallback.Stub() { + @Override + public void provideWindowSurfaceInfo(int windowFlags, int processUid, + SurfaceControl surfaceControl) { + final boolean canCaptureSecureLayers = canCaptureSecureLayers(); + if (!canCaptureSecureLayers + && (windowFlags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { + try { + callback.sendTakeScreenshotOfWindowError( + AccessibilityService.ERROR_TAKE_SCREENSHOT_SECURE_WINDOW, + interactionId); + } catch (RemoteException e) { + // ignore - the other side will time out + } + return; + } + + final ScreenCapture.LayerCaptureArgs captureArgs = + new ScreenCapture.LayerCaptureArgs.Builder(surfaceControl) + .setChildrenOnly(false) + .setUid(processUid) + .setCaptureSecureLayers(canCaptureSecureLayers) + .build(); + if (mSystemSupport.performScreenCapture(captureArgs, listener) != 0) { + try { + callback.sendTakeScreenshotOfWindowError( + AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, + interactionId); + } catch (RemoteException e) { + // ignore - the other side will time out + } + } + } + }; + connection.getRemote().getWindowSurfaceInfo(infoCallback); + } else { + connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback); + } } finally { Binder.restoreCallingIdentity(identity); } @@ -1523,7 +1565,14 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } } ); - mWindowManagerService.captureDisplay(displayId, null, screenCaptureListener); + if (Flags.allowSecureScreenshots()) { + mWindowManagerService.captureDisplay(displayId, + new ScreenCapture.CaptureArgs.Builder<>() + .setCaptureSecureLayers(canCaptureSecureLayers()).build(), + screenCaptureListener); + } else { + mWindowManagerService.captureDisplay(displayId, null, screenCaptureListener); + } } catch (Exception e) { sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); @@ -1564,6 +1613,13 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ }, null).recycleOnUse()); } + private boolean canCaptureSecureLayers() { + return Flags.allowSecureScreenshots() + && mAccessibilityServiceInfo.isAccessibilityTool() + && mAccessibilityServiceInfo.getResolveInfo().serviceInfo + .applicationInfo.isSystemApp(); + } + @Override @PermissionManuallyEnforced public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 67fdca446ba4..9eb8442be783 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -173,6 +173,7 @@ import android.view.accessibility.IAccessibilityManagerClient; import android.view.accessibility.IMagnificationConnection; import android.view.accessibility.IUserInitializationCompleteCallback; import android.view.inputmethod.EditorInfo; +import android.window.ScreenCapture; import com.android.internal.R; import com.android.internal.accessibility.AccessibilityShortcutController; @@ -6725,6 +6726,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub callback)); } + @Override + public int performScreenCapture(ScreenCapture.LayerCaptureArgs captureArgs, + ScreenCapture.ScreenCaptureListener captureListener) { + return ScreenCapture.captureLayers(captureArgs, captureListener); + } + @VisibleForTesting int getShortcutTypeForGenericShortcutCalls(int userId) { int navigationMode = Settings.Secure.getIntForUser( |