1cb93a386Sopenharmony_ci[Oboe Docs Home](README.md)
2cb93a386Sopenharmony_ci
3cb93a386Sopenharmony_ci# Tech Note: Disconnected Streams and Plugin Issues
4cb93a386Sopenharmony_ci
5cb93a386Sopenharmony_ciWhen Oboe is using **OpenSL ES**, and a headset is plugged in or out, then OpenSL ES will automatically switch between devices.
6cb93a386Sopenharmony_ciThis is convenient but can cause problems because the new device may have different burst sizes and different latency.
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ciWhen Oboe is using **AAudio**, and a headset is plugged in or out, then
9cb93a386Sopenharmony_cithe stream is no longer available and becomes "disconnected".
10cb93a386Sopenharmony_ciThe app should then be notified in one of two ways. 
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci1) If the app is using a callback then the AudioStreamCallback object will be called.
13cb93a386Sopenharmony_ciIt will launch a thread, which will call onErrorBeforeClose().
14cb93a386Sopenharmony_ciThen it stops and closes the stream.
15cb93a386Sopenharmony_ciThen onErrorAfterClose() will be called.
16cb93a386Sopenharmony_ciAn app may choose to reopen a stream in the onErrorAfterClose() method.
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci2) If an app is using read()/write() calls then they will return an error when a disconnect occurs.
19cb93a386Sopenharmony_ciThe app should then stop() and close() the stream.
20cb93a386Sopenharmony_ciAn app may then choose to reopen a stream.
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ci## Workaround for not Disconnecting Properly
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ciOn some versions of Android P the disconnect message does not reach AAudio and the app will not
25cb93a386Sopenharmony_ciknow that the device has changed. There is a "Test Disconnects" option in
26cb93a386Sopenharmony_ci[OboeTester](https://github.com/google/oboe/tree/master/apps/OboeTester/docs)
27cb93a386Sopenharmony_cithat can be used to diagnose this problem.
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ciAs a workaround you can listen for a Java [Intent.ACTION_HEADSET_PLUG](https://developer.android.com/reference/android/content/Intent#ACTION_HEADSET_PLUG),
30cb93a386Sopenharmony_ciwhich is fired when a head set is plugged in or out. If your min SDK is LOLLIPOP or later then you can use [AudioManager.ACTION_HEADSET_PLUG](https://developer.android.com/reference/android/media/AudioManager#ACTION_HEADSET_PLUG) instead.
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    // Receive a broadcast Intent when a headset is plugged in or unplugged.
33cb93a386Sopenharmony_ci    public class PluginBroadcastReceiver extends BroadcastReceiver {
34cb93a386Sopenharmony_ci        @Override
35cb93a386Sopenharmony_ci        public void onReceive(Context context, Intent intent) {
36cb93a386Sopenharmony_ci            // Close the stream if it was not disconnected.
37cb93a386Sopenharmony_ci        }
38cb93a386Sopenharmony_ci    }
39cb93a386Sopenharmony_ci    
40cb93a386Sopenharmony_ci    private BroadcastReceiver mPluginReceiver = new PluginBroadcastReceiver();
41cb93a386Sopenharmony_ci    
42cb93a386Sopenharmony_ciYou can register for the Intent when your app resumes and unregister when it pauses.
43cb93a386Sopenharmony_ci    
44cb93a386Sopenharmony_ci    @Override
45cb93a386Sopenharmony_ci    public void onResume() {
46cb93a386Sopenharmony_ci        super.onResume();
47cb93a386Sopenharmony_ci        IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
48cb93a386Sopenharmony_ci        this.registerReceiver(mPluginReceiver, filter);
49cb93a386Sopenharmony_ci    }
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    @Override
52cb93a386Sopenharmony_ci    public void onPause() {
53cb93a386Sopenharmony_ci        this.unregisterReceiver(mPluginReceiver);
54cb93a386Sopenharmony_ci        super.onPause();
55cb93a386Sopenharmony_ci    }
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci## Internal Notes
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci* Oboe Issues
60cb93a386Sopenharmony_ci  * [#381](https://github.com/google/oboe/issues/381) Connecting headphones does not trigger any event. S9
61cb93a386Sopenharmony_ci  * [#893](https://github.com/google/oboe/issues/893) onErrorBeforeClose and onErrorAfterClose not called, S10
62cb93a386Sopenharmony_ci  * [#908](https://github.com/google/oboe/issues/908) Huawei MAR-LX3A
63cb93a386Sopenharmony_ci* This issue is tracked internally as b/111711159.
64cb93a386Sopenharmony_ci* A fix in AOSP is [here](https://android-review.googlesource.com/c/platform/frameworks/av/+/836184)
65cb93a386Sopenharmony_ci* A fix was also merged into pi-dev on July 30, 2018.
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci### Results from Test Disconnect in OboeTester
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci| Device | Build | Result |
70cb93a386Sopenharmony_ci|:--|:--|:--|
71cb93a386Sopenharmony_ci| Pixel 1 | QQ1A.190919.002 | ALL PASS |
72cb93a386Sopenharmony_ci| Samsung S10e | PPR1.180610.011 | MMAP Output plugIN failed |
73cb93a386Sopenharmony_ci| Huawei MAR-LX3A | 10.0.0.216 | MMAP In/Out fails, Legacy In fails. |
74