注册

解析android匿名共享内存几个关键函数

基础知识

当我们在分析android的键盘记录的时候就不得不和input进行打交道,那么input在系统中是怎么进行实现的? Android手机中默认携带input子系统,并且开在机就会产生默认的mouse和keyboard事件,这样使得用户开机就可以触屏点击和使用按键。 android中键盘实现的系统源码位置\source\frameworks\base\cmds\input\src\com\android\commands\input\Input.java

关键代码实现解析:java层代码

Input类定义

public class Input {
//用于定义打印调试信息
private static final String TAG = "Input";
private static final String INVALID_ARGUMENTS = "Error: Invalid arguments for command: ";
//用map方式实现关键字和标识对应
private static final Map<String, Integer> SOURCES = new HashMap<String, Integer>() {{
put("keyboard", InputDevice.SOURCE_KEYBOARD);
put("dpad", InputDevice.SOURCE_DPAD);
put("gamepad", InputDevice.SOURCE_GAMEPAD);
put("touchscreen", InputDevice.SOURCE_TOUCHSCREEN);
put("mouse", InputDevice.SOURCE_MOUSE);
put("stylus", InputDevice.SOURCE_STYLUS);
put("trackball", InputDevice.SOURCE_TRACKBALL);
put("touchpad", InputDevice.SOURCE_TOUCHPAD);
put("touchnavigation", InputDevice.SOURCE_TOUCH_NAVIGATION);
put("joystick", InputDevice.SOURCE_JOYSTICK);
}};

sendKeyEvent 函数定义

//函数功能:发送键盘事件
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress) {
//获取从开机到现在的毫秒数
long now = SystemClock.uptimeMillis();
//注入键盘事件
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
if (longpress) {
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
inputSource));
}
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
}

sendSwipe 函数定义

//函数功能:实现滑屏操作
private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2, int duration) {
if (duration < 0) {
duration = 300;
}
//获取从开机到现在的毫秒数
long now = SystemClock.uptimeMillis();
//注入触摸事件
injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
//计算开始时间和结束时间
long startTime = now;
long endTime = startTime + duration;
while (now < endTime) {
long elapsedTime = now - startTime;
float alpha = (float) elapsedTime / duration;
injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
lerp(y1, y2, alpha), 1.0f);
now = SystemClock.uptimeMillis();
}
injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x2, y2, 0.0f);
}

injectKeyEvent 函数定义

//函数功能:注入事件的实现
private void injectKeyEvent(KeyEvent event) {
//打印调试信息
Log.i(TAG, "injectKeyEvent: " + event);
//获取inputManager的实例事件
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

injectMotionEvent 函数定义

函数功能:注入触摸事件
private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
final float DEFAULT_SIZE = 1.0f;
final int DEFAULT_META_STATE = 0;
final float DEFAULT_PRECISION_X = 1.0f;
final float DEFAULT_PRECISION_Y = 1.0f;
final int DEFAULT_DEVICE_ID = 0;
final int DEFAULT_EDGE_FLAGS = 0;
MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
DEFAULT_EDGE_FLAGS);
event.setSource(inputSource);
Log.i(TAG, "injectMotionEvent: " + event);
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

sendMove 函数定义

//函数功能:发送移动事件
private void sendMove(int inputSource, float dx, float dy) {
//获取时间
long now = SystemClock.uptimeMillis();
//调用注入触摸事件
injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, dx, dy, 0.0f);
}


内存几个关键函数

基础原理

android系统在应用程序框架层中提供了两个C++类MemoryHeapBase和MemoryBase来创建和管理匿名共享内存。 如果一个进程需要与其他进程共享一块完整的匿名共享内存,那么就可以通过使用MemoryHeapBase类类创建这块匿名共享内存。如果一个进程创建一块匿名共享内存后,只希望与其他进程共享其中的一部分,那么就可以通过MemoryBase类来创建这块匿名共享内存。

IMemory.h:定义内存相关类的接口,表示堆内存的类IMemoryHeap和BnMemoryHeap,表示一般内存的类IMemory和BnMemory。 MemoryHeapBase.h:定义类MemoryHeapBase,继承并实现BnMemoryHeap MemoryBase.h:定义类MemoryBase,继承并实现BnMemory。

android系统在应用程序框架层中提供了java类MemoryFile来创建和管理匿名共享内存。使用java类MemoryFile创建的匿名共享内存可以在不同的Android应用程序之间进行共享。

java代码解析

匿名共享内存java类MemoryFile在系统中的source\frameworks\base\core\java\android\os\MemoryFile.java文件中实现。

