Merge "Simplify UI and animation choreography a bit" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a7e2e4b569
@@ -25,7 +25,7 @@
|
|||||||
android:layout_marginBottom="@dimen/screenshot_offset_y"
|
android:layout_marginBottom="@dimen/screenshot_offset_y"
|
||||||
android:scaleType="fitEnd"
|
android:scaleType="fitEnd"
|
||||||
android:elevation="@dimen/screenshot_preview_elevation"
|
android:elevation="@dimen/screenshot_preview_elevation"
|
||||||
android:visibility="gone"
|
android:visibility="invisible"
|
||||||
android:background="@drawable/screenshot_rounded_corners"
|
android:background="@drawable/screenshot_rounded_corners"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:contentDescription="@string/screenshot_edit_label"
|
android:contentDescription="@string/screenshot_edit_label"
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@@ -79,13 +80,15 @@ import com.android.internal.logging.UiEventLogger;
|
|||||||
import com.android.internal.policy.PhoneWindow;
|
import com.android.internal.policy.PhoneWindow;
|
||||||
import com.android.settingslib.applications.InterestingConfigChanges;
|
import com.android.settingslib.applications.InterestingConfigChanges;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.dagger.qualifiers.Background;
|
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
|
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
|
||||||
|
import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback;
|
||||||
import com.android.systemui.util.DeviceConfigProxy;
|
import com.android.systemui.util.DeviceConfigProxy;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -172,7 +175,7 @@ public class ScreenshotController {
|
|||||||
private final UiEventLogger mUiEventLogger;
|
private final UiEventLogger mUiEventLogger;
|
||||||
private final ImageExporter mImageExporter;
|
private final ImageExporter mImageExporter;
|
||||||
private final Executor mMainExecutor;
|
private final Executor mMainExecutor;
|
||||||
private final Executor mBgExecutor;
|
private final ExecutorService mBgExecutor;
|
||||||
|
|
||||||
private final WindowManager mWindowManager;
|
private final WindowManager mWindowManager;
|
||||||
private final WindowManager.LayoutParams mWindowLayoutParams;
|
private final WindowManager.LayoutParams mWindowLayoutParams;
|
||||||
@@ -181,7 +184,6 @@ public class ScreenshotController {
|
|||||||
private final ScrollCaptureClient mScrollCaptureClient;
|
private final ScrollCaptureClient mScrollCaptureClient;
|
||||||
private final DeviceConfigProxy mConfigProxy;
|
private final DeviceConfigProxy mConfigProxy;
|
||||||
private final PhoneWindow mWindow;
|
private final PhoneWindow mWindow;
|
||||||
private final View mDecorView;
|
|
||||||
private final DisplayManager mDisplayManager;
|
private final DisplayManager mDisplayManager;
|
||||||
|
|
||||||
private ScreenshotView mScreenshotView;
|
private ScreenshotView mScreenshotView;
|
||||||
@@ -189,8 +191,7 @@ public class ScreenshotController {
|
|||||||
private SaveImageInBackgroundTask mSaveInBgTask;
|
private SaveImageInBackgroundTask mSaveInBgTask;
|
||||||
|
|
||||||
private Animator mScreenshotAnimation;
|
private Animator mScreenshotAnimation;
|
||||||
|
private RequestCallback mCurrentRequestCallback;
|
||||||
private Runnable mOnCompleteRunnable;
|
|
||||||
|
|
||||||
private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
|
private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
|
||||||
@Override
|
@Override
|
||||||
@@ -227,15 +228,14 @@ public class ScreenshotController {
|
|||||||
UiEventLogger uiEventLogger,
|
UiEventLogger uiEventLogger,
|
||||||
DeviceConfigProxy configProxy,
|
DeviceConfigProxy configProxy,
|
||||||
ImageExporter imageExporter,
|
ImageExporter imageExporter,
|
||||||
@Main Executor mainExecutor,
|
@Main Executor mainExecutor) {
|
||||||
@Background Executor bgExecutor) {
|
|
||||||
mScreenshotSmartActions = screenshotSmartActions;
|
mScreenshotSmartActions = screenshotSmartActions;
|
||||||
mNotificationsController = screenshotNotificationsController;
|
mNotificationsController = screenshotNotificationsController;
|
||||||
mScrollCaptureClient = scrollCaptureClient;
|
mScrollCaptureClient = scrollCaptureClient;
|
||||||
mUiEventLogger = uiEventLogger;
|
mUiEventLogger = uiEventLogger;
|
||||||
mImageExporter = imageExporter;
|
mImageExporter = imageExporter;
|
||||||
mMainExecutor = mainExecutor;
|
mMainExecutor = mainExecutor;
|
||||||
mBgExecutor = bgExecutor;
|
mBgExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class));
|
mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class));
|
||||||
final Context displayContext = context.createDisplayContext(getDefaultDisplay());
|
final Context displayContext = context.createDisplayContext(getDefaultDisplay());
|
||||||
@@ -266,8 +266,8 @@ public class ScreenshotController {
|
|||||||
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
|
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
|
||||||
mWindow.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
|
mWindow.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
|
||||||
mWindow.setBackgroundDrawableResource(android.R.color.transparent);
|
mWindow.setBackgroundDrawableResource(android.R.color.transparent);
|
||||||
mDecorView = mWindow.getDecorView();
|
|
||||||
|
|
||||||
|
mConfigChanges.applyNewConfig(context.getResources());
|
||||||
reloadAssets();
|
reloadAssets();
|
||||||
|
|
||||||
// Setup the Camera shutter sound
|
// Setup the Camera shutter sound
|
||||||
@@ -275,9 +275,8 @@ public class ScreenshotController {
|
|||||||
mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
|
mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void takeScreenshotFullscreen(Consumer<Uri> finisher, Runnable onComplete) {
|
void takeScreenshotFullscreen(Consumer<Uri> finisher, RequestCallback requestCallback) {
|
||||||
mOnCompleteRunnable = onComplete;
|
mCurrentRequestCallback = requestCallback;
|
||||||
|
|
||||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||||
getDefaultDisplay().getRealMetrics(displayMetrics);
|
getDefaultDisplay().getRealMetrics(displayMetrics);
|
||||||
takeScreenshotInternal(
|
takeScreenshotInternal(
|
||||||
@@ -287,16 +286,14 @@ public class ScreenshotController {
|
|||||||
|
|
||||||
void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
|
void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
|
||||||
Insets visibleInsets, int taskId, int userId, ComponentName topComponent,
|
Insets visibleInsets, int taskId, int userId, ComponentName topComponent,
|
||||||
Consumer<Uri> finisher, Runnable onComplete) {
|
Consumer<Uri> finisher, RequestCallback requestCallback) {
|
||||||
// TODO: use task Id, userId, topComponent for smart handler
|
// TODO: use task Id, userId, topComponent for smart handler
|
||||||
mOnCompleteRunnable = onComplete;
|
|
||||||
|
|
||||||
if (screenshot == null) {
|
if (screenshot == null) {
|
||||||
Log.e(TAG, "Got null bitmap from screenshot message");
|
Log.e(TAG, "Got null bitmap from screenshot message");
|
||||||
mNotificationsController.notifyScreenshotError(
|
mNotificationsController.notifyScreenshotError(
|
||||||
R.string.screenshot_failed_to_capture_text);
|
R.string.screenshot_failed_to_capture_text);
|
||||||
finisher.accept(null);
|
requestCallback.reportError();
|
||||||
mOnCompleteRunnable.run();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,17 +303,19 @@ public class ScreenshotController {
|
|||||||
visibleInsets = Insets.NONE;
|
visibleInsets = Insets.NONE;
|
||||||
screenshotScreenBounds.set(0, 0, screenshot.getWidth(), screenshot.getHeight());
|
screenshotScreenBounds.set(0, 0, screenshot.getWidth(), screenshot.getHeight());
|
||||||
}
|
}
|
||||||
|
mCurrentRequestCallback = requestCallback;
|
||||||
saveScreenshot(screenshot, finisher, screenshotScreenBounds, visibleInsets, showFlash);
|
saveScreenshot(screenshot, finisher, screenshotScreenBounds, visibleInsets, showFlash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a screenshot selector
|
* Displays a screenshot selector
|
||||||
*/
|
*/
|
||||||
void takeScreenshotPartial(final Consumer<Uri> finisher, Runnable onComplete) {
|
void takeScreenshotPartial(final Consumer<Uri> finisher, RequestCallback requestCallback) {
|
||||||
dismissScreenshot(true);
|
mScreenshotView.reset();
|
||||||
mOnCompleteRunnable = onComplete;
|
mCurrentRequestCallback = requestCallback;
|
||||||
|
|
||||||
mWindowManager.addView(mScreenshotView, mWindowLayoutParams);
|
attachWindow();
|
||||||
|
mWindow.setContentView(mScreenshotView);
|
||||||
|
|
||||||
mScreenshotView.takePartialScreenshot(
|
mScreenshotView.takePartialScreenshot(
|
||||||
rect -> takeScreenshotInternal(finisher, rect));
|
rect -> takeScreenshotInternal(finisher, rect));
|
||||||
@@ -337,9 +336,9 @@ public class ScreenshotController {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
|
cancelTimeout();
|
||||||
if (immediate) {
|
if (immediate) {
|
||||||
resetScreenshotView();
|
finishDismiss();
|
||||||
} else {
|
} else {
|
||||||
mScreenshotView.animateDismissal();
|
mScreenshotView.animateDismissal();
|
||||||
}
|
}
|
||||||
@@ -354,6 +353,8 @@ public class ScreenshotController {
|
|||||||
*/
|
*/
|
||||||
void releaseContext() {
|
void releaseContext() {
|
||||||
mContext.release();
|
mContext.release();
|
||||||
|
mCameraSound.release();
|
||||||
|
mBgExecutor.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -363,12 +364,8 @@ public class ScreenshotController {
|
|||||||
if (DEBUG_UI) {
|
if (DEBUG_UI) {
|
||||||
Log.d(TAG, "reloadAssets()");
|
Log.d(TAG, "reloadAssets()");
|
||||||
}
|
}
|
||||||
boolean wasAttached = mDecorView.isAttachedToWindow();
|
if (mScreenshotView != null && mScreenshotView.isAttachedToWindow()) {
|
||||||
if (wasAttached) {
|
mWindow.clearContentView(); // Is there a simpler way to say "remove screenshotView?"
|
||||||
if (DEBUG_WINDOW) {
|
|
||||||
Log.d(TAG, "Removing screenshot window");
|
|
||||||
}
|
|
||||||
mWindowManager.removeView(mDecorView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// respect the display cutout in landscape (since we'd otherwise overlap) but not portrait
|
// respect the display cutout in landscape (since we'd otherwise overlap) but not portrait
|
||||||
@@ -376,12 +373,6 @@ public class ScreenshotController {
|
|||||||
mWindowLayoutParams.setFitInsetsTypes(
|
mWindowLayoutParams.setFitInsetsTypes(
|
||||||
orientation == ORIENTATION_PORTRAIT ? 0 : WindowInsets.Type.displayCutout());
|
orientation == ORIENTATION_PORTRAIT ? 0 : WindowInsets.Type.displayCutout());
|
||||||
|
|
||||||
// ignore system bar insets for the purpose of window layout
|
|
||||||
mDecorView.setOnApplyWindowInsetsListener((v, insets) -> v.onApplyWindowInsets(
|
|
||||||
new WindowInsets.Builder(insets)
|
|
||||||
.setInsets(WindowInsets.Type.all(), Insets.NONE)
|
|
||||||
.build()));
|
|
||||||
|
|
||||||
// Inflate the screenshot layout
|
// Inflate the screenshot layout
|
||||||
mScreenshotView = (ScreenshotView)
|
mScreenshotView = (ScreenshotView)
|
||||||
LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
|
LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
|
||||||
@@ -393,12 +384,18 @@ public class ScreenshotController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDismiss() {
|
public void onDismiss() {
|
||||||
resetScreenshotView();
|
finishDismiss();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ignore system bar insets for the purpose of window layout
|
||||||
|
mScreenshotView.setOnApplyWindowInsetsListener((v, insets) -> v.onApplyWindowInsets(
|
||||||
|
new WindowInsets.Builder(insets)
|
||||||
|
.setInsets(WindowInsets.Type.all(), Insets.NONE)
|
||||||
|
.build()));
|
||||||
|
|
||||||
// TODO(159460485): Remove this when focus is handled properly in the system
|
// TODO(159460485): Remove this when focus is handled properly in the system
|
||||||
mDecorView.setOnTouchListener((v, event) -> {
|
mScreenshotView.setOnTouchListener((v, event) -> {
|
||||||
if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
|
if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
|
||||||
if (DEBUG_INPUT) {
|
if (DEBUG_INPUT) {
|
||||||
Log.d(TAG, "onTouch: ACTION_OUTSIDE");
|
Log.d(TAG, "onTouch: ACTION_OUTSIDE");
|
||||||
@@ -420,8 +417,10 @@ public class ScreenshotController {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// view is added to window manager in startAnimation
|
if (DEBUG_WINDOW) {
|
||||||
mWindow.setContentView(mScreenshotView, mWindowLayoutParams);
|
Log.d(TAG, "adding OnComputeInternalInsetsListener");
|
||||||
|
}
|
||||||
|
mScreenshotView.getViewTreeObserver().addOnComputeInternalInsetsListener(mScreenshotView);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -458,14 +457,9 @@ public class ScreenshotController {
|
|||||||
Log.e(TAG, "takeScreenshotInternal: Screenshot bitmap was null");
|
Log.e(TAG, "takeScreenshotInternal: Screenshot bitmap was null");
|
||||||
mNotificationsController.notifyScreenshotError(
|
mNotificationsController.notifyScreenshotError(
|
||||||
R.string.screenshot_failed_to_capture_text);
|
R.string.screenshot_failed_to_capture_text);
|
||||||
if (DEBUG_CALLBACK) {
|
if (mCurrentRequestCallback != null) {
|
||||||
Log.d(TAG, "Supplying null to Consumer<Uri>");
|
mCurrentRequestCallback.reportError();
|
||||||
}
|
}
|
||||||
finisher.accept(null);
|
|
||||||
if (DEBUG_CALLBACK) {
|
|
||||||
Log.d(TAG, "Calling mOnCompleteRunnable.run()");
|
|
||||||
}
|
|
||||||
mOnCompleteRunnable.run();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,6 +476,13 @@ public class ScreenshotController {
|
|||||||
mAccessibilityManager.sendAccessibilityEvent(event);
|
mAccessibilityManager.sendAccessibilityEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mConfigChanges.applyNewConfig(mContext.getResources())) {
|
||||||
|
if (DEBUG_UI) {
|
||||||
|
Log.d(TAG, "saveScreenshot: reloading assets");
|
||||||
|
}
|
||||||
|
reloadAssets();
|
||||||
|
}
|
||||||
|
|
||||||
if (mScreenshotView.isAttachedToWindow()) {
|
if (mScreenshotView.isAttachedToWindow()) {
|
||||||
// if we didn't already dismiss for another reason
|
// if we didn't already dismiss for another reason
|
||||||
if (!mScreenshotView.isDismissing()) {
|
if (!mScreenshotView.isDismissing()) {
|
||||||
@@ -508,18 +509,101 @@ public class ScreenshotController {
|
|||||||
mScreenBitmap.setHasAlpha(false);
|
mScreenBitmap.setHasAlpha(false);
|
||||||
mScreenBitmap.prepareToDraw();
|
mScreenBitmap.prepareToDraw();
|
||||||
|
|
||||||
if (mConfigChanges.applyNewConfig(mContext.getResources())) {
|
saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady);
|
||||||
if (DEBUG_UI) {
|
|
||||||
Log.d(TAG, "saveScreenshot: reloading assets");
|
|
||||||
}
|
|
||||||
reloadAssets();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The window is focusable by default
|
// The window is focusable by default
|
||||||
setWindowFocusable(true);
|
setWindowFocusable(true);
|
||||||
|
|
||||||
// Start the post-screenshot animation
|
if (mConfigProxy.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||||
startAnimation(finisher, screenRect, screenInsets, showFlash);
|
SystemUiDeviceConfigFlags.SCREENSHOT_SCROLLING_ENABLED, false)) {
|
||||||
|
View decorView = mWindow.getDecorView();
|
||||||
|
|
||||||
|
// Wait until this window is attached to request because it is
|
||||||
|
// the reference used to locate the target window (below).
|
||||||
|
withWindowAttached(() -> {
|
||||||
|
mScrollCaptureClient.setHostWindowToken(decorView.getWindowToken());
|
||||||
|
mScrollCaptureClient.request(DEFAULT_DISPLAY,
|
||||||
|
/* onConnection */
|
||||||
|
(connection) -> mScreenshotHandler.post(() ->
|
||||||
|
mScreenshotView.showScrollChip(() ->
|
||||||
|
/* onClick */
|
||||||
|
runScrollCapture(connection))));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
attachWindow();
|
||||||
|
if (DEBUG_WINDOW) {
|
||||||
|
Log.d(TAG, "setContentView: " + mScreenshotView);
|
||||||
|
}
|
||||||
|
mScreenshotView.getViewTreeObserver().addOnPreDrawListener(
|
||||||
|
new ViewTreeObserver.OnPreDrawListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreDraw() {
|
||||||
|
if (DEBUG_WINDOW) {
|
||||||
|
Log.d(TAG, "onPreDraw: startAnimation");
|
||||||
|
}
|
||||||
|
mScreenshotView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||||
|
startAnimation(screenRect, showFlash);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mScreenshotView.setScreenshot(mScreenBitmap, screenInsets);
|
||||||
|
setContentView(mScreenshotView);
|
||||||
|
cancelTimeout(); // restarted after animation
|
||||||
|
}
|
||||||
|
|
||||||
|
private void withWindowAttached(Runnable action) {
|
||||||
|
View decorView = mWindow.getDecorView();
|
||||||
|
if (decorView.isAttachedToWindow()) {
|
||||||
|
action.run();
|
||||||
|
} else {
|
||||||
|
decorView.getViewTreeObserver().addOnWindowAttachListener(
|
||||||
|
new ViewTreeObserver.OnWindowAttachListener() {
|
||||||
|
@Override
|
||||||
|
public void onWindowAttached() {
|
||||||
|
decorView.getViewTreeObserver().removeOnWindowAttachListener(this);
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowDetached() { }
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setContentView(View contentView) {
|
||||||
|
mWindow.setContentView(contentView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachWindow() {
|
||||||
|
View decorView = mWindow.getDecorView();
|
||||||
|
if (decorView.isAttachedToWindow()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG_WINDOW) {
|
||||||
|
Log.d(TAG, "attachWindow");
|
||||||
|
}
|
||||||
|
mWindowManager.addView(decorView, mWindowLayoutParams);
|
||||||
|
decorView.requestApplyInsets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeWindow() {
|
||||||
|
final View decorView = mWindow.peekDecorView();
|
||||||
|
if (decorView != null && decorView.isAttachedToWindow()) {
|
||||||
|
if (DEBUG_WINDOW) {
|
||||||
|
Log.d(TAG, "Removing screenshot window");
|
||||||
|
}
|
||||||
|
mWindowManager.removeViewImmediate(decorView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runScrollCapture(ScrollCaptureClient.Connection connection) {
|
||||||
|
cancelTimeout();
|
||||||
|
ScrollCaptureController controller = new ScrollCaptureController(mContext, connection,
|
||||||
|
mMainExecutor, mBgExecutor, mImageExporter);
|
||||||
|
controller.start(/* onDismiss */ () -> dismissScreenshot(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -528,11 +612,11 @@ public class ScreenshotController {
|
|||||||
*/
|
*/
|
||||||
private void saveScreenshotAndToast(Consumer<Uri> finisher) {
|
private void saveScreenshotAndToast(Consumer<Uri> finisher) {
|
||||||
// Play the shutter sound to notify that we've taken a screenshot
|
// Play the shutter sound to notify that we've taken a screenshot
|
||||||
mScreenshotHandler.post(() -> {
|
|
||||||
mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
|
mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
|
||||||
});
|
|
||||||
|
|
||||||
saveScreenshotInWorkerThread(finisher, imageData -> {
|
saveScreenshotInWorkerThread(
|
||||||
|
/* onComplete */ finisher,
|
||||||
|
/* actionsReadyListener */ imageData -> {
|
||||||
if (DEBUG_CALLBACK) {
|
if (DEBUG_CALLBACK) {
|
||||||
Log.d(TAG, "returning URI to finisher (Consumer<URI>): " + imageData.uri);
|
Log.d(TAG, "returning URI to finisher (Consumer<URI>): " + imageData.uri);
|
||||||
}
|
}
|
||||||
@@ -549,65 +633,17 @@ public class ScreenshotController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If scrolling is enabled, check whether the current view is scrollable and if so, show the
|
|
||||||
* scroll chip.
|
|
||||||
*/
|
|
||||||
private void maybeRequestScrollCapture() {
|
|
||||||
if (mConfigProxy.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
|
|
||||||
SystemUiDeviceConfigFlags.SCREENSHOT_SCROLLING_ENABLED, false)) {
|
|
||||||
mScrollCaptureClient.setHostWindowToken(mDecorView.getWindowToken());
|
|
||||||
mScrollCaptureClient.request(DEFAULT_DISPLAY, (connection) ->
|
|
||||||
mScreenshotView.showScrollChip(() -> {
|
|
||||||
ScrollCaptureController controller = new ScrollCaptureController(
|
|
||||||
mContext, connection, mMainExecutor, mBgExecutor, mImageExporter);
|
|
||||||
controller.run(() -> mScreenshotHandler.post(
|
|
||||||
() -> dismissScreenshot(false)));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the animation after taking the screenshot
|
* Starts the animation after taking the screenshot
|
||||||
*/
|
*/
|
||||||
private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets,
|
private void startAnimation(Rect screenRect, boolean showFlash) {
|
||||||
boolean showFlash) {
|
if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
|
||||||
mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
|
mScreenshotAnimation.cancel();
|
||||||
mScreenshotHandler.post(() -> {
|
|
||||||
if (!mDecorView.isAttachedToWindow()) {
|
|
||||||
if (DEBUG_WINDOW) {
|
|
||||||
Log.d(TAG, "Adding screenshot window");
|
|
||||||
}
|
}
|
||||||
mDecorView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onViewAttachedToWindow(View v) {
|
|
||||||
mDecorView.removeOnAttachStateChangeListener(this);
|
|
||||||
maybeRequestScrollCapture();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewDetachedFromWindow(View v) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mWindowManager.addView(mWindow.getDecorView(), mWindowLayoutParams);
|
|
||||||
} else {
|
|
||||||
maybeRequestScrollCapture();
|
|
||||||
}
|
|
||||||
|
|
||||||
mScreenshotView.prepareForAnimation(mScreenBitmap, screenInsets);
|
|
||||||
|
|
||||||
mScreenshotHandler.post(() -> {
|
|
||||||
if (DEBUG_WINDOW) {
|
|
||||||
Log.d(TAG, "adding OnComputeInternalInsetsListener");
|
|
||||||
}
|
|
||||||
mScreenshotView.getViewTreeObserver().addOnComputeInternalInsetsListener(
|
|
||||||
mScreenshotView);
|
|
||||||
|
|
||||||
mScreenshotAnimation =
|
mScreenshotAnimation =
|
||||||
mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash);
|
mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash);
|
||||||
|
|
||||||
saveScreenshotInWorkerThread(finisher, this::showUiOnActionsReady);
|
|
||||||
|
|
||||||
// Play the shutter sound to notify that we've taken a screenshot
|
// Play the shutter sound to notify that we've taken a screenshot
|
||||||
mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
|
mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
|
||||||
|
|
||||||
@@ -615,23 +651,20 @@ public class ScreenshotController {
|
|||||||
Log.d(TAG, "starting post-screenshot animation");
|
Log.d(TAG, "starting post-screenshot animation");
|
||||||
}
|
}
|
||||||
mScreenshotAnimation.start();
|
mScreenshotAnimation.start();
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reset screenshot view and then call onCompleteRunnable */
|
/** Reset screenshot view and then call onCompleteRunnable */
|
||||||
private void resetScreenshotView() {
|
private void finishDismiss() {
|
||||||
if (DEBUG_UI) {
|
if (DEBUG_UI) {
|
||||||
Log.d(TAG, "resetScreenshotView");
|
Log.d(TAG, "finishDismiss");
|
||||||
}
|
}
|
||||||
if (mScreenshotView.isAttachedToWindow()) {
|
cancelTimeout();
|
||||||
if (DEBUG_WINDOW) {
|
removeWindow();
|
||||||
Log.d(TAG, "Removing screenshot window");
|
|
||||||
}
|
|
||||||
mWindowManager.removeViewImmediate(mDecorView);
|
|
||||||
}
|
|
||||||
mOnCompleteRunnable.run();
|
|
||||||
mScreenshotView.reset();
|
mScreenshotView.reset();
|
||||||
|
if (mCurrentRequestCallback != null) {
|
||||||
|
mCurrentRequestCallback.onFinish();
|
||||||
|
mCurrentRequestCallback = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -655,8 +688,12 @@ public class ScreenshotController {
|
|||||||
mSaveInBgTask.execute();
|
mSaveInBgTask.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetTimeout() {
|
private void cancelTimeout() {
|
||||||
mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
|
mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetTimeout() {
|
||||||
|
cancelTimeout();
|
||||||
|
|
||||||
AccessibilityManager accessibilityManager = (AccessibilityManager)
|
AccessibilityManager accessibilityManager = (AccessibilityManager)
|
||||||
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||||
@@ -715,7 +752,7 @@ public class ScreenshotController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hideSharedElements() {
|
public void hideSharedElements() {
|
||||||
resetScreenshotView();
|
finishDismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -763,13 +800,21 @@ public class ScreenshotController {
|
|||||||
if (DEBUG_WINDOW) {
|
if (DEBUG_WINDOW) {
|
||||||
Log.d(TAG, "setWindowFocusable: " + focusable);
|
Log.d(TAG, "setWindowFocusable: " + focusable);
|
||||||
}
|
}
|
||||||
|
int flags = mWindowLayoutParams.flags;
|
||||||
if (focusable) {
|
if (focusable) {
|
||||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||||
} else {
|
} else {
|
||||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||||
}
|
}
|
||||||
if (mDecorView.isAttachedToWindow()) {
|
if (mWindowLayoutParams.flags == flags) {
|
||||||
mWindowManager.updateViewLayout(mDecorView, mWindowLayoutParams);
|
if (DEBUG_WINDOW) {
|
||||||
|
Log.d(TAG, "setWindowFocusable: skipping, already " + focusable);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final View decorView = mWindow.peekDecorView();
|
||||||
|
if (decorView != null && decorView.isAttachedToWindow()) {
|
||||||
|
mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -316,21 +316,21 @@ public class ScreenshotView extends FrameLayout implements
|
|||||||
mScreenshotSelectorView.requestFocus();
|
mScreenshotSelectorView.requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareForAnimation(Bitmap bitmap, Insets screenInsets) {
|
void setScreenshot(Bitmap bitmap, Insets screenInsets) {
|
||||||
mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
|
mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
|
||||||
// make static preview invisible (from gone) so we can query its location on screen
|
|
||||||
mScreenshotPreview.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) {
|
AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) {
|
||||||
mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
if (DEBUG_ANIM) {
|
||||||
mScreenshotPreview.buildLayer();
|
Log.d(TAG, "createAnim: bounds=" + bounds + " showFlash=" + showFlash);
|
||||||
|
}
|
||||||
|
|
||||||
Rect previewBounds = new Rect();
|
Rect previewBounds = new Rect();
|
||||||
mScreenshotPreview.getBoundsOnScreen(previewBounds);
|
mScreenshotPreview.getBoundsOnScreen(previewBounds);
|
||||||
int[] previewLocation = new int[2];
|
Rect targetPosition = new Rect();
|
||||||
mScreenshotPreview.getLocationInWindow(previewLocation);
|
mScreenshotPreview.getHitRect(targetPosition);
|
||||||
|
|
||||||
|
// ratio of preview width, end vs. start size
|
||||||
float cornerScale =
|
float cornerScale =
|
||||||
mCornerSizeX / (mOrientationPortrait ? bounds.width() : bounds.height());
|
mCornerSizeX / (mOrientationPortrait ? bounds.width() : bounds.height());
|
||||||
final float currentScale = 1 / cornerScale;
|
final float currentScale = 1 / cornerScale;
|
||||||
@@ -358,8 +358,13 @@ public class ScreenshotView extends FrameLayout implements
|
|||||||
|
|
||||||
// animate from the current location, to the static preview location
|
// animate from the current location, to the static preview location
|
||||||
final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
|
final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
|
||||||
final PointF finalPos = new PointF(previewLocation[0] + previewBounds.width() / 2f,
|
final PointF finalPos = new PointF(targetPosition.exactCenterX(),
|
||||||
previewLocation[1] + previewBounds.height() / 2f);
|
targetPosition.exactCenterY());
|
||||||
|
|
||||||
|
if (DEBUG_ANIM) {
|
||||||
|
Log.d(TAG, "toCorner: startPos=" + startPos);
|
||||||
|
Log.d(TAG, "toCorner: finalPos=" + finalPos);
|
||||||
|
}
|
||||||
|
|
||||||
ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
|
ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
|
||||||
toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
|
toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
|
||||||
@@ -427,7 +432,7 @@ public class ScreenshotView extends FrameLayout implements
|
|||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (DEBUG_ANIM) {
|
if (DEBUG_ANIM) {
|
||||||
Log.d(TAG, "drop-in animation completed");
|
Log.d(TAG, "drop-in animation ended");
|
||||||
}
|
}
|
||||||
mDismissButton.setOnClickListener(view -> {
|
mDismissButton.setOnClickListener(view -> {
|
||||||
if (DEBUG_INPUT) {
|
if (DEBUG_INPUT) {
|
||||||
@@ -653,13 +658,12 @@ public class ScreenshotView extends FrameLayout implements
|
|||||||
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
|
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
|
||||||
// Clear any references to the bitmap
|
// Clear any references to the bitmap
|
||||||
mScreenshotPreview.setImageDrawable(null);
|
mScreenshotPreview.setImageDrawable(null);
|
||||||
|
mScreenshotPreview.setVisibility(View.INVISIBLE);
|
||||||
mPendingSharedTransition = false;
|
mPendingSharedTransition = false;
|
||||||
mActionsContainerBackground.setVisibility(View.GONE);
|
mActionsContainerBackground.setVisibility(View.GONE);
|
||||||
mActionsContainer.setVisibility(View.GONE);
|
mActionsContainer.setVisibility(View.GONE);
|
||||||
mBackgroundProtection.setAlpha(0f);
|
mBackgroundProtection.setAlpha(0f);
|
||||||
mDismissButton.setVisibility(View.GONE);
|
mDismissButton.setVisibility(View.GONE);
|
||||||
mScreenshotPreview.setVisibility(View.GONE);
|
|
||||||
mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null);
|
|
||||||
mScreenshotStatic.setTranslationX(0);
|
mScreenshotStatic.setTranslationX(0);
|
||||||
mScreenshotPreview.setTranslationY(0);
|
mScreenshotPreview.setTranslationY(0);
|
||||||
mScreenshotPreview.setContentDescription(
|
mScreenshotPreview.setContentDescription(
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class ScrollCaptureController {
|
|||||||
*
|
*
|
||||||
* @param after action to take after the flow is complete
|
* @param after action to take after the flow is complete
|
||||||
*/
|
*/
|
||||||
public void run(final Runnable after) {
|
public void start(final Runnable after) {
|
||||||
mCaptureTime = ZonedDateTime.now();
|
mCaptureTime = ZonedDateTime.now();
|
||||||
mRequestId = UUID.randomUUID();
|
mRequestId = UUID.randomUUID();
|
||||||
mConnection.start((session) -> startCapture(session, after));
|
mConnection.start((session) -> startCapture(session, after));
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS;
|
|||||||
import static com.android.systemui.screenshot.LogConfig.DEBUG_SERVICE;
|
import static com.android.systemui.screenshot.LogConfig.DEBUG_SERVICE;
|
||||||
import static com.android.systemui.screenshot.LogConfig.logTag;
|
import static com.android.systemui.screenshot.LogConfig.logTag;
|
||||||
|
|
||||||
|
import android.annotation.MainThread;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -59,7 +60,8 @@ import javax.inject.Inject;
|
|||||||
public class TakeScreenshotService extends Service {
|
public class TakeScreenshotService extends Service {
|
||||||
private static final String TAG = logTag(TakeScreenshotService.class);
|
private static final String TAG = logTag(TakeScreenshotService.class);
|
||||||
|
|
||||||
private final ScreenshotController mScreenshot;
|
private ScreenshotController mScreenshot;
|
||||||
|
|
||||||
private final UserManager mUserManager;
|
private final UserManager mUserManager;
|
||||||
private final UiEventLogger mUiEventLogger;
|
private final UiEventLogger mUiEventLogger;
|
||||||
private final ScreenshotNotificationsController mNotificationsController;
|
private final ScreenshotNotificationsController mNotificationsController;
|
||||||
@@ -79,6 +81,15 @@ public class TakeScreenshotService extends Service {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Informs about coarse grained state of the Controller. */
|
||||||
|
interface RequestCallback {
|
||||||
|
/** Respond to the current request indicating the screenshot request failed.*/
|
||||||
|
void reportError();
|
||||||
|
|
||||||
|
/** The controller has completed handling this request UI has been removed */
|
||||||
|
void onFinish();
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TakeScreenshotService(ScreenshotController screenshotController, UserManager userManager,
|
public TakeScreenshotService(ScreenshotController screenshotController, UserManager userManager,
|
||||||
UiEventLogger uiEventLogger,
|
UiEventLogger uiEventLogger,
|
||||||
@@ -116,7 +127,8 @@ public class TakeScreenshotService extends Service {
|
|||||||
Log.d(TAG, "onUnbind");
|
Log.d(TAG, "onUnbind");
|
||||||
}
|
}
|
||||||
if (mScreenshot != null) {
|
if (mScreenshot != null) {
|
||||||
mScreenshot.dismissScreenshot(true);
|
mScreenshot.removeWindow();
|
||||||
|
mScreenshot = null;
|
||||||
}
|
}
|
||||||
unregisterReceiver(mCloseSystemDialogs);
|
unregisterReceiver(mCloseSystemDialogs);
|
||||||
return false;
|
return false;
|
||||||
@@ -126,18 +138,39 @@ public class TakeScreenshotService extends Service {
|
|||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (mScreenshot != null) {
|
if (mScreenshot != null) {
|
||||||
|
mScreenshot.removeWindow();
|
||||||
mScreenshot.releaseContext();
|
mScreenshot.releaseContext();
|
||||||
|
mScreenshot = null;
|
||||||
}
|
}
|
||||||
if (DEBUG_SERVICE) {
|
if (DEBUG_SERVICE) {
|
||||||
Log.d(TAG, "onDestroy");
|
Log.d(TAG, "onDestroy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class RequestCallbackImpl implements RequestCallback {
|
||||||
|
private final Messenger mReplyTo;
|
||||||
|
|
||||||
|
RequestCallbackImpl(Messenger replyTo) {
|
||||||
|
mReplyTo = replyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportError() {
|
||||||
|
reportUri(mReplyTo, null);
|
||||||
|
sendComplete(mReplyTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
sendComplete(mReplyTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Respond to incoming Message via Binder (Messenger) */
|
/** Respond to incoming Message via Binder (Messenger) */
|
||||||
|
@MainThread
|
||||||
private boolean handleMessage(Message msg) {
|
private boolean handleMessage(Message msg) {
|
||||||
final Messenger replyTo = msg.replyTo;
|
final Messenger replyTo = msg.replyTo;
|
||||||
final Runnable onComplete = () -> sendComplete(replyTo);
|
|
||||||
final Consumer<Uri> uriConsumer = (uri) -> reportUri(replyTo, uri);
|
final Consumer<Uri> uriConsumer = (uri) -> reportUri(replyTo, uri);
|
||||||
|
RequestCallback requestCallback = new RequestCallbackImpl(replyTo);
|
||||||
|
|
||||||
// If the storage for this user is locked, we have no place to store
|
// If the storage for this user is locked, we have no place to store
|
||||||
// the screenshot, so skip taking it instead of showing a misleading
|
// the screenshot, so skip taking it instead of showing a misleading
|
||||||
@@ -146,14 +179,7 @@ public class TakeScreenshotService extends Service {
|
|||||||
Log.w(TAG, "Skipping screenshot because storage is locked!");
|
Log.w(TAG, "Skipping screenshot because storage is locked!");
|
||||||
mNotificationsController.notifyScreenshotError(
|
mNotificationsController.notifyScreenshotError(
|
||||||
R.string.screenshot_failed_to_save_user_locked_text);
|
R.string.screenshot_failed_to_save_user_locked_text);
|
||||||
if (DEBUG_CALLBACK) {
|
requestCallback.reportError();
|
||||||
Log.d(TAG, "handleMessage: calling uriConsumer.accept(null)");
|
|
||||||
}
|
|
||||||
uriConsumer.accept(null);
|
|
||||||
if (DEBUG_CALLBACK) {
|
|
||||||
Log.d(TAG, "handleMessage: calling onComplete.run()");
|
|
||||||
}
|
|
||||||
onComplete.run();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,13 +193,13 @@ public class TakeScreenshotService extends Service {
|
|||||||
if (DEBUG_SERVICE) {
|
if (DEBUG_SERVICE) {
|
||||||
Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_FULLSCREEN");
|
Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_FULLSCREEN");
|
||||||
}
|
}
|
||||||
mScreenshot.takeScreenshotFullscreen(uriConsumer, onComplete);
|
mScreenshot.takeScreenshotFullscreen(uriConsumer, requestCallback);
|
||||||
break;
|
break;
|
||||||
case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION:
|
case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION:
|
||||||
if (DEBUG_SERVICE) {
|
if (DEBUG_SERVICE) {
|
||||||
Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_SELECTED_REGION");
|
Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_SELECTED_REGION");
|
||||||
}
|
}
|
||||||
mScreenshot.takeScreenshotPartial(uriConsumer, onComplete);
|
mScreenshot.takeScreenshotPartial(uriConsumer, requestCallback);
|
||||||
break;
|
break;
|
||||||
case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:
|
case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:
|
||||||
if (DEBUG_SERVICE) {
|
if (DEBUG_SERVICE) {
|
||||||
@@ -186,8 +212,16 @@ public class TakeScreenshotService extends Service {
|
|||||||
int taskId = screenshotRequest.getTaskId();
|
int taskId = screenshotRequest.getTaskId();
|
||||||
int userId = screenshotRequest.getUserId();
|
int userId = screenshotRequest.getUserId();
|
||||||
ComponentName topComponent = screenshotRequest.getTopComponent();
|
ComponentName topComponent = screenshotRequest.getTopComponent();
|
||||||
|
|
||||||
|
if (screenshot == null) {
|
||||||
|
Log.e(TAG, "Got null bitmap from screenshot message");
|
||||||
|
mNotificationsController.notifyScreenshotError(
|
||||||
|
R.string.screenshot_failed_to_capture_text);
|
||||||
|
requestCallback.reportError();
|
||||||
|
} else {
|
||||||
mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,
|
mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,
|
||||||
taskId, userId, topComponent, uriConsumer, onComplete);
|
taskId, userId, topComponent, uriConsumer, requestCallback);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.w(TAG, "Invalid screenshot option: " + msg.what);
|
Log.w(TAG, "Invalid screenshot option: " + msg.what);
|
||||||
@@ -196,7 +230,7 @@ public class TakeScreenshotService extends Service {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
private void sendComplete(Messenger target) {
|
private static void sendComplete(Messenger target) {
|
||||||
try {
|
try {
|
||||||
if (DEBUG_CALLBACK) {
|
if (DEBUG_CALLBACK) {
|
||||||
Log.d(TAG, "sendComplete: " + target);
|
Log.d(TAG, "sendComplete: " + target);
|
||||||
@@ -207,7 +241,7 @@ public class TakeScreenshotService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportUri(Messenger target, Uri uri) {
|
private static void reportUri(Messenger target, Uri uri) {
|
||||||
try {
|
try {
|
||||||
if (DEBUG_CALLBACK) {
|
if (DEBUG_CALLBACK) {
|
||||||
Log.d(TAG, "reportUri: " + target + " -> " + uri);
|
Log.d(TAG, "reportUri: " + target + " -> " + uri);
|
||||||
|
|||||||
Reference in New Issue
Block a user