Screenshot helper - add method that allows the caller to supply bitmap.
Add a method to screenshot helper that allows the caller to provide the bitmap to be treated as a screen shot. First use Overview can provide a task snapshot to use as a screenshot. Test: update tests, local Bug: 145297320 Change-Id: I4d21906212797bf394094d7a29208be02a6bfd7e
This commit is contained in:
@@ -452,13 +452,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
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
@@ -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,
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.Notification;
|
||||
@@ -38,6 +39,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PointF;
|
||||
@@ -300,8 +302,11 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
int width = crop.width();
|
||||
int height = crop.height();
|
||||
|
||||
// Take the screenshot
|
||||
mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
|
||||
takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, null);
|
||||
}
|
||||
|
||||
private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect) {
|
||||
mScreenBitmap = screenshot;
|
||||
if (mScreenBitmap == null) {
|
||||
mNotificationsController.notifyScreenshotError(
|
||||
R.string.screenshot_failed_to_capture_text);
|
||||
@@ -317,7 +322,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
|
||||
|
||||
// Start the post-screenshot animation
|
||||
startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels);
|
||||
startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
|
||||
screenRect);
|
||||
}
|
||||
|
||||
void takeScreenshot(Consumer<Uri> finisher) {
|
||||
@@ -327,9 +333,16 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
|
||||
}
|
||||
|
||||
void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
|
||||
Insets visibleInsets, int taskId, Consumer<Uri> finisher) {
|
||||
// TODO use taskId and visibleInsets
|
||||
takeScreenshot(screenshot, finisher, screenshotScreenBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a screenshot selector
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
void takeScreenshotPartial(final Consumer<Uri> finisher) {
|
||||
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
|
||||
mScreenshotSelectorView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@@ -402,7 +415,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
/**
|
||||
* Starts the animation after taking the screenshot
|
||||
*/
|
||||
private void startAnimation(final Consumer<Uri> finisher, int w, int h) {
|
||||
private void startAnimation(final Consumer<Uri> finisher, int w, int h,
|
||||
@Nullable Rect screenRect) {
|
||||
// If power save is on, show a toast so there is some visual indication that a screenshot
|
||||
// has been taken.
|
||||
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
@@ -422,7 +436,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
mScreenshotAnimation.removeAllListeners();
|
||||
}
|
||||
|
||||
ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
|
||||
ValueAnimator screenshotDropInAnim = screenRect != null ? createRectAnimation(screenRect)
|
||||
: createScreenshotDropInAnimation();
|
||||
ValueAnimator screenshotFadeOutAnim = createScreenshotToCornerAnimation(w, h);
|
||||
mScreenshotAnimation = new AnimatorSet();
|
||||
mScreenshotAnimation.playSequentially(screenshotDropInAnim, screenshotFadeOutAnim);
|
||||
@@ -460,6 +475,46 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
});
|
||||
}
|
||||
|
||||
private ValueAnimator createRectAnimation(Rect rect) {
|
||||
mScreenshotView.setAdjustViewBounds(true);
|
||||
mScreenshotView.setMaxHeight(rect.height());
|
||||
mScreenshotView.setMaxWidth(rect.width());
|
||||
|
||||
final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
|
||||
/ SCREENSHOT_DROP_IN_DURATION);
|
||||
final float flashDurationPct = 2f * flashPeakDurationPct;
|
||||
final Interpolator scaleInterpolator = x -> {
|
||||
// We start scaling when the flash is at it's peak
|
||||
if (x < flashPeakDurationPct) {
|
||||
return 0;
|
||||
}
|
||||
return (x - flashDurationPct) / (1f - flashDurationPct);
|
||||
};
|
||||
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
|
||||
anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mBackgroundView.setAlpha(0f);
|
||||
mBackgroundView.setVisibility(View.VISIBLE);
|
||||
mScreenshotView.setAlpha(0f);
|
||||
mScreenshotView.setElevation(0f);
|
||||
mScreenshotView.setTranslationX(0f);
|
||||
mScreenshotView.setTranslationY(0f);
|
||||
mScreenshotView.setScaleX(1f);
|
||||
mScreenshotView.setScaleY(1f);
|
||||
mScreenshotView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener(animation -> {
|
||||
float t = (Float) animation.getAnimatedValue();
|
||||
mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
|
||||
mScreenshotView.setAlpha(t);
|
||||
});
|
||||
return anim;
|
||||
}
|
||||
|
||||
private ValueAnimator createScreenshotDropInAnimation() {
|
||||
final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
|
||||
/ SCREENSHOT_DROP_IN_DURATION);
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
@@ -205,8 +206,13 @@ public class GlobalScreenshotLegacy {
|
||||
int width = crop.width();
|
||||
int height = crop.height();
|
||||
|
||||
// Take the screenshot
|
||||
mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
|
||||
takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher,
|
||||
statusBarVisible, navBarVisible, null);
|
||||
}
|
||||
|
||||
private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, boolean statusBarVisible,
|
||||
boolean navBarVisible, Rect screenboundsOfBitmap) {
|
||||
mScreenBitmap = screenshot;
|
||||
if (mScreenBitmap == null) {
|
||||
mNotificationsController.notifyScreenshotError(
|
||||
R.string.screenshot_failed_to_capture_text);
|
||||
@@ -220,7 +226,7 @@ public class GlobalScreenshotLegacy {
|
||||
|
||||
// Start the post-screenshot animation
|
||||
startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
|
||||
statusBarVisible, navBarVisible);
|
||||
statusBarVisible, navBarVisible, screenboundsOfBitmap);
|
||||
}
|
||||
|
||||
void takeScreenshot(Consumer<Uri> finisher, boolean statusBarVisible, boolean navBarVisible) {
|
||||
@@ -229,6 +235,12 @@ public class GlobalScreenshotLegacy {
|
||||
new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
|
||||
}
|
||||
|
||||
void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
|
||||
Insets visibleInsets, int taskId, Consumer<Uri> finisher) {
|
||||
// TODO use taskId and visibleInsets
|
||||
takeScreenshot(screenshot, finisher, false, false, screenshotScreenBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a screenshot selector
|
||||
*/
|
||||
@@ -302,7 +314,7 @@ public class GlobalScreenshotLegacy {
|
||||
* Starts the animation after taking the screenshot
|
||||
*/
|
||||
private void startAnimation(final Consumer<Uri> finisher, int w, int h,
|
||||
boolean statusBarVisible, boolean navBarVisible) {
|
||||
boolean statusBarVisible, boolean navBarVisible, @Nullable Rect screenBoundsOfBitmap) {
|
||||
// If power save is on, show a toast so there is some visual indication that a screenshot
|
||||
// has been taken.
|
||||
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
@@ -323,7 +335,8 @@ public class GlobalScreenshotLegacy {
|
||||
}
|
||||
|
||||
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
|
||||
ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
|
||||
ValueAnimator screenshotDropInAnim = screenBoundsOfBitmap != null
|
||||
? createRectAnimation(screenBoundsOfBitmap) : createScreenshotDropInAnimation();
|
||||
ValueAnimator screenshotFadeOutAnim =
|
||||
createScreenshotDropOutAnimation(w, h, statusBarVisible, navBarVisible);
|
||||
mScreenshotAnimation = new AnimatorSet();
|
||||
@@ -430,6 +443,53 @@ public class GlobalScreenshotLegacy {
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a bitmap was supplied to be used as the screenshot, animated from where that bitmap was
|
||||
* on screen, rather than using the whole screen.
|
||||
*/
|
||||
private ValueAnimator createRectAnimation(Rect rect) {
|
||||
mScreenshotView.setAdjustViewBounds(true);
|
||||
mScreenshotView.setMaxHeight(rect.height());
|
||||
mScreenshotView.setMaxWidth(rect.width());
|
||||
|
||||
final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
|
||||
/ SCREENSHOT_DROP_IN_DURATION);
|
||||
final float flashDurationPct = 2f * flashPeakDurationPct;
|
||||
final Interpolator scaleInterpolator = x -> {
|
||||
// We start scaling when the flash is at it's peak
|
||||
if (x < flashPeakDurationPct) {
|
||||
return 0;
|
||||
}
|
||||
return (x - flashDurationPct) / (1f - flashDurationPct);
|
||||
};
|
||||
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
|
||||
anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mBackgroundView.setAlpha(0f);
|
||||
mBackgroundView.setVisibility(View.VISIBLE);
|
||||
mScreenshotView.setAlpha(0f);
|
||||
mScreenshotView.setElevation(0f);
|
||||
mScreenshotView.setTranslationX(0f);
|
||||
mScreenshotView.setTranslationY(0f);
|
||||
mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
|
||||
mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
|
||||
mScreenshotView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener(animation -> {
|
||||
float t = (Float) animation.getAnimatedValue();
|
||||
float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
|
||||
- scaleInterpolator.getInterpolation(t)
|
||||
* (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
|
||||
mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
|
||||
mScreenshotView.setAlpha(t);
|
||||
});
|
||||
return anim;
|
||||
}
|
||||
|
||||
private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
|
||||
boolean navBarVisible) {
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
|
||||
|
||||
@@ -22,6 +22,9 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREEN
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -85,6 +88,22 @@ public class TakeScreenshotService extends Service {
|
||||
finisher, msg.arg1 > 0, msg.arg2 > 0);
|
||||
}
|
||||
break;
|
||||
case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:
|
||||
Bitmap screenshot = msg.getData().getParcelable(
|
||||
WindowManager.PARCEL_KEY_SCREENSHOT_BITMAP);
|
||||
Rect screenBounds = msg.getData().getParcelable(
|
||||
WindowManager.PARCEL_KEY_SCREENSHOT_BOUNDS);
|
||||
Insets insets = msg.getData().getParcelable(
|
||||
WindowManager.PARCEL_KEY_SCREENSHOT_INSETS);
|
||||
int taskId = msg.getData().getInt(WindowManager.PARCEL_KEY_SCREENSHOT_TASK_ID);
|
||||
if (useCornerFlow) {
|
||||
mScreenshot.handleImageAsScreenshot(
|
||||
screenshot, screenBounds, insets, taskId, finisher);
|
||||
} else {
|
||||
mScreenshotLegacy.handleImageAsScreenshot(
|
||||
screenshot, screenBounds, insets, taskId, finisher);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.d(TAG, "Invalid screenshot option: " + msg.what);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user