Loading core/java/android/view/WindowManager.java +37 −2 Original line number Diff line number Diff line Loading @@ -497,13 +497,48 @@ public interface WindowManager extends ViewManager { * Message for taking fullscreen screenshot * @hide */ final int TAKE_SCREENSHOT_FULLSCREEN = 1; int TAKE_SCREENSHOT_FULLSCREEN = 1; /** * Message for taking screenshot of selected region. * @hide */ final int TAKE_SCREENSHOT_SELECTED_REGION = 2; int TAKE_SCREENSHOT_SELECTED_REGION = 2; /** * Message for handling a screenshot flow with an image provided by the caller. * @hide */ int TAKE_SCREENSHOT_PROVIDED_IMAGE = 3; /** * Parcel key for the screen shot bitmap sent with messages of type * {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}, type {@link android.graphics.Bitmap} * @hide */ String PARCEL_KEY_SCREENSHOT_BITMAP = "screenshot_screen_bitmap"; /** * Parcel key for the screen bounds of the image sent with messages of type * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link Rect} in screen coordinates. * @hide */ String PARCEL_KEY_SCREENSHOT_BOUNDS = "screenshot_screen_bounds"; /** * Parcel key for the task id of the task that the screen shot was taken of, sent with messages * of type [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type int. * @hide */ String PARCEL_KEY_SCREENSHOT_TASK_ID = "screenshot_task_id"; /** * Parcel key for the visible insets of the image sent with messages of type * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link android.graphics.Insets} in * screen coordinates. * @hide */ String PARCEL_KEY_SCREENSHOT_INSETS = "screenshot_insets"; /** * @hide Loading core/java/com/android/internal/util/ScreenshotHelper.java +47 −4 Original line number Diff line number Diff line Loading @@ -6,7 +6,11 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; Loading @@ -14,6 +18,7 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.view.WindowManager; import java.util.function.Consumer; Loading @@ -38,9 +43,9 @@ public class ScreenshotHelper { * is recommended for general use. * * @param screenshotType The type of screenshot, for example either * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} * {@link android.view.WindowManager#TAKE_SCREENSHOT_FULLSCREEN} * or * {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} * {@link android.view.WindowManager#TAKE_SCREENSHOT_SELECTED_REGION} * @param hasStatus {@code true} if the status bar is currently showing. {@code false} * if * not. Loading @@ -65,9 +70,9 @@ public class ScreenshotHelper { * is recommended for general use. * * @param screenshotType The type of screenshot, for example either * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} * {@link android.view.WindowManager#TAKE_SCREENSHOT_FULLSCREEN} * or * {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} * {@link android.view.WindowManager#TAKE_SCREENSHOT_SELECTED_REGION} * @param hasStatus {@code true} if the status bar is currently showing. {@code false} * if * not. Loading @@ -84,6 +89,40 @@ public class ScreenshotHelper { public void takeScreenshot(final int screenshotType, final boolean hasStatus, final boolean hasNav, long timeoutMs, @NonNull Handler handler, @Nullable Consumer<Uri> completionConsumer) { takeScreenshot(screenshotType, hasStatus, hasNav, timeoutMs, handler, null, completionConsumer ); } /** * Request that provided image be handled as if it was a screenshot. * * @param screenshot The bitmap to treat as the screen shot. * @param boundsInScreen The bounds in screen coordinates that the bitmap orginated from. * @param insets The insets that the image was shown with, inside the screenbounds. * @param taskId The taskId of the task that the screen shot was taken of. * @param handler A handler used in case the screenshot times out * @param completionConsumer Consumes `false` if a screenshot was not taken, and `true` if the * screenshot was taken. */ public void provideScreenshot(@NonNull Bitmap screenshot, @NonNull Rect boundsInScreen, @NonNull Insets insets, int taskId, @NonNull Handler handler, @Nullable Consumer<Uri> completionConsumer) { Bundle imageBundle = new Bundle(); imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BITMAP, screenshot); imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BOUNDS, boundsInScreen); imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_INSETS, insets); imageBundle.putInt(WindowManager.PARCEL_KEY_SCREENSHOT_TASK_ID, taskId); takeScreenshot( WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE, false, false, // ignored when image bundle is set SCREENSHOT_TIMEOUT_MS, handler, imageBundle, completionConsumer); } private void takeScreenshot(final int screenshotType, final boolean hasStatus, final boolean hasNav, long timeoutMs, @NonNull Handler handler, @Nullable Bundle providedImage, @Nullable Consumer<Uri> completionConsumer) { synchronized (mScreenshotLock) { if (mScreenshotConnection != null) { return; Loading Loading @@ -139,6 +178,10 @@ public class ScreenshotHelper { msg.arg1 = hasStatus ? 1 : 0; msg.arg2 = hasNav ? 1 : 0; if (screenshotType == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE) { msg.setData(providedImage); } try { messenger.send(msg); } catch (RemoteException e) { Loading core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java +10 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,9 @@ import static org.mockito.Mockito.mock; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.os.Handler; import android.os.Looper; Loading Loading @@ -84,6 +87,13 @@ public final class ScreenshotHelperTest { null); } @Test public void testProvidedImageScreenshot() { mScreenshotHelper.provideScreenshot( Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888), new Rect(), Insets.of(0, 0, 0, 0), 1, mHandler, null); } @Test public void testScreenshotTimesOut() { long timeoutMs = 10; Loading packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.systemui.shared.recents; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.os.Bundle; import android.view.MotionEvent; /** * Temporary callbacks into SystemUI. * Next id = 22 */ interface ISystemUiProxy { Loading Loading @@ -114,4 +117,10 @@ interface ISystemUiProxy { * Sets the shelf height and visibility. */ void setShelfHeight(boolean visible, int shelfHeight) = 20; /** * Handle the provided image as if it was a screenshot. */ void handleImageAsScreenshot(in Bitmap screenImage, in Rect locationInScreen, in Insets visibleInsets, int taskId) = 21; } packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +12 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; Loading @@ -55,6 +57,7 @@ import android.view.MotionEvent; import android.view.accessibility.AccessibilityManager; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.util.ScreenshotHelper; import com.android.systemui.Dumpable; import com.android.systemui.model.SysUiState; import com.android.systemui.pip.PipUI; Loading Loading @@ -115,6 +118,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private final DeviceProvisionedController mDeviceProvisionedController; private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>(); private final Intent mQuickStepIntent; private final ScreenshotHelper mScreenshotHelper; private Region mActiveNavBarRegion; Loading Loading @@ -365,6 +369,13 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } } @Override public void handleImageAsScreenshot(Bitmap screenImage, Rect locationInScreen, Insets visibleInsets, int taskId) { mScreenshotHelper.provideScreenshot(screenImage, locationInScreen, visibleInsets, taskId, mHandler, null); } private boolean verifyCaller(String reason) { final int callerId = Binder.getCallingUserHandle().getIdentifier(); if (callerId != mCurrentBoundedUserId) { Loading Loading @@ -518,6 +529,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis // Listen for status bar state changes statusBarWinController.registerCallback(mStatusBarWindowCallback); mScreenshotHelper = new ScreenshotHelper(context); } public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton, Loading Loading
core/java/android/view/WindowManager.java +37 −2 Original line number Diff line number Diff line Loading @@ -497,13 +497,48 @@ public interface WindowManager extends ViewManager { * Message for taking fullscreen screenshot * @hide */ final int TAKE_SCREENSHOT_FULLSCREEN = 1; int TAKE_SCREENSHOT_FULLSCREEN = 1; /** * Message for taking screenshot of selected region. * @hide */ final int TAKE_SCREENSHOT_SELECTED_REGION = 2; int TAKE_SCREENSHOT_SELECTED_REGION = 2; /** * Message for handling a screenshot flow with an image provided by the caller. * @hide */ int TAKE_SCREENSHOT_PROVIDED_IMAGE = 3; /** * Parcel key for the screen shot bitmap sent with messages of type * {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}, type {@link android.graphics.Bitmap} * @hide */ String PARCEL_KEY_SCREENSHOT_BITMAP = "screenshot_screen_bitmap"; /** * Parcel key for the screen bounds of the image sent with messages of type * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link Rect} in screen coordinates. * @hide */ String PARCEL_KEY_SCREENSHOT_BOUNDS = "screenshot_screen_bounds"; /** * Parcel key for the task id of the task that the screen shot was taken of, sent with messages * of type [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type int. * @hide */ String PARCEL_KEY_SCREENSHOT_TASK_ID = "screenshot_task_id"; /** * Parcel key for the visible insets of the image sent with messages of type * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link android.graphics.Insets} in * screen coordinates. * @hide */ String PARCEL_KEY_SCREENSHOT_INSETS = "screenshot_insets"; /** * @hide Loading
core/java/com/android/internal/util/ScreenshotHelper.java +47 −4 Original line number Diff line number Diff line Loading @@ -6,7 +6,11 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; Loading @@ -14,6 +18,7 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.view.WindowManager; import java.util.function.Consumer; Loading @@ -38,9 +43,9 @@ public class ScreenshotHelper { * is recommended for general use. * * @param screenshotType The type of screenshot, for example either * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} * {@link android.view.WindowManager#TAKE_SCREENSHOT_FULLSCREEN} * or * {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} * {@link android.view.WindowManager#TAKE_SCREENSHOT_SELECTED_REGION} * @param hasStatus {@code true} if the status bar is currently showing. {@code false} * if * not. Loading @@ -65,9 +70,9 @@ public class ScreenshotHelper { * is recommended for general use. * * @param screenshotType The type of screenshot, for example either * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} * {@link android.view.WindowManager#TAKE_SCREENSHOT_FULLSCREEN} * or * {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} * {@link android.view.WindowManager#TAKE_SCREENSHOT_SELECTED_REGION} * @param hasStatus {@code true} if the status bar is currently showing. {@code false} * if * not. Loading @@ -84,6 +89,40 @@ public class ScreenshotHelper { public void takeScreenshot(final int screenshotType, final boolean hasStatus, final boolean hasNav, long timeoutMs, @NonNull Handler handler, @Nullable Consumer<Uri> completionConsumer) { takeScreenshot(screenshotType, hasStatus, hasNav, timeoutMs, handler, null, completionConsumer ); } /** * Request that provided image be handled as if it was a screenshot. * * @param screenshot The bitmap to treat as the screen shot. * @param boundsInScreen The bounds in screen coordinates that the bitmap orginated from. * @param insets The insets that the image was shown with, inside the screenbounds. * @param taskId The taskId of the task that the screen shot was taken of. * @param handler A handler used in case the screenshot times out * @param completionConsumer Consumes `false` if a screenshot was not taken, and `true` if the * screenshot was taken. */ public void provideScreenshot(@NonNull Bitmap screenshot, @NonNull Rect boundsInScreen, @NonNull Insets insets, int taskId, @NonNull Handler handler, @Nullable Consumer<Uri> completionConsumer) { Bundle imageBundle = new Bundle(); imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BITMAP, screenshot); imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BOUNDS, boundsInScreen); imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_INSETS, insets); imageBundle.putInt(WindowManager.PARCEL_KEY_SCREENSHOT_TASK_ID, taskId); takeScreenshot( WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE, false, false, // ignored when image bundle is set SCREENSHOT_TIMEOUT_MS, handler, imageBundle, completionConsumer); } private void takeScreenshot(final int screenshotType, final boolean hasStatus, final boolean hasNav, long timeoutMs, @NonNull Handler handler, @Nullable Bundle providedImage, @Nullable Consumer<Uri> completionConsumer) { synchronized (mScreenshotLock) { if (mScreenshotConnection != null) { return; Loading Loading @@ -139,6 +178,10 @@ public class ScreenshotHelper { msg.arg1 = hasStatus ? 1 : 0; msg.arg2 = hasNav ? 1 : 0; if (screenshotType == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE) { msg.setData(providedImage); } try { messenger.send(msg); } catch (RemoteException e) { Loading
core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java +10 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,9 @@ import static org.mockito.Mockito.mock; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.os.Handler; import android.os.Looper; Loading Loading @@ -84,6 +87,13 @@ public final class ScreenshotHelperTest { null); } @Test public void testProvidedImageScreenshot() { mScreenshotHelper.provideScreenshot( Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888), new Rect(), Insets.of(0, 0, 0, 0), 1, mHandler, null); } @Test public void testScreenshotTimesOut() { long timeoutMs = 10; Loading
packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.systemui.shared.recents; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.os.Bundle; import android.view.MotionEvent; /** * Temporary callbacks into SystemUI. * Next id = 22 */ interface ISystemUiProxy { Loading Loading @@ -114,4 +117,10 @@ interface ISystemUiProxy { * Sets the shelf height and visibility. */ void setShelfHeight(boolean visible, int shelfHeight) = 20; /** * Handle the provided image as if it was a screenshot. */ void handleImageAsScreenshot(in Bitmap screenImage, in Rect locationInScreen, in Insets visibleInsets, int taskId) = 21; }
packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +12 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; Loading @@ -55,6 +57,7 @@ import android.view.MotionEvent; import android.view.accessibility.AccessibilityManager; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.util.ScreenshotHelper; import com.android.systemui.Dumpable; import com.android.systemui.model.SysUiState; import com.android.systemui.pip.PipUI; Loading Loading @@ -115,6 +118,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private final DeviceProvisionedController mDeviceProvisionedController; private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>(); private final Intent mQuickStepIntent; private final ScreenshotHelper mScreenshotHelper; private Region mActiveNavBarRegion; Loading Loading @@ -365,6 +369,13 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } } @Override public void handleImageAsScreenshot(Bitmap screenImage, Rect locationInScreen, Insets visibleInsets, int taskId) { mScreenshotHelper.provideScreenshot(screenImage, locationInScreen, visibleInsets, taskId, mHandler, null); } private boolean verifyCaller(String reason) { final int callerId = Binder.getCallingUserHandle().getIdentifier(); if (callerId != mCurrentBoundedUserId) { Loading Loading @@ -518,6 +529,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis // Listen for status bar state changes statusBarWinController.registerCallback(mStatusBarWindowCallback); mScreenshotHelper = new ScreenshotHelper(context); } public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton, Loading