[Android][FWK]一個system_server 重啟的案例分析
阿新 • • 發佈:2018-12-25
android 8.1 上,報了一個手機重啟。
檢視android event log, 查詢關鍵字 am_crash, 發現問題出現的時間點上有個 NullPointerException
16:16:12.278 1000 3277 3456 I am_crash: [3277,0,system_server,-1,java.lang.NullPointerException,Attempt to invoke virtual method 'void com.android.bluetooth.gatt.AdvertiseManager.stopAdvertisingSets()' on a null object reference,Parcel.java,1949]
main log 上可以看到, system server 已經在垂死掙扎中。
16:16:12.446 10037 32271 32271 E AndroidRuntime: DeadSystemException: The system died; earlier logs will point to the root cause
以上列印log的程式碼位置如下:
frameworks/base/core/java/android/util/Log.java /** * Helper function for long messages. Uses the LineBreakBufferedWriter to break * up long messages and stacktraces along newlines, but tries to write in large * chunks. This is to avoid truncation. * @hide */ public static int printlns(int bufID, int priority, String tag, String msg, Throwable tr) { ImmediateLogWriter logWriter = new ImmediateLogWriter(bufID, priority, tag); // Acceptable buffer size. Get the native buffer size, subtract two zero terminators, // and the length of the tag. // Note: we implicitly accept possible truncation for Modified-UTF8 differences. It // is too expensive to compute that ahead of time. int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD // Base. - 2 // Two terminators. - (tag != null ? tag.length() : 0) // Tag length. - 32; // Some slack. // At least assume you can print *some* characters (tag is not too large). bufferSize = Math.max(bufferSize, 100); LineBreakBufferedWriter lbbw = new LineBreakBufferedWriter(logWriter, bufferSize); lbbw.println(msg); if (tr != null) { // This is to reduce the amount of log spew that apps do in the non-error // condition of the network being unavailable. Throwable t = tr; while (t != null) { if (t instanceof UnknownHostException) { break; } if (t instanceof DeadSystemException) { lbbw.println("DeadSystemException: The system died; " + "earlier logs will point to the root cause"); break; } t = t.getCause(); } if (t == null) { tr.printStackTrace(lbbw); } } lbbw.flush(); return logWriter.getWritten(); }
以下是發生問題時的BackTrace,問題就是一個 NullPointerException,跟 BT 有關。
16:16:12.278 1000 3277 3456 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: android.io 16:16:12.278 1000 3277 3456 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.android.bluetooth.gatt.AdvertiseManager.stopAdvertisingSets()' on a null object reference 16:16:12.278 1000 3277 3456 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1949) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1889) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at android.bluetooth.IBluetoothGatt$Stub$Proxy.unregAll(IBluetoothGatt.java:1855) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at com.android.server.BluetoothManagerService.sendBrEdrDownCallback(BluetoothManagerService.java:794) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at com.android.server.BluetoothManagerService.bluetoothStateChangeHandler(BluetoothManagerService.java:2076) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at com.android.server.BluetoothManagerService.-wrap7(Unknown Source:0) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at com.android.server.BluetoothManagerService$BluetoothHandler.handleMessage(BluetoothManagerService.java:1697) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:105) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at android.os.HandlerThread.run(HandlerThread.java:65) 16:16:12.278 1000 3277 3456 E AndroidRuntime: at com.android.server.ServiceThread.run(ServiceThread.java:46) 16:16:12.280 1000 3277 3277 I chatty : uid=1000 system_server expire 1 line
對應code:
frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
769 /**
770 * Inform BluetoothAdapter instances that BREDR part is down
771 * and turn off all service and stack if no LE app needs it
772 */
773 private void sendBrEdrDownCallback() {
774 if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks");
775
776 if (mBluetooth == null) {
777 Slog.w(TAG, "Bluetooth handle is null");
778 return;
779 }
780
781 if (isBleAppPresent()) {
782 // Need to stay at BLE ON. Disconnect all Gatt connections
783 try {
784 mBluetoothGatt.unregAll();
785 } catch (RemoteException e) {
786 Slog.e(TAG, "Unable to disconnect all apps.", e);
787 }
788 } else {
789 try {
790 mBluetoothLock.readLock().lock();
791 if (mBluetooth != null) mBluetooth.onBrEdrDown();
792 } catch (RemoteException e) {
793 Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
794 } finally {
795 mBluetoothLock.readLock().unlock();
796 }
797 }
798
799 }
BluetoothManagerService.java 794行已經在走異常流程。
省略分析...
屬於android 原生問題,最後發現已經有patch,傳送門
https://android-review.googlesource.com/
end.