系统版本:Android 7.1
logcat中的crash信息:
F DEBUG : Revision: '0'
F DEBUG : ABI: 'arm'
F DEBUG : pid: 2750, tid: 3858, name: InputReader >>> system_server <<<
F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
F DEBUG : r0 00000000 r1 00000004 r2 00000001 r3 00000000
F DEBUG : r4 a4e6275c r5 a693ee00 r6 b2cb2e40 r7 b2cb2ec8
F DEBUG : r8 a4e62784 r9 b2cb2e54 sl c1ef0da5 fp b2c56820
F DEBUG : ip b1702ab4 sp a4e62748 lr b16e9b77 pc b37d1cfe cpsr 000f0030
F DEBUG :
F DEBUG : backtrace:
F DEBUG : #00 pc 0000bcfe /system/lib/libutils.so (_ZNK7android7RefBase9incStrongEPKv+3)
F DEBUG : #01 pc 00010b73 /system/lib/libandroid_servers.so (_ZN7android2spINS_12InputManagerEEaSEPS1_+18)
F DEBUG : #02 pc 000115d3 /system/lib/libandroid_servers.so (_ZN7android18NativeInputManager23obtainPointerControllerEi+110)
F DEBUG : #03 pc 0002d05f /system/lib/libinputflinger.so (_ZN7android17CursorInputMapper9configureExPKNS_24InputReaderConfigurationEj+94)
F DEBUG : #04 pc 00029ca5 /system/lib/libinputflinger.so (_ZN7android11InputDevice9configureExPKNS_24InputReaderConfigurationEj+260)
F DEBUG : #05 pc 000299b3 /system/lib/libinputflinger.so (_ZN7android11InputReader15addDeviceLockedExi+138)
F DEBUG : #06 pc 00029767 /system/lib/libinputflinger.so (_ZN7android11InputReader19processEventsLockedEPKNS_8RawEventEj+102)
F DEBUG : #07 pc 00029639 /system/lib/libinputflinger.so (_ZN7android11InputReader8loopOnceEv+180)
F DEBUG : #08 pc 0002b0cd /system/lib/libinputflinger.so (_ZN7android17InputReaderThread10threadLoopEv+8)
F DEBUG : #09 pc 0000e345 /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140)
F DEBUG : #10 pc 000664bd /system/lib/libandroid_runtime.so (_ZN7android14AndroidRuntime15javaThreadShellEPv+80)
F DEBUG : #11 pc 00046f63 /system/lib/libc.so (_ZL15__pthread_startPv+22)
F DEBUG : #12 pc 00019cfd /system/lib/libc.so (__start_thread+6)
根据这个crash信息,分析inputreader的调用结构:
核心逻辑均处于这个文件中:
frameworks/native/services/inputflinger/InputReader.cpp
从栈#08开始依次:
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
#07:
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector inputDevices;
{ // acquire lock
AutoMutex _l(mLock);
oldGeneration = mGeneration;
timeoutMillis = -1;
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
processEventsLocked(mEventBuffer, count);
}
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// Flush queued events out to the listener.
// This must happen outside of the lock because the listener could potentially call
// back into the InputReader's methods, such as getScanCodeState, or become blocked
// on another thread similarly waiting to acquire the InputReader lock thereby
// resulting in a deadlock. This situation is actually quite plausible because the
// listener is actually the input dispatcher, which calls into the window manager,
// which occasionally calls into the input reader.
mQueuedListener->flush();
}
#06:
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) {
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
#if DEBUG_RAW_EVENTS
ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
#05:
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex >= 0) {
ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
return;
}
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
device->configure(when, &mConfig, 0);
device->reset(when);
if (device->isIgnored()) {
ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
identifier.name.string());
} else {
ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
identifier.name.string(), device->getSources());
}
mDevices.add(deviceId, device);
bumpGenerationLocked();
if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
notifyExternalStylusPresenceChanged();
}
}
#04:
void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
mSources = 0;
if (!isIgnored()) {
if (!changes) { // first time only
mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
sp keyboardLayout =
mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
bumpGeneration();
}
}
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
if (mAlias != alias) {
mAlias = alias;
bumpGeneration();
}
}
}
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->configure(when, config, changes);
mSources |= mapper->getSources();
}
}
}
#03:
void CursorInputMapper::configure(nsecs_t when,
const InputReaderConfiguration* config, uint32_t changes) {
InputMapper::configure(when, config, changes);
if (!changes) { // first time only
mCursorScrollAccumulator.configure(getDevice());
// Configure basic parameters.
configureParameters();
// Configure device mode.
switch (mParameters.mode) {
case Parameters::MODE_POINTER:
mSource = AINPUT_SOURCE_MOUSE;
mXPrecision = 1.0f;
mYPrecision = 1.0f;
mXScale = 1.0f;
mYScale = 1.0f;
mPointerController = getPolicy()->obtainPointerController(getDeviceId());
break;
case Parameters::MODE_NAVIGATION:
mSource = AINPUT_SOURCE_TRACKBALL;
mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
break;
}
mVWheelScale = 1.0f;
mHWheelScale = 1.0f;
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
DisplayViewport v;
if (config->getDisplayInfo(false /*external*/, &v)) {
mOrientation = v.orientation;
} else {
mOrientation = DISPLAY_ORIENTATION_0;
}
} else {
mOrientation = DISPLAY_ORIENTATION_0;
}
bumpGeneration();
}
}
#02:
该栈在这个文件中:
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
sp NativeInputManager::obtainPointerController(int32_t /* deviceId */) {
AutoMutex _l(mLock);
sp controller = mLocked.pointerController.promote();
if (controller == NULL) {
ensureSpriteControllerLocked();
controller = new PointerController(this, mLooper, mLocked.spriteController);
mLocked.pointerController = controller;
DisplayViewport& v = mLocked.internalViewport;
controller->setDisplayViewport(
v.logicalRight - v.logicalLeft,
v.logicalBottom - v.logicalTop,
v.orientation);
updateInactivityTimeoutLocked(controller);
}
return controller;
}
#01栈使用addr2line分析:
注意使用addr2line分析时如果跟
out\target\product\product_name\symbols\system\lib\
这个路径里面的库是可以分析到具体的行的
$ addr2line -C -f -e system/lib/libandroid_servers.so 00010b73
android::sp::operator=(android::InputManager*)
??:?
#00:
$ addr2line -C -f -e system/lib/libutils.so 0000bcfe
android::RefBase::incStrong(void const*) const
??:?
引用代码:
template
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
__sync_fetch_and_add(&mCount, 1);
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (__sync_fetch_and_sub(&mCount, 1) == 1) {
delete static_cast(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount;
}
typedef LightRefBase basetype;
protected:
inline ~LightRefBase() { }
private:
friend class ReferenceMover;
inline static void moveReferences(void* d, void const* s, size_t n,
const ReferenceConverterBase& caster) { }
private:
mutable volatile int32_t mCount;
};
根据addr2line分析到的栈信息,最后确定问题出在obtainPointerController这个函数的
new PointerController(this, mLooper, mLocked.spriteController);
的位置,进一步
PointerController::PointerController(const sp& policy,
const sp& looper, const sp& spriteController) :
mPolicy(policy), mLooper(looper), mSpriteController(spriteController) {
mHandler = new WeakMessageHandler(this);
mCallback = new WeakLooperCallback(this);
if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
Looper::EVENT_INPUT, mCallback, nullptr);
} else {
ALOGE("Failed to initialize DisplayEventReceiver.");
}
AutoMutex _l(mLock);
mLocked.animationPending = false;
mLocked.displayWidth = -1;
mLocked.displayHeight = -1;
mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
mLocked.presentation = PRESENTATION_POINTER;
mLocked.presentationChanged = false;
mLocked.inactivityTimeout = INACTIVITY_TIMEOUT_NORMAL;
mLocked.pointerFadeDirection = 0;
mLocked.pointerX = 0;
mLocked.pointerY = 0;
mLocked.pointerAlpha = 0.0f; // pointer is initially faded
mLocked.pointerSprite = mSpriteController->createSprite();
mLocked.pointerIconChanged = false;
mLocked.requestedPointerType= mPolicy->getDefaultPointerIconId();
mLocked.animationFrameIndex = 0;
mLocked.lastFrameUpdatedTime = 0;
mLocked.buttonState = 0;
mPolicy->loadPointerIcon(&mLocked.pointerIcon);
loadResources();
if (mLocked.pointerIcon.isValid()) {
mLocked.pointerIconChanged = true;
updatePointerLocked();
}
}
该构造函数给mSpriteController这个引用赋初值时发生错误,此次只是记录分析栈信息的过程,不分析问题的原因。