AndroidFramework⾳频⼦系统(09)⽿麦插拔之流程分析该系列⽂章总纲链接:
本章关键点总结 & 说明:
本章节主要关注 以上思维导图左上 ⽿麦插拔 部分 即可。本章节主要分析⽿麦插拔流程,⽿机发⽣插拔后,android是如何在framework层处理的。同时本章节 涉及输⼊⼦系统会写的相对简单⼀些,详细可参考输⼊⼦系统的专题链接:
对于⽿麦的插拔,Android有两种模式,可以使⽤input⼦系统,也可以使⽤state dev(uevent)上报拔插操作。说明如下:
输⼊⼦系统:可以上报按键事件也可以上报开关事件(EV_SW),事件类型包括headset、headPhone、li
neOut。对于输⼊设备都需要指定能产⽣同步类事件EV_SYN. 对于按键事件,输⼊⼦系统还需要设置按键值的范围,但是对于开关类事件不需要设置。
switch class⼦系统:通过uevent向⽤户空间发送数据,Android中有个线程专门监听这类事件。使⽤switch dev⼦系统时,名字必须要设置为"h2w",Android系统监听/sys/class/switch/h2w这个虚拟设备。
具体使⽤哪种操作 取决于config_useDevInputEventForAudioJack 这个配置值,定义在l⽂件中,如下:
...
<!-- When true use the linux /dev/input/event subsystem to detect the switch changes
on the headphone/microphone jack. When false use the older uevent framework. -->
<bool name="config_useDevInputEventForAudioJack">false</bool>
...
该值为true时使⽤input⼦系统, 为false时使⽤uevent机制,该值在下述⽂件中定义, 后⼀个⽂件会覆盖前⼀个⽂件:
frameworks/base/core/res/res/l
device/"平台⼚商"/frameworks/base/core/res/res/l
接下来我么对两种模式进⾏分析,两种模式前半段不⼀致,后半段处理是⼀致的。主要就是分析这样⼀个流程:底层的⽿麦插拔是如何把事件⼀层层上报,最终通过ActivityManagerService将消息⼴播出去的过程。
1 前半段分析(两种模式到WiredAccessoryManager中updateLocked⽅法)
1.1 使⽤input⼦系统的流程(从input⼦系统到WiredAccessoryManager中updateLocked⽅法)
input⼦系统通过InputReader开始读取事件并处理。代码如下:
void InputReader::loopOnce() {
//...
/
/获取事件
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
//...
//处理事件
processEventsLocked(mEventBuffer, count);
//...
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
mQueuedListener->flush();
}
InputReader线程 通过EventHub中的getEvent⽅法 从驱动中获取事件后使⽤processEventsLocked开始处理,processEventsLocked实现如下:
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
//...
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
//...
}
count -= batchSize;
rawEvent += batchSize;
}
}
这⾥继续分析processEventsForDeviceLocked的实现,代码如下:
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
//...
InputDevice* device = mDevices.valueAt(deviceIndex);
//...
device->process(rawEvents, count);
}
继续分析InputDevice的process⽅法,代码如下:
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
size_t numMappers = mMappers.size();
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
if (mDropUntilNextSync) {
//...
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
/
/...
} else {
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
}
}
}
对于swicth事件来说,这⾥的map是SwitchInputMapper,它的process函数实现如下:
void SwitchInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_SW:
processSwitch(rawEvent->code, rawEvent->value);
break;
case EV_SYN:
if (rawEvent->code == SYN_REPORT) {
sync(rawEvent->when);
}
}
}
继续分析processSwitch,代码如下:
void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
if (switchCode >= 0 && switchCode < 32) {
if (switchValue) {notify for mi band
mSwitchValues |= 1 << switchCode;
} else {
mSwitchValues &= ~(1 << switchCode);
}
mUpdatedSwitchMask |= 1 << switchCode;
}
}
这⾥主要是通过mSwitchValues的值进⾏状态存储,我们继续分析sync的实现,代码如下:
void SwitchInputMapper::sync(nsecs_t when) {
if (mUpdatedSwitchMask) {
uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
NotifySwitchArgs args(when, 0, updatedSwitchValues, mUpdatedSwitchMask);
getListener()->notifySwitch(&args);
mUpdatedSwitchMask = 0;
}
}
这⾥的getListener()->notifySwitch(&args)实际上就是InputDispatcher的notifySwitch⽅法,代码实现如下:
void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
uint32_t policyFlags = args->policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
mPolicy->notifySwitch(args->eventTime,
args->switchValues, args->switchMask, policyFlags);
}
这⾥的mPolicy->notifySwitch 经过JNI的回调最终会调⽤到Java层的InputManagerService中的notifySwitch⽅法,代码如下:
// Native callback.
private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
if ((switchMask & SW_LID_BIT) != 0) {
final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
}
if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
}
//mUseDevInputEventForAudioJack在这⾥被配置成true,会⾛该分⽀
if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
switchMask);
}
}
这⾥继续分析notifyWiredAccessoryChanged,代码实现如下:
@Override
public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
synchronized (mLock) {
int headset;
mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;
switch (mSwitchValues &
(SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) { case 0:
headset = 0;
break;
case SW_HEADPHONE_INSERT_BIT:
headset = BIT_HEADSET_NO_MIC;
break;
case SW_LINEOUT_INSERT_BIT:
headset = BIT_LINEOUT;
break;
case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:
headset = BIT_HEADSET;
break;
case SW_MICROPHONE_INSERT_BIT:
headset = BIT_HEADSET;
break;
default:
headset = 0;
break;
}
updateLocked(NAME_H2W,
(mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);
}
}
这⾥调⽤到了updateLocked⽅法了。接下来的分析我们在后半段分析时继续。
1.2 使⽤uevent机制的流程(从uevent到WiredAccessoryManager中updateLocked⽅法)
在systemserver中的startOtherServices中关于WiredAccessoryManager的创建和使⽤如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论