ScreenShot流程

base/services/core/java/com/android/server/policy/PhoneWindowManager.java

物理截屏:按下power键和音量下键

private void initKeyCombinationRules() {mKeyCombinationManager = new KeyCombinationManager();final boolean screenshotChordEnabled = mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableScreenshotChord);if (screenshotChordEnabled) {mKeyCombinationManager.addRule(//按下电源键和音量下键new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_POWER) {@Overridevoid execute() {mPowerKeyHandled = true;interceptScreenshotChord();}@Overridevoid cancel() {cancelPendingScreenshotChordAction();}});}
}

收到截屏指令后,执行interceptScreenshotChord方法,

设置截屏类型

全屏:TAKE_SCREENSHOT_FULLSCREEN

用户选择区域:TAKE_SCREENSHOT_SELECTED_REGION

调用者提供的图像:TAKE_SCREENSHOT_PROVIDED_IMAGE

设置截屏来源

SCREENSHOT_KEY_CHORD

SCREENSHOT_KEY_OTHER

SCREENSHOT_OVERVIEW

SCREENSHOT_ACCESSIBILITY_ACTIONS

SCREENSHOT_OTHER

SCREENSHOT_VENDOR_GESTURE

private void interceptScreenshotChord() {mHandler.removeCallbacks(mScreenshotRunnable);mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);mScreenshotRunnable.setScreenshotSource(SCREENSHOT_KEY_CHORD);mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());}

执行ScreenRunnale.run()方法

private class ScreenshotRunnable implements Runnable {private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;private int mScreenshotSource = SCREENSHOT_KEY_OTHER;public void setScreenshotType(int screenshotType) {mScreenshotType = screenshotType;}public void setScreenshotSource(int screenshotSource) {mScreenshotSource = screenshotSource;}@Overridepublic void run() {mDefaultDisplayPolicy.takeScreenshot(mScreenshotType, mScreenshotSource);}}

截屏takeScreenshot()

base/services/core/java/com/android/server/wm/DisplayPolicy.java

public void takeScreenshot(int screenshotType, int source) {if (mScreenshotHelper != null) {mScreenshotHelper.takeScreenshot(screenshotType,getStatusBar() != null && getStatusBar().isVisible(),getNavigationBar() != null && getNavigationBar().isVisible(),source, mHandler, null /* completionConsumer */);}}

base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java

创建一个 GlobalScreenshot 对象,通过GlobalScreenshot对象实现截屏
private final GlobalScreenshot mScreenshot;

在Handler中对三种截屏方式做处理

