Android截屏源码分析

Android截屏源码分析
手机通过按power键和音量下键进行截屏源码分析:
从图1中可以看到InputReaderThread线程从驱动读取数据并处理过程。


图1、从驱动读取数据并处理过程
首先通过InputReaderThread::threadLoop()进入线程池,实时判断是否有事件读取。
frameworks/base/services/input/InputReader.cpp
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
/*
frameworks/base/services/input/EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);//从驱动读取事件
}
*/
processEventsLocked(mEventBuffer, count);
}

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
}
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
device->process(rawEvents, count);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
//该设备的所有mapper进行处理;注意:这里使用了多态
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
}

//KeyboardInput按键设备
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
}
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
int32_t scanCode, uint32_t policyFlags) {
getListener()->notifyKey(&args);
}

InputReaderThread线程对系统层按键做处理(比较重要的是POWER键,最终在PhoneWindowManager中的interceptKeyBeforeQueueing和interceptMotionBeforeQueueingWhenScreenOff)后分发给InputDispatcherThread线程
以下几种情况都会唤醒InputDispatcherThread线程,即调用mLooper->wake()唤醒正在awoken()中的InputReaderThread线程:
frameworks/base/services/input/InputDispatcher.cpp
//首先定义了一个InputDispatcherPolicyInterface型的职能指针mPolicy。
sp<InputDispatcherPolicyInterface> mPolicy;
//有新输入设备注册等
void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);
needWake = enqueueInboundEventLocked(newEntry);
if (needWake) {
mLooper->wake();
}
}
//分发按键事件
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
mPolicy->interceptKeyBeforeQueueing(&event, policyFlags);
}
frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
由于NativeInputManager继承了类InputDispatcherPolicyInterface,即分发按键事件最终调用了类NativeInputManager中的函数interceptKeyBeforeQueueing。
class NativeInputManager : public virtual RefBase,
public virtual InputDispatcherPolicyInterface {
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
}
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags, isScreenOn);
//如下函数中将有待机和开机的处理
handleInterceptActions(wmActions, when, policyFlags);
}
通过jni调用frame层InputManagerService类中interceptKeyBeforeQueueing函数。
frameworks/base/service/java/com/android/server/input/InputManagerService.java
public class InputManagerService{
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
return mWindowManagerCallbacks.interceptKeyBeforeQueueing(
event, policyFlags, isScreenOn);
}
public interface WindowManagerCallbacks {
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
}
}
InputMonitor.java继承了InputManagerService中内部类WindowManagerCallbacks,函数回调InputMonitor中函数interceptKeyBeforeQueueing。
frameworks/base/service/java/com/android/server/wm/ InputMonitor.java
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
public int interceptKeyBeforeQueueing(
KeyEvent event, int policyFlags, boolean isScreenOn) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
}
通过以下代码分析最终会调用类PhoneWindowManager中interceptKeyBeforeQueueing函数。
frameworks/base/service/java/com/android/server/wm/WindowManagerService.java
final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();

frameworks/base/core/java/com/android/internal/policy/PolicyManager.java
public static WindowManagerPolicy makeNewWindowManager() {
return sPolicy.makeNewWindowManager();
}
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();

frameworks/base/core/java/com/android/internal/policy/Policy.java
package com.android.internal.policy.impl;
public class Policy implements IPolicy {
public WindowManagerPolicy makeNewWindowManager() {
return new PhoneWindowManager();
}
}
由以上步骤进行推理可得知所调用的方法如下:
frameworks/base/core/java/com/android/internal/policy/PhoneWindowManager.java
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (down) {
if (isScreenOn && !mVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
interceptScreenshotChord();
}
}
case KeyEvent.KEYCODE_POWER: {
if (down) {
if (isScreenOn && !mPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
interceptScreenshotChord();
}
}
}
private void interceptScreenshotChord() {
mHandler.postDelayed(mScreenshotChordLongPress, getScreenshotChordLongPressDelay());
}
最终会调用线程mScreenshotChordLongPress中的run方法
private final Runnable mScreenshotChordLongPress = new Runnable() {
public void run() {
takeScreenshot();
}
};

takeScreenshot();函数为Android截屏函数。到此为止,我们学习了如何从驱动获取信息,并上报给frame层,启动手机截屏函数。后续继续展开截屏函数如何通过frameworks层与驱动进行交互的过程。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值