1. 程式人生 > >[Android][FWK]一個system_server 重啟的案例分析

[Android][FWK]一個system_server 重啟的案例分析

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.