2017-09-25 297 views
7

我是一個Android應用程序開發人員,我在用下面的崩潰報告的麻煩(我得到了那些每天5/6):Android的怪異AudioTrack崩潰

native: pc 00000000000418e0 /system/lib/libc.so (tgkill+12) 
    native: pc 0000000000040d59 /system/lib/libc.so (pthread_kill+32) 
    native: pc 000000000001c7eb /system/lib/libc.so (raise+10) 
    native: pc 000000000001999d /system/lib/libc.so (__libc_android_abort+34) 
    native: pc 0000000000017550 /system/lib/libc.so (abort+4) 
    native: pc 0000000000008d53 /system/lib/libcutils.so (__android_log_assert+86) 
    native: pc 000000000006e2c3 /system/lib/libmedia.so (_ZN7android11ClientProxy13releaseBufferEPNS_5Proxy6BufferE+94) 
    native: pc 000000000006c11d /system/lib/libmedia.so (_ZN7android10AudioTrack13releaseBufferEPKNS0_6BufferE+112) 
    native: pc 000000000006c987 /system/lib/libmedia.so (_ZN7android10AudioTrack18processAudioBufferEv+1350) 
    native: pc 000000000006d7f3 /system/lib/libmedia.so (_ZN7android10AudioTrack16AudioTrackThread10threadLoopEv+194) 
    native: pc 0000000000010079 /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+112) 
    native: pc 000000000004065b /system/lib/libc.so (_ZL15__pthread_startPv+30) 
    native: pc 000000000001a021 /system/lib/libc.so (__start_thread+6) 

的函數調用世界。

這些都是存儲在堆中的所有增值經銷商:

/* OpenSL ES audio stuff */ 
SLObjectItf engineObject = NULL; 
SLEngineItf engineEngine = NULL; 
SLObjectItf outputMixObject = NULL; 
SLObjectItf playerObject = NULL; 
SLPlayItf playerPlay = NULL; 
SLVolumeItf playerVolume = NULL; 
SLAndroidSimpleBufferQueueItf playerBufferQueue = NULL; 
char  openSLinited = 0; 

int16_t  audioBuffer1[48000]; 
int16_t  audioBuffer2[48000]; 
int16_t *currentAudioBuffer; 

這是我是如何初始化所有機械:

void Java_com_myapp_myappname_MyActivity_jniOpenSLInit(JNIEnv *env, 
                 jobject thiz, 
                 jint freq) 
{ 
    SLresult result; 

    // create engine 
    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 
    assert(SL_RESULT_SUCCESS == result); 

    // realize the engine 
    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 
    assert(SL_RESULT_SUCCESS == result); 

    // get the engine interface, which is needed to create other objects 
    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, 
              &engineEngine); 
    assert(SL_RESULT_SUCCESS == result); 

    // create output mix 
    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 
               0, NULL, NULL); 
    assert(SL_RESULT_SUCCESS == result); 

    // realize the output mix 
    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 
    assert(SL_RESULT_SUCCESS == result); 

    SLuint32 SLfreq; 
    if (freq == 44100) 
     SLfreq = SL_SAMPLINGRATE_44_1; 
    else 
     SLfreq = SL_SAMPLINGRATE_48; 

    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = 
     {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; 
    SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 2, SLfreq, 
            SL_PCMSAMPLEFORMAT_FIXED_16, 
            SL_PCMSAMPLEFORMAT_FIXED_16, 
            SL_SPEAKER_FRONT_LEFT | 
            SL_SPEAKER_FRONT_RIGHT, 
            SL_BYTEORDER_LITTLEENDIAN}; 

    SLDataSource audioSrc = {&loc_bufq, &format_pcm}; 

    /* configure audio sink */ 
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, 
              outputMixObject}; 
    SLDataSink audioSnk = {&loc_outmix, NULL}; 

    const SLInterfaceID idsAudioPlayer[2] = {SL_IID_BUFFERQUEUE, 
              SL_IID_VOLUME }; 

    const SLboolean reqAudioPlayer[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; 

    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, 
               &audioSrc, 
               &audioSnk, 2, idsAudioPlayer, 
               reqAudioPlayer); 
    assert(SL_RESULT_SUCCESS == result); 

    // realize the player 
    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 
    assert(SL_RESULT_SUCCESS == result); 

    // get the play interface 
    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, 
              &playerPlay); 
    assert(SL_RESULT_SUCCESS == result); 

    // get the volume interface 
    result = (*playerObject)->GetInterface(playerObject, SL_IID_VOLUME, 
              &playerVolume); 
    assert(SL_RESULT_SUCCESS == result); 

    // get the buffer queue interface 
    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, 
              &playerBufferQueue); 
    assert(SL_RESULT_SUCCESS == result); 

    // register callback on the buffer queue 
    result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, 
                audio_player_cb, NULL); 
    assert(SL_RESULT_SUCCESS == result); 

    // done! 
    openSLinited = 1; 
} 

這就是所謂的啓動機器。

