diff --git a/src/android/AudioRecorder_to_android.cpp b/src/android/AudioRecorder_to_android.cpp
index ebb95926492d9abbdaca4d643feaa2f755e6b4ab..800a767184d32a5edc21fe0d3e8a7b2bcea03e03 100644
--- a/src/android/AudioRecorder_to_android.cpp
+++ b/src/android/AudioRecorder_to_android.cpp
@@ -212,6 +212,12 @@ static void audioRecorder_callback(int event, void* user, void *info) {
     //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info);
 
     CAudioRecorder *ar = (CAudioRecorder *)user;
+
+    if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) {
+        // it is not safe to enter the callback (the track is about to go away)
+        return;
+    }
+
     void * callbackPContext = NULL;
 
     switch(event) {
@@ -289,6 +295,8 @@ static void audioRecorder_callback(int event, void* user, void *info) {
         break;
 
     }
+
+    ar->mCallbackProtector->exitCb();
 }
 
 
@@ -312,6 +320,7 @@ SLresult android_audioRecorder_create(CAudioRecorder* ar) {
         // microphone to simple buffer queue
         ar->mAndroidObjType = AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE;
         ar->mAudioRecord.clear();
+        ar->mCallbackProtector = new android::CallbackProtector();
         ar->mRecordSource = AUDIO_SOURCE_DEFAULT;
     } else {
         result = SL_RESULT_CONTENT_UNSUPPORTED;
@@ -429,15 +438,30 @@ SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) {
 }
 
 
+//-----------------------------------------------------------------------------
+/**
+ * Called with a lock on AudioRecorder, and blocks until safe to destroy
+ */
+void android_audioRecorder_preDestroy(CAudioRecorder* ar) {
+    object_unlock_exclusive(&ar->mObject);
+    if (ar->mCallbackProtector != 0) {
+        ar->mCallbackProtector->requestCbExitAndWait();
+    }
+    object_lock_exclusive(&ar->mObject);
+}
+
+
 //-----------------------------------------------------------------------------
 void android_audioRecorder_destroy(CAudioRecorder* ar) {
     SL_LOGV("android_audioRecorder_destroy(%p) entering", ar);
 
     if (ar->mAudioRecord != 0) {
         ar->mAudioRecord->stop();
+        ar->mAudioRecord.clear();
     }
     // explicit destructor
     ar->mAudioRecord.~sp();
+    ar->mCallbackProtector.~sp();
 
 #ifdef MONITOR_RECORDING
     if (NULL != gMonitorFp) {
diff --git a/src/android/AudioRecorder_to_android.h b/src/android/AudioRecorder_to_android.h
index b8d4dd27cfcf15f17e603f8f8c021c9ed816f91c..d561ca1277cc3da123e6c963e26dadf7de644950 100644
--- a/src/android/AudioRecorder_to_android.h
+++ b/src/android/AudioRecorder_to_android.h
@@ -45,6 +45,8 @@ extern SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar
 
 extern SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async);
 
+extern void android_audioRecorder_preDestroy(CAudioRecorder* ar);
+
 extern void android_audioRecorder_destroy(CAudioRecorder* ar);
 
 /**************************************************************************************************
diff --git a/src/classes.h b/src/classes.h
index 977772dab16f6b5d16e214ec35bad37d6ec03bb2..37508e70b50c7f344bbb71490f536d7ae24a1632 100644
--- a/src/classes.h
+++ b/src/classes.h
@@ -150,6 +150,7 @@
     // FIXME consolidate the next several variables into ARecorder class to avoid placement new
     enum AndroidObjectType mAndroidObjType;
     android::sp<android::AudioRecord> mAudioRecord;
+    android::sp<android::CallbackProtector> mCallbackProtector;
     audio_source_t mRecordSource;
 #endif
 } /*CAudioRecorder*/;
diff --git a/src/itf/IEngine.c b/src/itf/IEngine.c
index 6950baf601877a53480a1f988df4cfc31839114e..7d3e07a92d5018acf63a1c03b1de3822de4d9b98 100644
--- a/src/itf/IEngine.c
+++ b/src/itf/IEngine.c
@@ -453,6 +453,8 @@ static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pReco
                     // FIXME unnecessary once those fields are encapsulated in one class, rather
                     //   than a structure
                     (void) new (&thiz->mAudioRecord) android::sp<android::AudioRecord>();
+                    (void) new (&thiz->mCallbackProtector)
+                            android::sp<android::CallbackProtector>();
                     thiz->mRecordSource = AUDIO_SOURCE_DEFAULT;
 #endif
 
diff --git a/src/objects/CAudioRecorder.c b/src/objects/CAudioRecorder.c
index 956e98727b5640377eada1578f2170229141ab70..6eab0cfce229270ccaf56dedd7e03f1e01d95888 100644
--- a/src/objects/CAudioRecorder.c
+++ b/src/objects/CAudioRecorder.c
@@ -59,5 +59,9 @@ void CAudioRecorder_Destroy(void *self)
 
 predestroy_t CAudioRecorder_PreDestroy(void *self)
 {
+    CAudioRecorder *thiz = (CAudioRecorder *) self;
+#ifdef ANDROID
+    android_audioRecorder_preDestroy(thiz);
+#endif
     return predestroy_ok;
 }