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