void openSLStart() 
{ 
    bzero(audioBuffer1, 96000); 
    bzero(audioBuffer2, 96000); 

    if (!openSLinited) 
     return; 

    (*playerBufferQueue)->Enqueue(playerBufferQueue, audioBuffer1, 
            4096 * 4); 
    (*playerBufferQueue)->Enqueue(playerBufferQueue, audioBuffer2, 
            4096 * 4); 

    currentAudioBuffer = audioBuffer1; 

    // set the player's state to playing 
    (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 
} 

這是新入隊的樣品

void audio_player_cb(SLAndroidSimpleBufferQueueItf bq, void *context) 
{ 
    if (!openSLinited) 
     return; 

    assert(bq == playerBufferQueue); 
    assert(NULL == context); 

    // switch between audio buffer 1 and 2 
    if (currentAudioBuffer == audioBuffer1) 
     currentAudioBuffer = audioBuffer2; 
    else 
     currentAudioBuffer = audioBuffer1; 

    // this function read samples (4096 16 bit samples) from an internal buffer 
    sound_read_samples(4096, currentAudioBuffer); 

    // feed openSL machine 
    (*playerBufferQueue)->Enqueue(playerBufferQueue, currentAudioBuffer, 
            4096 * 2); 
} 

最後的回調,這是OpenSL是如何終止

void Java_com_myfirm_myappname_MyActivity_jniOpenSLTerm(JNIEnv *env, 
                 jobject thiz) 
{ 
    // shutdown every created object 
    if (playerObject) 
    { 
     // stop the player 
     SLresult result = (*playerPlay)->SetPlayState(playerPlay, 
                 SL_PLAYSTATE_STOPPED); 

     if (SL_RESULT_SUCCESS == result) 
      utils_log("Player succesfully stopped"); 

     (*playerObject)->Destroy(playerObject); 
     playerObject = NULL; 
     playerPlay = NULL; 
    } 

    if (outputMixObject) 
    { 
     (*outputMixObject)->Destroy(outputMixObject); 
     outputMixObject = NULL; 
    } 

    if (engineObject) 
    { 
     (*engineObject)->Destroy(engineObject); 
     engineObject = NULL; 
    } 

    openSLinited = 0; 

    utils_log("OpenSLTerm complete"); 
} 

我不能在我的手機和模擬器再現。它只是從來沒有崩潰這種方式。

我跑出了有關如何解決這個問題的想法。有人可以幫我擺脫這個崩潰嗎?

更新10月8日

我試過的建議刪除日誌。崩潰仍然存在。

問題影響的Android 6.0,7.0和7.1(至少,我得到了不同版本的報道)

更新10月9日

按照要求通過阿姆賈德汗:

這是生成庫的Android.mk

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 

LOCAL_MODULE := libmyapp-jni 
LOCAL_SRC_FILES := src.c src2.c src3.c 
LOCAL_LDLIBS := -llog -landroid -ljnigraphics -lGLESv2 -lOpenSLES 
LOCAL_CFLAGS += -O3 -DNDEBUG 

include $(BUILD_SHARED_LIBRARY) 

並且這是命令跑來構建l (所有ABI都生成)

/cygdrive/c/Android/ndk/ndk-build.cmd NDK_DEBUG=0 APP_BUILD_SCRIPT=./Android.mk NDK_PROJECT_PATH=. 

在此先感謝您。

+0

由於得到這個錯誤的牛軋糖和高版本,從本機.so文件刪除所有日誌嘗試,我們在本地使用日誌,以便文件也產生此故障Play商店中。 (utils_log)這種方法,你可以把[斷言()]代碼 –

+0

我試圖刪除日誌...崩潰再次發生。它似乎影響Android 6,7.0和7.1。我真的失去了 –

+0

你可以添加你的Android.mk代碼和ABI將支持 –

回答

1

我看到了崩潰,它和我的崩潰是一樣的,這是由於android日誌產生的,最近我上傳了apk並找到了相同的跟蹤。

native: pc 0000000000048793 /system/lib/libc.so (pthread_kill+34) 
    native: pc 000000000001d5d5 /system/lib/libc.so (raise+10) 
    native: pc 0000000000019111 /system/lib/libc.so (__libc_android_abort+34) 
    native: pc 0000000000017174 /system/lib/libc.so (abort+4) 
    native: pc 000000000000c481 /system/lib/libcutils.so (__android_log_assert+112) 
    native: pc 0000000000025595 /system/lib/libhwui.so 
    native: pc 00000000000270d1 /system/lib/libhwui.so 
    native: pc 000000000002b959 /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread12RenderThread10threadLoopEv+80) 
    native: pc 000000000000e35d /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+140) 
    native: pc 000000000006830b /system/lib/libandroid_runtime.so (_ZN7android14AndroidRuntime15javaThreadShellEPv+102) 
    native: pc 0000000000048263 /system/lib/libc.so (_ZL15__pthread_startPv+22) 
    native: pc 0000000000019b5d /system/lib/libc.so (__start_thread+6) 

這個回溯是我最近的更新,所以我在我的本地文件中進行android日誌打印。

__android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "%s", Str); 

我用日誌來檢查時,我上傳我得到了回溯打印我的數據,因此,我已刪除了所有來自本地日誌和從本地調用Java函數。

然後,之後我做了乾淨的構建和上傳,因此在最新的版本是不是直到產生現在超過5構建上傳

Android相關的日誌支持

包含應用程序可以使用各種定義將日誌消息從本機代碼發送到內核。有關這些定義的更多信息,請參閱中的註釋。

您可以編寫自己的包裝宏來訪問此功能。如果你想執行日誌記錄,你的本地模塊應該鏈接到/system/lib/liblog.so。

LOCAL_LDLIBS:通過在你的Android.mk文件中的以下行實現此鏈接= -llog

在這裏,你也會找到辦法容易找出錯誤本土

+0

我已經完全刪除所有的日誌。崩潰仍然存在。 –

+0

您是否正在嘗試構建64位體系結構的文件,或者是否使用64位體系結構的外部庫? –

+0

我已經爲每個架構構建了這個庫。在32位或64位都崩潰的事件 –