Index: /pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c	(revision 3412)
+++ /pjproject/trunk/pjmedia/src/pjmedia-audiodev/coreaudio_dev.c	(revision 3413)
@@ -126,4 +126,6 @@
 };
 
+/* Static variable */
+static struct coreaudio_factory *cf_instance = NULL;
 
 /* Prototypes */
@@ -287,5 +289,5 @@
 
     /* Initialize the Audio Session */
-    ostatus = AudioSessionInitialize(NULL, NULL, interruptionListener, cf);
+    ostatus = AudioSessionInitialize(NULL, NULL, interruptionListener, NULL);
     if (ostatus != kAudioSessionNoError) {
 	PJ_LOG(4, (THIS_FILE,
@@ -314,4 +316,6 @@
 		   "notifications (%i)", ostatus));
     }
+    
+    cf_instance = cf;
 #endif
 
@@ -335,5 +339,5 @@
         kAudioSessionProperty_AudioRouteChange, propListener, cf);
 #endif
-
+    
     if (cf->pool) {
 	pj_pool_release(cf->pool);
@@ -342,4 +346,7 @@
 
     if (cf->mutex) {
+	pj_mutex_lock(cf->mutex);
+	cf_instance = NULL;
+	pj_mutex_unlock(cf->mutex);
 	pj_mutex_destroy(cf->mutex);
 	cf->mutex = NULL;
@@ -1053,6 +1060,4 @@
     struct coreaudio_factory *cf = (struct coreaudio_factory*)inClientData;
     struct stream_list *it, *itBegin;
-    pj_status_t status;
-    OSStatus ostatus;
     CFDictionaryRef routeDictionary;
     CFNumberRef reason;
@@ -1070,12 +1075,6 @@
     CFNumberGetValue(reason, kCFNumberSInt32Type, &reasonVal);
 
-    if (reasonVal == kAudioSessionRouteChangeReason_CategoryChange) {
-	PJ_LOG(3, (THIS_FILE, "audio route changed due to category change, "
-		   "ignoring..."));
-	return;
-    }
-    if (reasonVal == kAudioSessionRouteChangeReason_Override) {
-	PJ_LOG(3, (THIS_FILE, "audio route changed due to user override, "
-		   "ignoring..."));
+    if (reasonVal != kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
+	PJ_LOG(3, (THIS_FILE, "ignoring audio route change..."));
 	return;
     }
@@ -1086,27 +1085,19 @@
     itBegin = &cf->streams;
     for (it = itBegin->next; it != itBegin; it = it->next) {
-	pj_bool_t running = it->stream->running;
-
 	if (it->stream->interrupted)
 	    continue;
 
+	/* This does not seem necessary anymore. Just make sure	
+	 * that your application can receive remote control
+	 * events by adding the code:
+	 *     [[UIApplication sharedApplication] 
+	 *      beginReceivingRemoteControlEvents];
+	 * Otherwise audio route change (such as headset plug/unplug)
+	 * will not be processed while your application is in the 
+	 * background mode.
+	 */
+	/*
 	status = ca_stream_stop((pjmedia_aud_stream *)it->stream);
-
-	ostatus = AudioUnitUninitialize(it->stream->io_units[0]);
-	ostatus = AudioComponentInstanceDispose(it->stream->io_units[0]);
-
-	status = create_audio_unit(it->stream->cf->io_comp, 0,
-				   it->stream->param.dir,
-				   it->stream, &it->stream->io_units[0]);
-	if (status != PJ_SUCCESS) {
-	    PJ_LOG(3, (THIS_FILE,
-		       "Error: failed to create a replacement audio unit (%i)",
-		       status));
-	    continue;
-	}
-
-	if (running) {
-	    status = ca_stream_start((pjmedia_aud_stream *)it->stream);
-	}
+	status = ca_stream_start((pjmedia_aud_stream *)it->stream);
 	if (status != PJ_SUCCESS) {
 	    PJ_LOG(3, (THIS_FILE,
@@ -1115,5 +1106,6 @@
 	    continue;
 	}
-	PJ_LOG(3, (THIS_FILE, "core audio unit successfully reinstantiated"));
+	PJ_LOG(3, (THIS_FILE, "core audio unit successfully restarted"));
+	*/
     }
     pj_mutex_unlock(cf->mutex);
@@ -1122,9 +1114,6 @@
 static void interruptionListener(void *inClientData, UInt32 inInterruption)
 {
-    struct coreaudio_factory *cf = (struct coreaudio_factory*)inClientData;
     struct stream_list *it, *itBegin;
     pj_status_t status;
-    OSStatus ostatus;
-    pj_assert(cf);
 
     PJ_LOG(3, (THIS_FILE, "Session interrupted! --- %s ---",
@@ -1132,35 +1121,29 @@
 	   "Begin Interruption" : "End Interruption"));
 
-    pj_mutex_lock(cf->mutex);
-    itBegin = &cf->streams;
+    if (!cf_instance)
+	return;
+    
+    pj_mutex_lock(cf_instance->mutex);
+    itBegin = &cf_instance->streams;
     for (it = itBegin->next; it != itBegin; it = it->next) {
-	if (!it->stream->running)
-	    continue;
-
 	if (inInterruption == kAudioSessionEndInterruption &&
 	    it->stream->interrupted == PJ_TRUE)
 	{
-	    ostatus = AudioUnitUninitialize(it->stream->io_units[0]);
-	    ostatus = AudioComponentInstanceDispose(it->stream->io_units[0]);
-
-	    status = create_audio_unit(it->stream->cf->io_comp, 0,
-				       it->stream->param.dir,
-				       it->stream, &it->stream->io_units[0]);
-	    if (status != PJ_SUCCESS) {
-		PJ_LOG(3, (THIS_FILE,
-			   "Error: failed to create a replacement "
-			   "audio unit (%i)", ostatus));
-		continue;
-	    }
-
+	    /* Make sure that your application can receive remote control
+	     * events by adding the code:
+	     *     [[UIApplication sharedApplication] 
+	     *      beginReceivingRemoteControlEvents];
+	     * Otherwise audio unit will fail to restart while your
+	     * application is in the background mode.
+	     */
 	    status = ca_stream_start((pjmedia_aud_stream*)it->stream);
 	    if (status != PJ_SUCCESS) {
 		PJ_LOG(3, (THIS_FILE,
 			   "Error: failed to restart the audio unit (%i)",
-			   ostatus));
-		       continue;
+			   status));
+		continue;
 	    }
-	    PJ_LOG(3, (THIS_FILE, "core audio unit successfully "
-		       "reinstantiated"));
+	    PJ_LOG(3, (THIS_FILE, "core audio unit successfully resumed"
+		       " after interruption"));
 	} else if (inInterruption == kAudioSessionBeginInterruption &&
 		   it->stream->running == PJ_TRUE)
@@ -1170,5 +1153,5 @@
 	}
     }
-    pj_mutex_unlock(cf->mutex);
+    pj_mutex_unlock(cf_instance->mutex);
 }
 
