【问题标题】:How to debug Android native code on a real device如何在真机上调试 Android 原生代码
【发布时间】:2010-09-10 12:53:03
【问题描述】:

我在 Android 中的媒体后端(主要是 Stagefrightplayer)遇到了一些问题,我想了解它为什么会引发错误。这些错误通常是特定于设备的,因此在模拟器上进行调试是不够的。

例子:

I/AwesomePlayer(  147): mConnectingDataSource->connect() returned -1004
V/MediaPlayerService(  147): [332] notify (0x272830, 100, 1, -1004)
E/MediaPlayer(24881): error (1, -1004)
E/MediaPlayer(24881): Error (1,-1004)
W/PlayerListener(24881): Received error: what = 1, extra = -1004

示例 2:

E/MediaPlayer(  941): error (1, -2147483648)

我还让玩家彻底崩溃并吐出一个 traces.txt。

有没有办法调试正在发生的事情,就像我调试 Java 代码一样?谢谢。

【问题讨论】:

  • 来自 C++ 用户态代码,与内核无关。请参阅 git://android.git.kernel.org/platform/frameworks/base.git/media/jni/android_media_MediaPlayer.cpp 和类似内容。
  • 谢谢。但仍然:是否可以调试这个,例如使用远程 GDB 会话?

标签: android c++ debugging android-source android-music-player


【解决方案1】:

您可以做很多事情。

如果您认为错误出在框架本身,请获取源并挖掘http://source.android.com/

否则,最好的 Android 调试器是 DDMS,它可以与模拟器一起使用,也可以与真实设备一起使用。 http://developer.android.com/guide/developing/tools/ddms.html

通过 adb (http://developer.android.com/guide/developing/tools/adb.html) 进行的转储状态还可以为您提供设备上正在发生的事情的完整快照,但您很难在错误发生时获得确切的时间点。

尽管这仍然不会像 GDB 那样为您提供源代码级别的调试(或者我不确定您通常调试 Java 代码的方式是什么意思)。

如果您真的将内核作为内核,那么您不再是真正在 Android 中,而是在 Linux 世界中更多,但我认为您不需要走那么远。

如果您在使用特定的 Android 应用程序时遇到问题(该应用程序不是开源的,不是您自己的),恐怕您运气不好。

对于 MediaPlayer 部分,Eclair 的文件位于 https://android.googlesource.com/platform/frameworks/base/+/eclair-release/media/java/android/media/MediaPlayer.java,但找不到你放在那里的具体错误信息。

【讨论】:

    【解决方案2】:

    并不是说这直接回答了您的问题,但这些信息可能对您有用。

    因此,根据您的 -1004 错误代码,您在尝试流式传输时遇到了 I/O 错误。至于 -2147483648 错误代码,对您帮助不大。您将不得不查看媒体播放器的所有日志输出,以了解为什么您会得到该代码,因为它没有被定义。我已经从解码器对视频编码的阻塞中看到了这一点。

    借自:/frameworks/base/include/media/stagefright/MediaErrors.h

    MEDIA_ERROR_BASE = -1000,

    ERROR_ALREADY_CONNECTED = MEDIA_ERROR_BASE,
    ERROR_NOT_CONNECTED     = MEDIA_ERROR_BASE - 1,
    ERROR_UNKNOWN_HOST      = MEDIA_ERROR_BASE - 2,
    ERROR_CANNOT_CONNECT    = MEDIA_ERROR_BASE - 3,
    ERROR_IO                = MEDIA_ERROR_BASE - 4,
    ERROR_CONNECTION_LOST   = MEDIA_ERROR_BASE - 5,
    ERROR_MALFORMED         = MEDIA_ERROR_BASE - 7,
    ERROR_OUT_OF_RANGE      = MEDIA_ERROR_BASE - 8,
    ERROR_BUFFER_TOO_SMALL  = MEDIA_ERROR_BASE - 9,
    ERROR_UNSUPPORTED       = MEDIA_ERROR_BASE - 10,
    ERROR_END_OF_STREAM     = MEDIA_ERROR_BASE - 11,
    

    【讨论】:

      【解决方案3】:

      可以使用远程调试(目标上的 gdbserver + 主机上的 gdb) 逐步完成在真实硬件上运行的 C/C++ 用户态代码。 它提供了所有“常规”选项,例如断点、回溯、查看/设置变量、跟踪点。

      详情请看Android构建系统的'gdbclient'shell函数, 预构建 eabi gdb 和可能的 DDD 或其他前端。 Eclipse应该没问题。

      【讨论】:

        【解决方案4】:

        即使您无法在内核级别进行调试,将神秘的错误编号追踪到正确的头文件(和描述性定义)仍然很有用。

        -1004 表示ERROR_IO,可以在MediaErrors.h中找到:
        https://android.googlesource.com/platform/frameworks/base/+/eclair-release/include/media/stagefright/MediaErrors.h#32

        -2147483648 可能是UNKNOWN_ERROR,可以在Errors.h中找到:
        https://android.googlesource.com/platform/frameworks/base/+/eclair-release/include/utils/Errors.h#49

        正如您在Errors.h 中看到的,它包括errno.h,其中包括内核级错误代码/kernel/include/asm-generic/errno.h。

        例如,如果 connect() 返回错误代码 -110,您将知道这是因为超时,因为它被定义为:

        #define ETIMEDOUT       110     /* Connection timed out */
        

        【讨论】:

          【解决方案5】:

          虽然 Android 确实支持远程 GDB 会话,但这可能不适用于内核端代码。您最好的选择是使用可用于执行停止模式调试的JTAG 连接。由于停止模式调试会有效地停止 CPU 的执行,您可能会发现这会导致看门狗定时器出现问题。

          或者,将跟踪插入内核代码可能更容易。

          【讨论】:

          • 谢谢,但是...在我的 Java 代码中插入跟踪将如何帮助调试内核代码?和我在一起,我很无知:p
          【解决方案6】:

          您可以通过几种不同的方式做到这一点。首先你需要找出你要调试的服务是在Java框架服务中,比如system_server,还是在纯原生应用中,比如surfaceflinger。

          如果是纯原生服务,请查看Debugging android platform native applications文章。

          如果服务是托管在system_server进程中的Java代码,请查看Debugging Android Java framework services文章。

          如果你要调试的代码是Java服务通过JNI隐式加载的原生库,请查看Debugging Android framework native libraries文章。

          【讨论】:

            【解决方案7】:

            除非您想在汇编级别进行调试,否则您可能必须自己构建一个启用调试 + 调试符号的内核。我认为小型设备中的大多数内核默认情况下会避免这样做,因为它会使内核变得更大。此时您可以启用内核调试器...

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-10-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-08-11
              • 2015-08-23
              • 1970-01-01
              • 2012-05-31
              相关资源
              最近更新 更多