G-sensor因數據交互問題導致手機crash
問題現象:
問題原因:
通過工作抓取到的kernel層的log(截選重要部分)如下顯示:
<6>[ 7040.264871] SysRq: Show backtrace of all active CPUs
<6>[ 7040.264925]Backtrace for cpu 0 (current):
<6>[ 7040.264946] CPU: 0PID: 4667 Comm: watchdog Tainted: P W O3.10.49-g8347c3d-00015-g4c1aa2f #1
<6>[ 7040.265001][<c00132f8>] (unwind_backtrace+0x0/0xe0) from [<c0011084>](show_stack+0x10/0x14)
<6>[ 7040.265023][<c0011084>] (show_stack+0x10/0x14) from [<c00125c8>](smp_send_all_cpu_backtrace+0x50/0xcc)
<6>[ 7040.265045][<c00125c8>] (smp_send_all_cpu_backtrace+0x50/0xcc) from[<c02fbfec>] (__handle_sysrq+0x9c/0x140)
<6>[ 7040.265066][<c02fbfec>] (__handle_sysrq+0x9c/0x140) from [<c02fc3f4>](write_sysrq_trigger+0x38/0x48)
<6>[ 7040.265090][<c02fc3f4>] (write_sysrq_trigger+0x38/0x48) from [<c013c124>](proc_reg_write+0x6c/0x80)
<6>[ 7040.265113][<c013c124>] (proc_reg_write+0x6c/0x80) from [<c00f66fc>](vfs_write+0xd0/0x180)
<6>[ 7040.265134][<c00f66fc>] (vfs_write+0xd0/0x180) from [<c00f6bb8>](SyS_write+0x38/0x68)
<6>[ 7040.265152][<c00f6bb8>] (SyS_write+0x38/0x68) from [<c000d700>](ret_fast_syscall+0x0/0x30)
<6>[ 7040.265161]
<6>[ 7040.265161]sending IPI to all other CPUs:
<4>[ 7040.265180] IPIbacktrace for cpu 1
<6>[ 7040.265192]
<6>[ 7040.265205] CPU: 1PID: 831 Comm: SensorService Tainted: P W O3.10.49-g8347c3d-00015-g4c1aa2f #1
<6>[ 7040.265215] task:ebce7380 ti: ebf3a000 task.ti: ebf3a000
<6>[ 7040.265231] PC isat sub_preempt_count+0x14/0xd4
這段log提供了,從kernellog的時間點看7040打印出堆棧異常信息,換算對應於logcat的19:11:27秒打印出了watchdog 和sensor service的 堆棧,而kernel沒有掛掉,僅僅打印出異常堆棧信息,logcat 在19:11:20 秒的時候 watchdog 已經被PowerManagerService block住的信息,而log被保存在了“ Wrote stack traces to'/data/anr/traces.txt'”下 。隨即打印主動watchdog 的堆棧(即kernel log的 7040s打印的堆棧信息)“01-01 19:11:27.258 767 4667 I Watchdog_N: dumpKernelStac。而且sensorservice的堆棧信息。所以應該是PowerManagerService 被block主了,要看下/data/anr/traces.txt'的信息。Logcat 裏面多次 “watchdog: Blocked in handler onmain thread (main), Blocked in handler on PowerManagerService(PowerManagerService)”而引發kernel 打印堆棧。
同時上層也有抓到具體重啓的原因是Watchdog: *** WATCHDOGKILLING SYSTEM PROCESS: Blocked in handler on main thread (main), Blocked inhandler on PowerManagerService (PowerManagerService)
追溯“Blocked in handler on main thread(main), Blocked in handler on PowerManagerService (PowerManagerService)”來源於下段函數任務沒完成或者time out導致。
// something is overdue!
blockedCheckers =getBlockedCheckersLocked();
subject =describeCheckersLocked(blockedCheckers);
allowRestart = mAllowRestart;
if (hc.isOverdueLocked()) {
checkers.add(hc);
}
public booleanisOverdueLocked() {
return (!mCompleted) &&(SystemClock.uptimeMillis() > mStartTime + mWaitMax);
}
默認的超時時間是6s,也可以調用函數時傳入,現在看來應該是傳入的數據,而HAL層的數據都是由輪詢的方式由底層傳入。
static final longDEFAULT_TIMEOUT = DB ? 10*1000 : 60*1000;
static final boolean DB =false;
於是鎖定在了PhoneWindowManager.goingToSleep()這裏和PhoneWindowManager.screenTurnedOff()持有同一個同步鎖導致。screenTurnedOff 在等待 goingToSleep 釋放鎖,於是導致系統卡在android.hardware.SystemSensorManager$BaseEventQueue.nativeDisableSensor。最後被watchdog 殺掉。
詳細邏輯原因:
具體情況是在qcom的HAL層裏的sensors.cpp下的這個函數
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
在以下的時候,先會拿到鎖,然後有查到函數會在sm.readEvents()裏面耗費很大時間以致無法解鎖,才導致被kill掉。繼續往下調查
178 Mutex::Autolock _l(mLock);
179 int nb = sm.readEvents(slist[i].handle, data, count);
180 if (nb < 0) {
181 ALOGE("readEvents failed.(%d)", errno);
182 return nb;
進ReadEvent()裏面會因爲下面這段導致不斷被循環,而這段循環的要求mEnable =1是ok的,而numEventReceived只有在上面一個循環裏面纔會++,
291 if (numEventReceived == 0 && mEnabled == 1) {
292 n = mInputReader.fill(data_fd);
293 if (n)
294 goto again;
295 }
在操作numEventReceived變量的函數循環,發現在report事件的時候有如下循環:
257 case SYN_REPORT:
258 {
259 if(mUseAbsTimeStamp != true) {
260 mPendingEvent.timestamp = timevalToNano(event->time);
261 }
262 if (mEnabled) {
263 if(mPendingEvent.timestamp >= mEnabledTime) {
264/* [BUFFIX]-Mod- Begin by TCTNB.XQJ,PR-915938, 2015/2/11, from AKM fae modify,for cts test */
265 raw = mPendingEvent;
266 if (algo != NULL)
267 {
268 if (algo->methods->convert(&raw, NULL, NULL)) {
269 ALOGE("Calibration failed.");
270 }
271 }
272/* [BUFFIX]-Mod- End by TCTNB.XQJ*/
273 *data++ = mPendingEvent;
274 numEventReceived++;
275 }
如紅色部分,這裏的函數就無法進入,但在report的case裏面,有SYN_TIME_NSEC下有如下操作
245 case SYN_TIME_SEC:
246 {
247 mUseAbsTimeStamp = true;
248 report_time = event->value*1000000000LL;
249 }
250 break;
251 case SYN_TIME_NSEC:
252 {
253 mUseAbsTimeStamp = true;
254 mPendingEvent.timestamp = report_time+event->value;
這樣才能理順這個流程。而如果流程中間卡主,在長事件卡在循環裏面,如果7-8秒,會導致無法喚醒,更長時間會導致system crash掉。
Best regards,