AudioTrack: Enable deep buffer under certain conditions
Under certain conditions, i.e. USAGE_MEDIA and CONTENT_TYPE UNKNOWN, MUSIC, MOVIE and large buffers we route the AudioTrack to deep buffer to save power. Change-Id: Ibc8a31750999da842e36156f939448989ee50511 Test: Play Movies, CTS Bug: 30687201
This commit is contained in:
@@ -27,6 +27,7 @@ import java.util.Collection;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityThread;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
@@ -538,6 +539,15 @@ public class AudioTrack extends PlayerBase
|
||||
throw new IllegalArgumentException("Illegal null AudioFormat");
|
||||
}
|
||||
|
||||
// Check if we should enable deep buffer mode
|
||||
if (shouldEnablePowerSaving(mAttributes, format, bufferSizeInBytes, mode)) {
|
||||
mAttributes = new AudioAttributes.Builder(mAttributes)
|
||||
.replaceFlags((mAttributes.getAllFlags()
|
||||
| AudioAttributes.FLAG_DEEP_BUFFER)
|
||||
& ~AudioAttributes.FLAG_LOW_LATENCY)
|
||||
.build();
|
||||
}
|
||||
|
||||
// remember which looper is associated with the AudioTrack instantiation
|
||||
Looper looper;
|
||||
if ((looper = Looper.myLooper()) == null) {
|
||||
@@ -861,7 +871,10 @@ public class AudioTrack extends PlayerBase
|
||||
.build();
|
||||
break;
|
||||
case PERFORMANCE_MODE_NONE:
|
||||
break;
|
||||
if (!shouldEnablePowerSaving(mAttributes, mFormat, mBufferSizeInBytes, mMode)) {
|
||||
break; // do not enable deep buffer mode.
|
||||
}
|
||||
// permitted to fall through to enable deep buffer
|
||||
case PERFORMANCE_MODE_POWER_SAVING:
|
||||
mAttributes = new AudioAttributes.Builder(mAttributes)
|
||||
.replaceFlags((mAttributes.getAllFlags()
|
||||
@@ -912,6 +925,56 @@ public class AudioTrack extends PlayerBase
|
||||
AudioFormat.CHANNEL_OUT_SIDE_LEFT |
|
||||
AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
|
||||
|
||||
// Returns a boolean whether the attributes, format, bufferSizeInBytes, mode allow
|
||||
// power saving to be automatically enabled for an AudioTrack. Returns false if
|
||||
// power saving is already enabled in the attributes parameter.
|
||||
private static boolean shouldEnablePowerSaving(
|
||||
@Nullable AudioAttributes attributes, @Nullable AudioFormat format,
|
||||
int bufferSizeInBytes, int mode) {
|
||||
// If no attributes, OK
|
||||
// otherwise check attributes for USAGE_MEDIA and CONTENT_UNKNOWN, MUSIC, or MOVIE.
|
||||
if (attributes != null &&
|
||||
(attributes.getAllFlags() != 0 // cannot have any special flags
|
||||
|| attributes.getUsage() != AudioAttributes.USAGE_MEDIA
|
||||
|| (attributes.getContentType() != AudioAttributes.CONTENT_TYPE_UNKNOWN
|
||||
&& attributes.getContentType() != AudioAttributes.CONTENT_TYPE_MUSIC
|
||||
&& attributes.getContentType() != AudioAttributes.CONTENT_TYPE_MOVIE))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format must be fully specified and be linear pcm
|
||||
if (format == null
|
||||
|| format.getSampleRate() == AudioFormat.SAMPLE_RATE_UNSPECIFIED
|
||||
|| !AudioFormat.isEncodingLinearPcm(format.getEncoding())
|
||||
|| !AudioFormat.isValidEncoding(format.getEncoding())
|
||||
|| format.getChannelCount() < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mode must be streaming
|
||||
if (mode != MODE_STREAM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A buffer size of 0 is always compatible with deep buffer (when called from the Builder)
|
||||
// but for app compatibility we only use deep buffer power saving for large buffer sizes.
|
||||
if (bufferSizeInBytes != 0) {
|
||||
final long BUFFER_TARGET_MODE_STREAM_MS = 100;
|
||||
final int MILLIS_PER_SECOND = 1000;
|
||||
final long bufferTargetSize =
|
||||
BUFFER_TARGET_MODE_STREAM_MS
|
||||
* format.getChannelCount()
|
||||
* format.getBytesPerSample(format.getEncoding())
|
||||
* format.getSampleRate()
|
||||
/ MILLIS_PER_SECOND;
|
||||
if (bufferSizeInBytes < bufferTargetSize) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convenience method for the constructor's parameter checks.
|
||||
// This is where constructor IllegalArgumentException-s are thrown
|
||||
// postconditions:
|
||||
|
||||
Reference in New Issue
Block a user