//匿名共享内存的构造函数,参数1表示创建匿名共享内存的名称,参数2表示创建匿名共享内存大小
public MemoryFile(String name int length) throws IOException {
mLength = length;
if (length >= 0) {
//通过调用jni的接口去打开匿名共享内存
mFD = native_open(name length);
} else {
throw new IOException("Invalid length: " + length);
}

if (length > 0) {
//进行映射
mAddress = native_mmap(mFD length PROT_READ | PROT_WRITE);
} else {
mAddress = 0;
}
}

C++关键函数解析

//MemoryHeapBase构造函数的实现
MemoryHeapBase::MemoryHeapBase(const char* device size_t size uint32_t flags)
: mFD(-1) mSize(0) mBase(MAP_FAILED) mFlags(flags)
mDevice(0) mNeedUnmap(false) mOffset(0)
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
open_flags |= O_SYNC;
//通过调用open打开匿名共享内存设备文件
int fd = open(device open_flags);
ALOGE_IF(fd<0 "error opening %s: %s" device strerror(errno));
if (fd >= 0) {
//指定的匿名共享内存大小按页对齐
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
//匿名共享内存映射到当前进程地址空间
if (mapfd(fd size) == NO_ERROR) {
mDevice = device;
}
}
}
//MemoryHeapBase构造函数
MemoryHeapBase::MemoryHeapBase(size_t size uint32_t flags char const * name)
: mFD(-1) mSize(0) mBase(MAP_FAILED) mFlags(flags)
mDevice(0) mNeedUnmap(false) mOffset(0)
{
//获得系统中页大小的内存
const size_t pagesize = getpagesize();
//内存页对齐
size = ((size + pagesize-1) & ~(pagesize-1));
//创建一块匿名共享内存
int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name size);
ALOGE_IF(fd<0 "error creating ashmem region: %s" strerror(errno));
if (fd >= 0) {
//创建的匿名共享内存映射到当前进程地址空间中
if (mapfd(fd size) == NO_ERROR) {
if (flags & READ_ONLY) {//如果地址映射成功,修改匿名共享内存的访问属性
ashmem_set_prot_region(fd PROT_READ);
}
}
}
}

初探android系统中input的java层实现

基础知识

当我们在分析android的键盘记录的时候就不得不和input进行打交道,那么input在系统中是怎么进行实现的? Android手机中默认携带input子系统,并且开在机就会产生默认的mouse和keyboard事件,这样使得用户开机就可以触屏点击和使用按键。 android中键盘实现的系统源码位置\source\frameworks\base\cmds\input\src\com\android\commands\input\Input.java

关键代码实现解析:java层代码

Input类定义

public class Input {
//用于定义打印调试信息
private static final String TAG = "Input";
private static final String INVALID_ARGUMENTS = "Error: Invalid arguments for command: ";
//用map方式实现关键字和标识对应
private static final Map<String, Integer> SOURCES = new HashMap<String, Integer>() {{
put("keyboard", InputDevice.SOURCE_KEYBOARD);
put("dpad", InputDevice.SOURCE_DPAD);
put("gamepad", InputDevice.SOURCE_GAMEPAD);
put("touchscreen", InputDevice.SOURCE_TOUCHSCREEN);
put("mouse", InputDevice.SOURCE_MOUSE);
put("stylus", InputDevice.SOURCE_STYLUS);
put("trackball", InputDevice.SOURCE_TRACKBALL);
put("touchpad", InputDevice.SOURCE_TOUCHPAD);
put("touchnavigation", InputDevice.SOURCE_TOUCH_NAVIGATION);
put("joystick", InputDevice.SOURCE_JOYSTICK);
}};

sendKeyEvent 函数定义

//函数功能:发送键盘事件
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress) {
//获取从开机到现在的毫秒数
long now = SystemClock.uptimeMillis();
//注入键盘事件
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
if (longpress) {
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
inputSource));
}
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
}

sendSwipe 函数定义

//函数功能:实现滑屏操作
private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2, int duration) {
if (duration < 0) {
duration = 300;
}
//获取从开机到现在的毫秒数
long now = SystemClock.uptimeMillis();
//注入触摸事件
injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
//计算开始时间和结束时间
long startTime = now;
long endTime = startTime + duration;
while (now < endTime) {
long elapsedTime = now - startTime;
float alpha = (float) elapsedTime / duration;
injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
lerp(y1, y2, alpha), 1.0f);
now = SystemClock.uptimeMillis();
}
injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x2, y2, 0.0f);
}

