销毁引擎对象时,如何避免android opensl es崩溃?

时间:2018-11-05 07:34:06

标签: android android-ndk opensl

我在android 8.1.0中遇到了opensl es崩溃。

相关代码:

TEResult SLESAudioEngine::release(TEMsg *pMsg) {
    TEResult ret;

    SLuint32 playState = 0;
    (*bqPlayerPlay)->GetPlayState(bqPlayerPlay, &playState);
    LOGE(LOG_TAG, "%s, %d, %d", __FUNCTION__, __LINE__, playState);

    if (bqPlayerPlay != nullptr) {
        SLresult slRet = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
        if (slRet != SL_RESULT_SUCCESS) {
            LOGE(LOG_TAG, "%s,%d SetPlayState failed %d", __FUNCTION__, __LINE__, ret);
            return slRet;
        }
        bqPlayerPlay = nullptr;
    }

    if (bqPlayerBufferQueue != nullptr) {
        SLresult slRet = (*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue);
        if (slRet != SL_RESULT_SUCCESS) {
            LOGE(LOG_TAG, "GetInterface BufferQueueItf failed %d", ret);
            return slRet;
        }
        bqPlayerBufferQueue = nullptr;
    }

    if (bqPlayerObject != nullptr) {
        (*bqPlayerObject)->Destroy(bqPlayerObject);
        bqPlayerObject = nullptr;
    }

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

    LOGE(LOG_TAG, "%s %d Destroy", __FUNCTION__, __LINE__);
    // destroy engine object, and invalidate all associated interfaces
    if (engineObject != NULL) {
        (*engineObject)->Destroy(engineObject);
        engineObject = NULL;
    }

    return ret;
}

相关日志:

11-05 15:17:58.270 F/DEBUG   ( 5887): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-05 15:17:58.270 F/DEBUG   ( 5887): Build fingerprint: 'vivo/PD1806/PD1806:8.1.0/OPM1.171019.019/compil08312141:user/release-keys'
11-05 15:17:58.270 F/DEBUG   ( 5887): Revision: '0'
11-05 15:17:58.270 F/DEBUG   ( 5887): ABI: 'arm'
11-05 15:17:58.270 F/DEBUG   ( 5887): pid: 5609, tid: 5835, name: jerikc.demo.app  >>> com.jerikc.demo.app <<<
11-05 15:17:58.270 F/DEBUG   ( 5887): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
11-05 15:17:58.270 F/DEBUG   ( 5887): Cause: null pointer dereference
11-05 15:17:58.270 F/DEBUG   ( 5887):     r0 fffffffe  r1 00000000  r2 c164d407  r3 f18e1e30
11-05 15:17:58.270 F/DEBUG   ( 5887):     r4 00002282  r5 f18e1da9  r6 f3e66dfc  r7 00000000
11-05 15:17:58.270 F/DEBUG   ( 5887):     r8 f3a66704  r9 000015e9  sl d148808d  fp ced2aa80
11-05 15:17:58.270 F/DEBUG   ( 5887):     ip 00000001  sp c9b95550  lr f18e1e07  pc f3dd0482  cpsr 880f0030
11-05 15:17:58.310 F/DEBUG   ( 5887): 
11-05 15:17:58.310 F/DEBUG   ( 5887): backtrace:
11-05 15:17:58.310 F/DEBUG   ( 5887):     #00 pc 000bc482  /system/lib/libandroid_runtime.so (android::proxy_cleanup(void const*, void*, void*)+65)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #01 pc 00040787  /system/lib/libbinder.so (android::BpBinder::ObjectManager::kill()+30)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #02 pc 00040745  /system/lib/libbinder.so (android::BpBinder::ObjectManager::~ObjectManager()+4)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #03 pc 000410b9  /system/lib/libbinder.so (android::BpBinder::~BpBinder()+124)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #04 pc 00041125  /system/lib/libbinder.so (android::BpBinder::~BpBinder()+12)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #05 pc 00040547  /system/lib/libbinder.so (android::BpRefBase::~BpRefBase()+46)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #06 pc 00004633  /system/lib/libaudiomanager.so (_ZTv0_n12_N7android14BpAudioManagerD0Ev+22)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #07 pc 0000dc5f  /system/lib/libwilhelm.so (android::sp<android::TrackPlayerBase>::clear()+18)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #08 pc 00016a2f  /system/lib/libwilhelm.so (CEngine_Destroy(void*)+198)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #09 pc 0001b975  /system/lib/libwilhelm.so (IObject_Destroy(SLObjectItf_ const* const*)+204)
11-05 15:17:58.310 F/DEBUG   ( 5887):     #10 pc 001c197f  /data/app/com.jerikc.demo.app-4ZSXR9PUHNOeJT-UudwsOQ==/lib/arm/libaudioenginedemo.so (SLESAudioEngine::release(TEMsg*)+486)
11-05 15:17:59.130 V/AudioFlinger( 1002): 5609 died, releasing its sessions

1 个答案:

答案 0 :(得分:2)

将OpenSL代码移动到单独的线程后,同样遇到了同样的问题。幸运的是,Android OS sources给出了一个简短的答案:

import org.json4s._
import org.json4s.native.JsonMethods._
import org.json4s.native.Serialization.{ read, write }
import org.json4s.native.Serialization

abstract class Tree
case class Node(nameN: String, trees: List[Tree]) extends Tree
case class Leaf(nameL: String) extends Tree

object Tree extends App {
  implicit val formats = Serialization.formats(NoTypeHints)

  // object creation to test the serialization
  val root =
    Node(
      "Grand Pavois project",
      List(
        Node(
          "studies",
          List(
            Leaf("preliminary studies"),
            Leaf("detailled studies")
          )
        ),
        Node(
          "realization",
          List(
            Leaf("ground"),
            Leaf("building"),
            Leaf("roof")
          )
        ),
        Node(
          "delivery",
          List(
            Leaf("quality inspection"),
            Leaf("customer delivery")
          )
        )
      )
    )

  val serialized = write(root) // object creation and serialization
  println(s"serialized: $serialized") // print the result, this is OK

  // and now what about deserialization?
  // string creation for deserialization
  // ( it is the same as serialized above, I do like that to trace for the demo)
  val rootString = """
{
  "nameN": "Grand Pavois project",
  "trees": [
    {
      "nameN": "studies",
      "trees": [
        {
          "nameL": "preliminary studies"
        },
        {
          "nameL": "detailled studies"
        }
      ]
    },
    {
      "nameN": "realization",
      "trees": [
        {
          "nameL": "ground"
        },
        {
          "nameL": "building"
        },
        {
          "nameL": "roof"
        }
      ]
    },
    {
      "nameN": "delivery",
      "trees": [
        {
          "nameL": "quality inspection"
        },
        {
          "nameL": "customer delivery"
        }
      ]
    }
  ]
}
"""
//standard deserialization below that produce an error :
// "Parsed JSON values do not match with class constructor"
val rootFromString = read[Tree](rootString)
}

长话短说,OpenSLES引擎现在由Java对象支持,因此它需要有效的JavaVM引用才能运行。基本上,这意味着应该从JVM附加线程创建它(不确定破坏性,但是我猜想static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) { android_atomic_dec(&gNumProxyRefs); JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie); env->DeleteGlobalRef((jobject)obj); } 被传递是有原因的。)