androidandroid-monkey

Android monkey triggers NullPointerException inside Spinner


I'm trying to find some hard-to-reproduce problems in my code. I used the monkey tool. But here, it appears that the problem is inside the Android spinner. Is that an API/framework problem? I tried it again with the same results.

// CRASH: com.panguso.mobile.client (pid 11171)
// Short Msg: java.lang.NullPointerException
// Long Msg: java.lang.NullPointerException
// Build Label: google/soju/crespo:4.1.1/JRO03E/403059:user/release-keys
// Build Changelist: 403059
// Build Time: 1342214487000
// java.lang.NullPointerException
//  at android.widget.Spinner$DialogPopup.dismiss(Spinner.java:828)
//  at android.widget.Spinner$DialogPopup.onClick(Spinner.java:862)
//  at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:924)
//  at android.widget.AdapterView.performItemClick(AdapterView.java:298)
//  at android.widget.AbsListView.performItemClick(AbsListView.java:1086)
//  at android.widget.AbsListView.onKeyUp(AbsListView.java:2996)
//  at android.widget.ListView.commonKey(ListView.java:2196)
//  at android.widget.ListView.onKeyUp(ListView.java:2051)
//  at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
//  at android.view.View.dispatchKeyEvent(View.java:7086)
//  at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1354)
//  at android.widget.ListView.dispatchKeyEvent(ListView.java:2026)
//  at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
//  at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
//  at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
//  at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
//  at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
//  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1892)
//  at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1369)
//  at android.app.Dialog.dispatchKeyEvent(Dialog.java:702)
//  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1819)
//  at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3575)
//  at android.view.ViewRootImpl.deliverKeyEvent(ViewRootImpl.java:3531)
//  at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3113)
//  at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4153)
//  at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4132)
//  at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4224)
//  at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
//  at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
//  at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:163)
//  at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4203)
//  at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4243)
//  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
//  at android.view.Choreographer.doCallbacks(Choreographer.java:555)
//  at android.view.Choreographer.doFrame(Choreographer.java:523)
//  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
//  at android.os.Handler.handleCallback(Handler.java:615)
//  at android.os.Handler.dispatchMessage(Handler.java:92)
//  at android.os.Looper.loop(Looper.java:137)
//  at android.app.ActivityThread.main(ActivityThread.java:4745)
//  at java.lang.reflect.Method.invokeNative(Native Method)
//  at java.lang.reflect.Method.invoke(Method.java:511)
//  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
//  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
//  at dalvik.system.NativeStart.main(Native Method)
// 
** Monkey aborted due to error.
Events injected: 1801
:Sending rotation degree=0, persist=false
:Dropped: keys=5 pointers=0 trackballs=0 flips=0 rotations=0
## Network stats: elapsed time=17738ms (0ms mobile, 17738ms wifi, 0ms not connected)
** System appears to have crashed at event 1801 of 10000 using seed 0

Solution

  • The stacktrace you posted does not mention any class inside your code, meaning that this problem is at least not directly caused by you.

    Little analysis of the stacktrace, from bottom to top since that is the path the code takes (sourcecode for that stacktrace can be found using http://www.grepcode.com/?st=true):

    ...
    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
    

    Monkey issues a key event like you could produce with a soft / hard keyboard.

    The key event is then forwarded to the DecorView which contains your app content and the ActionBar. The DecorView forwards the event to a Dialog.

    ...
    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1819)
    at android.app.Dialog.dispatchKeyEvent(Dialog.java:702)
    

    From here is passed through the view hierarchy until it reaches a ListView

    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1358)
    at android.widget.ListView.dispatchKeyEvent(ListView.java:2026)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1354)
    at android.view.View.dispatchKeyEvent(View.java:7086)
    at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
    at android.widget.ListView.onKeyUp(ListView.java:2051)
    at android.widget.ListView.commonKey(ListView.java:2196)
    

    The ListView forwards the key to it's content which seems to be a Spinner and the click seems to trigger a .dismiss() to the Dialog (the dropdown list) this Spinner shows.

    at android.widget.AbsListView.onKeyUp(AbsListView.java:2996)
    at android.widget.AbsListView.performItemClick(AbsListView.java:1086)
    at android.widget.AdapterView.performItemClick(AdapterView.java:298)
    at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:924)
    at android.widget.Spinner$DialogPopup.onClick(Spinner.java:862)
    at android.widget.Spinner$DialogPopup.dismiss(Spinner.java:828)
    

    A Spinner and a stacktrace that does not mention your code could be part of the system UI i.e. the ActionBar.

    example
    (source: android.com)

    As you can see in the image (taken from here) there is a Spinner (showing the date) and a Dialog with a ListView (Day, Week, ...) below. Clicking one of the items or the spinner itself or somewhere outside would close the dialog.

    The NullPointerException happens in the following piece of code

    public void dismiss() {
        mPopup.dismiss();  // Spinner.java:828
        mPopup = null;
    }
    

    mPopup is obviously null. That will only happen if the popup was not shown before since it is set in

    public void show() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        if (mPrompt != null) {
            builder.setTitle(mPrompt);
        }
        mPopup = builder.setSingleChoiceItems(mListAdapter,
                getSelectedItemPosition(), this).show();
    }
    

    Is that an API/framework problem?

    I don't know but monkey can click things that are not necessarily reachable for regular users and it can click at times / rates that users will not be able to click. So this problem might be caused by clicking in a way that the API programmers did not foresee / test. Is possible especially since the stacktrace is purely framework and they check for null of mPopup in other places but not here.

    But besides that possibility it could also be related to your code. Maybe you added a Spinner somewhere in your layout (or the ActionBar) and do something with it that it was not intended to do. And I guess if you don't override any of the default behavior (esp. key event handling) the framework does not need to jump into your code and would produce exactly the same stacktrace.