injectKeyEvent 函数定义

//函数功能:注入事件的实现
private void injectKeyEvent(KeyEvent event) {
//打印调试信息
Log.i(TAG, "injectKeyEvent: " + event);
//获取inputManager的实例事件
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

injectMotionEvent 函数定义

函数功能:注入触摸事件
private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
final float DEFAULT_SIZE = 1.0f;
final int DEFAULT_META_STATE = 0;
final float DEFAULT_PRECISION_X = 1.0f;
final float DEFAULT_PRECISION_Y = 1.0f;
final int DEFAULT_DEVICE_ID = 0;
final int DEFAULT_EDGE_FLAGS = 0;
MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
DEFAULT_EDGE_FLAGS);
event.setSource(inputSource);
Log.i(TAG, "injectMotionEvent: " + event);
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

sendMove 函数定义

//函数功能:发送移动事件
private void sendMove(int inputSource, float dx, float dy) {
//获取时间
long now = SystemClock.uptimeMillis();
//调用注入触摸事件
injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, dx, dy, 0.0f);
}

初探android系统中input的java层实现

基础知识

当我们在分析android的键盘记录的时候就不得不和input进行打交道,那么input在系统中是怎么进行实现的? Android手机中默认携带input子系统,并且开在机就会产生默认的mouse和keyboard事件,这样使得用户开机就可以触屏点击和使用按键。 android中键盘实现的系统源码位置\source\frameworks\base\cmds\input\src\com\android\commands\input\Input.java

关键代码实现解析:java层代码

Input类定义

public class Input {
//用于定义打印调试信息
private static final String TAG = "Input";
private static final String INVALID_ARGUMENTS = "Error: Invalid arguments for command: ";
//用map方式实现关键字和标识对应
private static final Map<String, Integer> SOURCES = new HashMap<String, Integer>() {{
put("keyboard", InputDevice.SOURCE_KEYBOARD);
put("dpad", InputDevice.SOURCE_DPAD);
put("gamepad", InputDevice.SOURCE_GAMEPAD);
put("touchscreen", InputDevice.SOURCE_TOUCHSCREEN);
put("mouse", InputDevice.SOURCE_MOUSE);
put("stylus", InputDevice.SOURCE_STYLUS);
put("trackball", InputDevice.SOURCE_TRACKBALL);
put("touchpad", InputDevice.SOURCE_TOUCHPAD);
put("touchnavigation", InputDevice.SOURCE_TOUCH_NAVIGATION);
put("joystick", InputDevice.SOURCE_JOYSTICK);
}};

sendKeyEvent 函数定义

//函数功能:发送键盘事件
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress) {
//获取从开机到现在的毫秒数
long now = SystemClock.uptimeMillis();
//注入键盘事件
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
if (longpress) {
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
inputSource));
}
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
}

sendSwipe 函数定义

//函数功能:实现滑屏操作
private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2, int duration) {
if (duration < 0) {
duration = 300;
}
//获取从开机到现在的毫秒数
long now = SystemClock.uptimeMillis();
//注入触摸事件
injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
//计算开始时间和结束时间
long startTime = now;
long endTime = startTime + duration;
while (now < endTime) {
long elapsedTime = now - startTime;
float alpha = (float) elapsedTime / duration;
injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
lerp(y1, y2, alpha), 1.0f);
now = SystemClock.uptimeMillis();
}
injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x2, y2, 0.0f);
}

injectKeyEvent 函数定义

//函数功能:注入事件的实现
private void injectKeyEvent(KeyEvent event) {
//打印调试信息
Log.i(TAG, "injectKeyEvent: " + event);
//获取inputManager的实例事件
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

injectMotionEvent 函数定义

函数功能:注入触摸事件
private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
final float DEFAULT_SIZE = 1.0f;
final int DEFAULT_META_STATE = 0;
final float DEFAULT_PRECISION_X = 1.0f;
final float DEFAULT_PRECISION_Y = 1.0f;
final int DEFAULT_DEVICE_ID = 0;
final int DEFAULT_EDGE_FLAGS = 0;
MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
DEFAULT_EDGE_FLAGS);
event.setSource(inputSource);
Log.i(TAG, "injectMotionEvent: " + event);
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

sendMove 函数定义

//函数功能:发送移动事件
private void sendMove(int inputSource, float dx, float dy) {
//获取时间
long now = SystemClock.uptimeMillis();
//调用注入触摸事件
injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, dx, dy, 0.0f);
}


0 个评论

要回复文章请先登录注册