@@ -1525,4 +1508,8 @@
 		          PJMEDIA_AUD_DEV_CAP_EC,
 		          &param->ec_enabled);
+    } else {
+	pj_bool_t ec = PJ_FALSE;
+	ca_stream_set_cap(&strm->base,
+		          PJMEDIA_AUD_DEV_CAP_EC, &ec);
     }
 
@@ -1957,6 +1944,4 @@
     OSStatus ostatus;
     UInt32 i;
-    pj_bool_t should_activate;
-    struct stream_list *it, *itBegin;
 
     if (stream->running)
@@ -1975,4 +1960,8 @@
     }
 
+#if !COREAUDIO_MAC
+    AudioSessionSetActive(true);
+#endif
+    
     for (i = 0; i < 2; i++) {
 	if (stream->io_units[i] == NULL) break;
@@ -1985,27 +1974,5 @@
     }
 
-    /*
-     * Make sure this stream is not in the list of running streams.
-     * If this is the 1st stream that is running we need to activate
-     * the audio session.
-     */
-    pj_mutex_lock(stream->cf->mutex);
-    pj_assert(!pj_list_empty(&stream->cf->streams));
-    pj_assert(!pj_list_empty(&stream->list_entry));
-    should_activate = PJ_TRUE;
-    itBegin = &stream->cf->streams;
-    for (it = itBegin->next; it != itBegin; it = it->next) {
-	if (it->stream->running) {
-	    should_activate = PJ_FALSE;
-	    break;
-	}
-    }
     stream->running = PJ_TRUE;
-    pj_mutex_unlock(stream->cf->mutex);
-
-#if !COREAUDIO_MAC
-    if (should_activate)
-	AudioSessionSetActive(true);
-#endif
 
     PJ_LOG(4, (THIS_FILE, "core audio stream started"));
@@ -2036,9 +2003,5 @@
     }
 
-    /*
-     * Make sure this stream is not in the list of running streams.
-     * If this is the 1st stream that is running we need to activate
-     * the audio session.
-     */
+    /* Check whether we need to deactivate the audio session. */
     pj_mutex_lock(stream->cf->mutex);
     pj_assert(!pj_list_empty(&stream->cf->streams));
Index: /pjproject/trunk/pjsip-apps/src/ipjsua/Classes/FirstViewController.m
===================================================================
--- /pjproject/trunk/pjsip-apps/src/ipjsua/Classes/FirstViewController.m	(revision 3412)
+++ /pjproject/trunk/pjsip-apps/src/ipjsua/Classes/FirstViewController.m	(revision 3413)
@@ -57,4 +57,6 @@
     [super viewDidLoad];
     
+    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
+    
     ipjsuaAppDelegate *appd = (ipjsuaAppDelegate *)[[UIApplication sharedApplication] delegate];
     appd.mainView = self;
