From 309dc35faf3fc8252fe8a937e195fbea3e6da489 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Sat, 16 Jun 2018 15:17:27 +0800 Subject: [PATCH 1/5] AudioAPI: simplify code --- .../main/java/com/termux/api/AudioAPI.java | 57 +++++++------------ 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/termux/api/AudioAPI.java b/app/src/main/java/com/termux/api/AudioAPI.java index 81a7dd8c2..05ad76a25 100644 --- a/app/src/main/java/com/termux/api/AudioAPI.java +++ b/app/src/main/java/com/termux/api/AudioAPI.java @@ -27,52 +27,37 @@ static void onReceive(TermuxApiReceiver apiReceiver, final Context context, Inte final boolean bluetootha2dp = am.isBluetoothA2dpOn(); final boolean wiredhs = am.isWiredHeadsetOn(); - int _sr, _bs, _sr_ll, _bs_ll, _nosr; - _sr = _bs = _sr_ll = _bs_ll = _nosr = 0; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - int[] modes = {AudioTrack.PERFORMANCE_MODE_POWER_SAVING, - AudioTrack.PERFORMANCE_MODE_LOW_LATENCY}; - for (int mode: modes) { - AudioTrack at = new AudioTrack.Builder() + final int sr, bs, sr_ll, bs_ll, nosr; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + nosr = 0; + AudioTrack at; + at = new AudioTrack.Builder() + .setBufferSizeInBytes(4) // one 16bit 2ch frame + .build(); + sr = at.getSampleRate(); + bs = at.getBufferSizeInFrames(); + at.release(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + at = new AudioTrack.Builder() .setBufferSizeInBytes(4) // one 16bit 2ch frame - .setPerformanceMode(mode) + .setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY) .build(); - if (mode == AudioTrack.PERFORMANCE_MODE_POWER_SAVING) { - _sr = at.getSampleRate(); - _bs = at.getBufferSizeInFrames(); - } else if (mode == AudioTrack.PERFORMANCE_MODE_LOW_LATENCY) { - _sr_ll = at.getSampleRate(); - _bs_ll = at.getBufferSizeInFrames(); - } - at.release(); - } - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - int[] flags = {0,AudioAttributes.FLAG_LOW_LATENCY}; - for (int flag: flags) { + } else { AudioAttributes aa = new AudioAttributes.Builder() - .setFlags(flag) + .setFlags(AudioAttributes.FLAG_LOW_LATENCY) .build(); - AudioTrack at = new AudioTrack.Builder() + at = new AudioTrack.Builder() .setAudioAttributes(aa) .setBufferSizeInBytes(4) // one 16bit 2ch frame .build(); - if (flag == 0) { - _sr = at.getSampleRate(); - _bs = at.getBufferSizeInFrames(); - } else if (flag == AudioAttributes.FLAG_LOW_LATENCY) { - _sr_ll = at.getSampleRate(); - _bs_ll = at.getBufferSizeInFrames(); - } - at.release(); } + sr_ll = at.getSampleRate(); + bs_ll = at.getBufferSizeInFrames(); + at.release(); } else { - _nosr = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); + sr = bs = sr_ll = bs_ll = 0; + nosr = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); } - final int sr = _sr; - final int bs = _bs; - final int sr_ll = _sr_ll; - final int bs_ll = _bs_ll; - final int nosr = _nosr; ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultJsonWriter() { public void writeJson(JsonWriter out) throws Exception { From db1fea29e9d9355908f0728aa152ac929df8e6be Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Sat, 16 Jun 2018 15:18:25 +0800 Subject: [PATCH 2/5] AudioAPI: remove volume info Redundunt with the introduction of VolumeAPI --- app/src/main/java/com/termux/api/AudioAPI.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/src/main/java/com/termux/api/AudioAPI.java b/app/src/main/java/com/termux/api/AudioAPI.java index 05ad76a25..769a260e5 100644 --- a/app/src/main/java/com/termux/api/AudioAPI.java +++ b/app/src/main/java/com/termux/api/AudioAPI.java @@ -22,8 +22,6 @@ static void onReceive(TermuxApiReceiver apiReceiver, final Context context, Inte } else { AudioUnprocessed = null; } - final int volume_level = am.getStreamVolume(AudioManager.STREAM_MUSIC); - final int maxvolume_level = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); final boolean bluetootha2dp = am.isBluetoothA2dpOn(); final boolean wiredhs = am.isWiredHeadsetOn(); @@ -67,8 +65,6 @@ public void writeJson(JsonWriter out) throws Exception { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { out.name("PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED").value(AudioUnprocessed); } - out.name("STREAM_MUSIC_VOLUME").value(volume_level); - out.name("STREAM_MUSIC_MAXVOLUME").value(maxvolume_level); out.name("BLUETOOTH_A2DP_IS_ON").value(bluetootha2dp); out.name("WIREDHEADSET_IS_CONNECTED").value(wiredhs); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { From 891bb7bdd3c62e6ead19f3d0224d351261a4f7d1 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Sat, 16 Jun 2018 15:19:47 +0800 Subject: [PATCH 3/5] AudioAPI: remove PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED It does not seem to have a point for us to get this property as it is not very clear what it actually reflects. We have not been getting PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND and PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND either. In fact, properties from getProperty() tend to be rather useless. PROPERTY_OUTPUT_FRAMES_PER_BUFFER and PROPERTY_OUTPUT_SAMPLE_RATE are kept only to show that, they should NOT be used to optimize any player in audio output, as they do not change as per the current sink, not like the values from the AudioTrack methods do. --- app/src/main/java/com/termux/api/AudioAPI.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/src/main/java/com/termux/api/AudioAPI.java b/app/src/main/java/com/termux/api/AudioAPI.java index 769a260e5..55185ed16 100644 --- a/app/src/main/java/com/termux/api/AudioAPI.java +++ b/app/src/main/java/com/termux/api/AudioAPI.java @@ -16,12 +16,6 @@ static void onReceive(TermuxApiReceiver apiReceiver, final Context context, Inte AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); final String SampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); final String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER); - final String AudioUnprocessed; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - AudioUnprocessed = am.getProperty(AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED); - } else { - AudioUnprocessed = null; - } final boolean bluetootha2dp = am.isBluetoothA2dpOn(); final boolean wiredhs = am.isWiredHeadsetOn(); @@ -62,9 +56,6 @@ public void writeJson(JsonWriter out) throws Exception { out.beginObject(); out.name("PROPERTY_OUTPUT_SAMPLE_RATE").value(SampleRate); out.name("PROPERTY_OUTPUT_FRAMES_PER_BUFFER").value(framesPerBuffer); - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - out.name("PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED").value(AudioUnprocessed); - } out.name("BLUETOOTH_A2DP_IS_ON").value(bluetootha2dp); out.name("WIREDHEADSET_IS_CONNECTED").value(wiredhs); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { From 809f31ae79acdb87186cc93529aa94d22f9516a7 Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Sat, 16 Jun 2018 15:21:10 +0800 Subject: [PATCH 4/5] AudioAPI: order output --- app/src/main/java/com/termux/api/AudioAPI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/termux/api/AudioAPI.java b/app/src/main/java/com/termux/api/AudioAPI.java index 55185ed16..24bca9cbd 100644 --- a/app/src/main/java/com/termux/api/AudioAPI.java +++ b/app/src/main/java/com/termux/api/AudioAPI.java @@ -56,8 +56,6 @@ public void writeJson(JsonWriter out) throws Exception { out.beginObject(); out.name("PROPERTY_OUTPUT_SAMPLE_RATE").value(SampleRate); out.name("PROPERTY_OUTPUT_FRAMES_PER_BUFFER").value(framesPerBuffer); - out.name("BLUETOOTH_A2DP_IS_ON").value(bluetootha2dp); - out.name("WIREDHEADSET_IS_CONNECTED").value(wiredhs); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { out.name("AUDIOTRACK_SAMPLE_RATE").value(sr); out.name("AUDIOTRACK_BUFFER_SIZE_IN_FRAMES").value(bs); @@ -68,6 +66,8 @@ public void writeJson(JsonWriter out) throws Exception { } else { out.name("AUDIOTRACK_NATIVE_OUTPUT_SAMPLE_RATE").value(nosr); } + out.name("BLUETOOTH_A2DP_IS_ON").value(bluetootha2dp); + out.name("WIREDHEADSET_IS_CONNECTED").value(wiredhs); out.endObject(); } }); From 34161d7ed11e4b5e40fda570528e77e7558596ab Mon Sep 17 00:00:00 2001 From: Tom Yan Date: Wed, 20 Jun 2018 13:59:24 +0800 Subject: [PATCH 5/5] AudioAPI: check info in PERFORMANCE_MODE_POWER_SAVING When setPerformanceMode was introduced in Android O, it was introduced with three possible modes, namely: PERFORMANCE_MODE_NONE (default) PERFORMANCE_MODE_LOW_LATENCY PERFORMANCE_MODE_POWER_SAVING While PERFORMANCE_MODE_NONE essentially causes tracks to be routed to the deep buffer mixer path on my phone (as PERFORMANCE_MODE_POWER_SAVING does), it may not be the case on every single device. Therefore, check info with track in PERFORMANCE_MODE_POWER_SAVING, compare it against that of the default PERFORMANCE_MODE_NONE, and print it out if they are not the same. Note: shouldEnablePowerSaving for PERFORMANCE_MODE_NONE always returns false for SAMPLE_RATE_UNSPECIFIED as of the current AudioTrack.java. --- .../main/java/com/termux/api/AudioAPI.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/termux/api/AudioAPI.java b/app/src/main/java/com/termux/api/AudioAPI.java index 24bca9cbd..ebb4c2dee 100644 --- a/app/src/main/java/com/termux/api/AudioAPI.java +++ b/app/src/main/java/com/termux/api/AudioAPI.java @@ -19,7 +19,7 @@ static void onReceive(TermuxApiReceiver apiReceiver, final Context context, Inte final boolean bluetootha2dp = am.isBluetoothA2dpOn(); final boolean wiredhs = am.isWiredHeadsetOn(); - final int sr, bs, sr_ll, bs_ll, nosr; + final int sr, bs, sr_ll, bs_ll, sr_ps, bs_ps, nosr; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { nosr = 0; AudioTrack at; @@ -29,6 +29,7 @@ static void onReceive(TermuxApiReceiver apiReceiver, final Context context, Inte sr = at.getSampleRate(); bs = at.getBufferSizeInFrames(); at.release(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { at = new AudioTrack.Builder() .setBufferSizeInBytes(4) // one 16bit 2ch frame @@ -46,8 +47,21 @@ static void onReceive(TermuxApiReceiver apiReceiver, final Context context, Inte sr_ll = at.getSampleRate(); bs_ll = at.getBufferSizeInFrames(); at.release(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + at = new AudioTrack.Builder() + .setBufferSizeInBytes(4) // one 16bit 2ch frame + .setPerformanceMode(AudioTrack.PERFORMANCE_MODE_POWER_SAVING) + .build(); + sr_ps = at.getSampleRate(); + bs_ps = at.getBufferSizeInFrames(); + at.release(); + } else { + sr_ps = sr; + bs_ps = bs; + } } else { - sr = bs = sr_ll = bs_ll = 0; + sr = bs = sr_ll = bs_ll = sr_ps = bs_ps = 0; nosr = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); } @@ -63,6 +77,10 @@ public void writeJson(JsonWriter out) throws Exception { out.name("AUDIOTRACK_SAMPLE_RATE_LOW_LATENCY").value(sr_ll); out.name("AUDIOTRACK_BUFFER_SIZE_IN_FRAMES_LOW_LATENCY").value(bs_ll); } + if (sr_ps != sr || bs_ps != bs) { // all or nothing + out.name("AUDIOTRACK_SAMPLE_RATE_POWER_SAVING").value(sr_ps); + out.name("AUDIOTRACK_BUFFER_SIZE_IN_FRAMES_POWER_SAVING").value(bs_ps); + } } else { out.name("AUDIOTRACK_NATIVE_OUTPUT_SAMPLE_RATE").value(nosr); }