private Handler mHandler = new Handler(Looper.myLooper()) {@Overridepublic void handleMessage(Message msg) {final Messenger callback = msg.replyTo;Consumer<Uri> uriConsumer = uri -> {Message reply = Message.obtain(null, SCREENSHOT_MSG_URI, uri);try {callback.send(reply);} catch (RemoteException e) {}};Runnable onComplete = () -> {Message reply = Message.obtain(null, SCREENSHOT_MSG_PROCESS_COMPLETE);try {callback.send(reply);} catch (RemoteException e) {}};// 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// animation and error notification.if (!mUserManager.isUserUnlocked()) {Log.w(TAG, "Skipping screenshot because storage is locked!");post(() -> uriConsumer.accept(null));post(onComplete);return;}ScreenshotHelper.ScreenshotRequest screenshotRequest =(ScreenshotHelper.ScreenshotRequest) msg.obj;mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshotRequest.getSource()));switch (msg.what) {case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:mScreenshot.takeScreenshot(uriConsumer, onComplete);break;case WindowManager.TAKE_SCREENSHOT_SELECTED_REGION:mScreenshot.takeScreenshotPartial(uriConsumer, onComplete);break;case WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE:Bitmap screenshot = BitmapUtil.bundleToHardwareBitmap(screenshotRequest.getBitmapBundle());Rect screenBounds = screenshotRequest.getBoundsInScreen();Insets insets = screenshotRequest.getInsets();int taskId = screenshotRequest.getTaskId();int userId = screenshotRequest.getUserId();ComponentName topComponent = screenshotRequest.getTopComponent();mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,taskId, userId, topComponent, uriConsumer, onComplete);break;default:Log.d(TAG, "Invalid screenshot option: " + msg.what);}}};

当截取全屏时

base/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java

private void takeScreenshot(Consumer<Uri> finisher, Rect crop) {// copy the input Rect, since SurfaceControl.screenshot can mutate itRect screenRect = new Rect(crop);int rot = mDisplay.getRotation();int width = crop.width();int height = crop.height();takeScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect,Insets.NONE, true);}private void takeScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,Insets screenInsets, boolean showFlash) {dismissScreenshot("new screenshot requested", true);mScreenBitmap = screenshot;if (mScreenBitmap == null) {mNotificationsController.notifyScreenshotError(R.string.screenshot_failed_to_capture_text);finisher.accept(null);mOnCompleteRunnable.run();return;}if (!isUserSetupComplete()) {// User setup isn't complete, so we don't want to show any UI beyond a toast, as editing// and sharing shouldn't be exposed to the user.saveScreenshotAndToast(finisher);return;}// OptimizationsmScreenBitmap.setHasAlpha(false);mScreenBitmap.prepareToDraw();onConfigChanged(mContext.getResources().getConfiguration());if (mDismissAnimation != null && mDismissAnimation.isRunning()) {mDismissAnimation.cancel();}// The window is focusable by defaultsetWindowFocusable(true);// Start the post-screenshot animationstartAnimation(finisher, screenRect, screenInsets, showFlash);}

截屏之后开始截屏动画

private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets,boolean showFlash) {// 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);if (powerManager.isPowerSaveMode()) {Toast.makeText(mContext, R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show();}mScreenshotHandler.post(() -> {if (!mScreenshotLayout.isAttachedToWindow()) {mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);}mScreenshotAnimatedView.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));setAnimatedViewSize(screenRect.width(), screenRect.height());// Show when the animation startsmScreenshotAnimatedView.setVisibility(View.GONE);mScreenshotPreview.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));// make static preview invisible (from gone) so we can query its location on screenmScreenshotPreview.setVisibility(View.INVISIBLE);mScreenshotHandler.post(() -> {mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);mScreenshotAnimation =createScreenshotDropInAnimation(screenRect, showFlash);saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {@Overridevoid onActionsReady(SavedImageData imageData) {showUiOnActionsReady(imageData);}});// Play the shutter sound to notify that we've taken a screenshotmCameraSound.play(MediaActionSound.SHUTTER_CLICK);mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);mScreenshotPreview.buildLayer();mScreenshotAnimation.start();});});}

SystemUI之ScreenShot相关推荐

  1. 屏幕截图 take screenshot

    ScreenCapture.CaptureScreenshotAsTexture yield return new WaitForEndOfFrame(); var screenShotTexture ...

  2. Android 4.0 截屏(Screenshot)代码流程小结

    Android 4.0 截屏 在Android 4.0 之前,Android手机上如果要使用截屏功能,只能通过Root手机,且使用第3方截图软件来实现截屏功能. Android4.0中,系统自带了截屏 ...

  3. Android核心程序之SystemUI - (一)开篇

    UI是实现用户交互的重要途径之一,而Android中一个重要的UI元素就是SystemUI,本文分析基于Android 5.1,分析SystemUI的启动及运行过程. SystemUI源代码所在路径为 ...

  4. Android 4.0 ICS SystemUI浅析——SystemUI启动流程

    阅读Android 4.0源码也有一段时间了,这次是针对SystemUI的一个学习过程.本文只是对SystemUI分析的一个开始--启动流程的分析,网上有很多关于2.3的SystemUI的分析,可4. ...

  5. Android源码学习------SystemUI(二)

    SystemUI----AndroidManifest文件 AndroidManifest是Android应用程序中最重要的文件之一.它是Android程序的全局配置文件,是每个 android程序中 ...

  6. SystemUi概述

    一.SystemUI概述 在Android系统中SystemUI是以应用的形式运行的.即编译SystemUI会产生APK文件.但它和普通的APK不同,它是开机启动的A并且不可以退出, SystemUI ...

  7. android 6.0 SystemUI源码分析(1)-SystemUI介绍

    1. SystemUI介绍 SystemUI是一个系统应用,主要功能有: 1)状态栏信息显示,比如电池,wifi信号,3G/4G等icon显示 2)通知面板,比如系统消息,第三方应用消息,都是在通知面 ...

  8. SystemUI架构分析学习

    目录 1.SystemUI路径及概念介绍 2.SystemUI主要功能 2.1Status bars详解 2.2Notification流程 2.3Navigation bars详解 1.System ...

  9. SystemUI深度裁剪

    SystemUI深度裁剪 前言 SystemUI AOSP包含了很多组件, Status bars,Navigation bars,Notification,Lockscreen,Quick sett ...

最新文章

  1. ednote服务器运行失败,endnote搜索文献时连不上服务器 Endnote连接服务器问题
  2. 解析自动驾驶算法四大模块的问题与后续发展
  3. #Sora#OpenStack基础库oslo.config试用总结
  4. Window.Open- ShowModalDialog- Window.Open Session丢失的Solution
  5. JMeter初探五-配置元件与参数化
  6. js数组去重,合集等操作
  7. 【bzoj4444】[Scoi2015]国旗计划 倍增
  8. linux学习笔记(11)df命令
  9. HCIE-OSPFV3
  10. 运行通达信行情接口软件的电脑需要什么配置?
  11. 在线浏览 Stata 15 PDF 全套电子手册
  12. 智能控制器在风机及水泵中的应用
  13. 头指针、头节点、首元结点——《王道数据结构》
  14. word2010怎样显示分节符?
  15. 幼儿园调查过程怎么写_幼儿园的调查报告范文
  16. Oracle管理的文件(OMF)的具体含义
  17. 方差分析介绍(结合COVID-19案例)
  18. 钟汉良日记:做短视频和直播的基础能力
  19. 大厂面试题含答案(二)
  20. 敏捷开发:一文了解影响地图和用户故事地图之间的那些事儿

热门文章

  1. su: failed to execute /bin/bash: Permission denied问题解决
  2. 英文论文-城市云脑,基于互联网云脑的智慧城市新架构
  3. 广东某大型餐厨垃圾处理设备 解决方案
  4. 【msvcp140.dll怎么下载】吃鸡msvcp140.dll丢失的解决方法
  5. 运动控制卡的运动控制介绍
  6. 解决中兴U880手机IMEI串号丢失的方法
  7. 安卓虚拟键盘_这是第一台安卓手机,当年谷歌和HTC靠它正面刚苹果|极客博物馆...
  8. Python爬虫实战:爬取贝壳网二手房40000条数据
  9. iCloud学习笔记
  10. 手把手带你免费部署https