Snap for 12391343 from f4bbe5bf8efebd555425ccabb6c64e9140a5fa42 to 24Q4-release
Change-Id: I79e89e34bb3d27fd2162ed7af5dc84a9a8e1d8ed
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index b5d4ae5..bf1520b 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -218,3 +218,10 @@
description: "Enable CameraServiceWatchdog to abort camera HAL to generate HAL tombstones"
bug: "349652177"
}
+
+flag {
+ namespace: "camera_platform"
+ name: "enable_stream_reconfiguration_for_unchanged_streams"
+ description: "Enable stream reconfiguration for unchanged streams"
+ bug: "341740105"
+}
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 9221c04..c732708 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -60,6 +60,15 @@
}
flag {
+ name: "equal_sco_lea_vc_index_range"
+ namespace: "media_audio"
+ description:
+ "Introduce the same index range for voice calls over SCO and "
+ "LE audio"
+ bug: "364364777"
+}
+
+flag {
name: "music_fx_edge_to_edge"
namespace: "media_audio"
description: "Enable Edge-to-edge feature for MusicFx and handle insets"
diff --git a/media/psh_utils/AudioToken.cpp b/media/psh_utils/AudioToken.cpp
index 626f959..f7bf382 100644
--- a/media/psh_utils/AudioToken.cpp
+++ b/media/psh_utils/AudioToken.cpp
@@ -41,6 +41,14 @@
// APM has a back pointer to AudioToken, which is accessible on toString().
// We first remove ourselves to prevent use after free.
apm.clear_token_ptr(this);
+
+ // The client token is released when it is no longer registered with AudioFlinger.
+ // However, it is possible that AudioTrackTokens are still active when the client is released
+ // after crashing and some of its tracks are draining. Those track tokens also
+ // maintain a pointer to the PowerClientStats keeping that consistent.
+
+ // Stopping the client moves its PowerClientStats from active to historical
+ // if it is the last pid associated with the client uid.
apm.stopClient(mPid);
}
diff --git a/media/psh_utils/PowerClientStats.cpp b/media/psh_utils/PowerClientStats.cpp
index 77d79e4..65f65a44 100644
--- a/media/psh_utils/PowerClientStats.cpp
+++ b/media/psh_utils/PowerClientStats.cpp
@@ -39,12 +39,12 @@
void PowerClientStats::stop(int64_t actualNs) {
std::lock_guard l(mMutex);
if (--mTokenCount > 0) return;
- if (mStartNs != 0) mDeltaNs += actualNs - mStartNs;
+ if (mStartNs != 0) mCumulativeNs += actualNs - mStartNs;
mStartNs = 0;
if (!mStartStats) return;
const auto stopStats = PowerStatsCollector::getCollector().getStats(kStatTimeToleranceNs);
if (stopStats && stopStats != mStartStats) {
- *mDeltaStats += *stopStats - *mStartStats;
+ *mCumulativeStats += *stopStats - *mStartStats;
}
mStartStats.reset();
}
@@ -64,15 +64,15 @@
std::lock_guard l(mMutex);
// Adjust delta time and stats if currently running.
- auto deltaStats = mDeltaStats;
- auto deltaNs = mDeltaNs;
- if (mStartNs) deltaNs += systemTime(SYSTEM_TIME_BOOTTIME) - mStartNs;
+ auto cumulativeStats = mCumulativeStats;
+ auto cumulativeNs = mCumulativeNs;
+ if (mStartNs) cumulativeNs += systemTime(SYSTEM_TIME_BOOTTIME) - mStartNs;
if (mStartStats) {
const auto stopStats = PowerStatsCollector::getCollector().getStats(kStatTimeToleranceNs);
if (stopStats && stopStats != mStartStats) {
- auto newStats = std::make_shared<PowerStats>(*deltaStats);
+ auto newStats = std::make_shared<PowerStats>(*cumulativeStats);
*newStats += *stopStats - *mStartStats;
- deltaStats = newStats;
+ cumulativeStats = newStats;
}
}
@@ -81,7 +81,7 @@
.append(std::to_string(mUid))
.append(" ").append(mediautils::UidInfo::getInfo(mUid)->package)
.append(" streams: ").append(std::to_string(mTokenCount))
- .append(" seconds: ").append(std::to_string(deltaNs * 1e-9));
+ .append(" seconds: ").append(std::to_string(cumulativeNs * 1e-9));
result.append(" {");
for (auto pid : mPids) {
result.append(" ").append(std::to_string(pid));
@@ -93,7 +93,7 @@
if (stats) {
std::string prefix2(prefix);
prefix2.append(" ");
- result.append("\n").append(deltaStats->normalizedEnergy(prefix2));
+ result.append("\n").append(cumulativeStats->normalizedEnergy(prefix2));
}
return result;
}
diff --git a/media/psh_utils/include/psh_utils/PowerClientStats.h b/media/psh_utils/include/psh_utils/PowerClientStats.h
index 93d1fa9..6e27e41 100644
--- a/media/psh_utils/include/psh_utils/PowerClientStats.h
+++ b/media/psh_utils/include/psh_utils/PowerClientStats.h
@@ -87,10 +87,12 @@
int64_t mStartNs GUARDED_BY(mMutex) = 0;
std::shared_ptr<const PowerStats> mStartStats GUARDED_BY(mMutex);
- // Total actual time app is active (stop - start)
- int64_t mDeltaNs GUARDED_BY(mMutex) = 0;
- // The stats taken for the active time (snapshots are quantized to 500ms accuracy).
- std::shared_ptr<PowerStats> mDeltaStats GUARDED_BY(mMutex) = std::make_shared<PowerStats>();
+ // Cumulative time while active: sum of deltas of (stop - start).
+ int64_t mCumulativeNs GUARDED_BY(mMutex) = 0;
+ // Cumulative stats while active: sum of deltas of (stop - start),
+ // where snapshots are quantized to ~500ms accuracy.
+ std::shared_ptr<PowerStats> mCumulativeStats GUARDED_BY(mMutex) =
+ std::make_shared<PowerStats>();
};
} // namespace android::media::psh_utils
diff --git a/media/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
index 1049d5e..8f9ee86 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -69,6 +69,6 @@
java_defaults {
name: "MediaBenchmark-defaults",
- min_sdk_version: "29",
- target_sdk_version: "30",
+ min_sdk_version: "35",
+ target_sdk_version: "35",
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
index 28c2654..bc0c16f 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
@@ -26,7 +26,7 @@
tools:ignore="AllowBackup,GoogleAppIndexingWarning,MissingApplicationIcon"
tools:remove="android:appComponentFactory">
</application>
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="31"/>
+ <uses-sdk android:minSdkVersion="35" android:targetSdkVersion="35"/>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.media.benchmark"
android:label="Benchmark Media Test"/>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/build.gradle b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
index a2af701..87fc24c 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/build.gradle
+++ b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
@@ -27,11 +27,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 30
+ compileSdkVersion 35
defaultConfig {
applicationId "com.android.media.benchmark"
minSdkVersion 29
- targetSdkVersion 30
+ targetSdkVersion 35
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
index afd70a3..c68a990 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
@@ -46,6 +46,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -118,7 +119,7 @@
}
@Test(timeout = PER_TEST_TIMEOUT_MS)
- public void testDecoder() throws IOException {
+ public void testDecoder() throws IOException, InterruptedException {
File inputFile = new File(mInputFilePath + mInputFile);
assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
inputFile.exists());
@@ -133,7 +134,7 @@
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
String mime = format.getString(MediaFormat.KEY_MIME);
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
assertTrue("No suitable codecs found for file: " + mInputFile + " track : " +
currentTrack + " mime: " + mime, (mediaCodecs.size() > 0));
@@ -205,7 +206,7 @@
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
String mime = format.getString(MediaFormat.KEY_MIME);
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
for (String codecName : mediaCodecs) {
Log.i("Test: %s\n", mInputFile);
Native nativeDecoder = new Native();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
index 4202732..4ce5214 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -50,6 +50,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -150,7 +151,7 @@
}
@BeforeClass
- public static void prepareInput() throws IOException {
+ public static void prepareInput() throws IOException, InterruptedException {
mDecodedFileFullHd = new File(mFileDirPath + DECODE_FULLHD_UNPACKED);
int status = decodeFile(mInputFilePath + DECODE_FULLHD_INPUT, mDecodedFileFullHd);
@@ -165,7 +166,8 @@
assertEquals("Decoder returned error " + status, 0, status);
}
- private static int decodeFile(String inputFileName, File outputDecodeFile) throws IOException {
+ private static int decodeFile(String inputFileName, File outputDecodeFile)
+ throws IOException, InterruptedException {
int status = -1;
File inputFile = new File(inputFileName);
assertTrue("Cannot open input file " + inputFileName, inputFile.exists());
@@ -220,7 +222,7 @@
int status;
int frameSize;
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
assertTrue("No suitable codecs found for mimetype: " + mMime, (mediaCodecs.size() > 0));
Boolean[] encodeMode = {true, false};
// Encoding the decoded input file
@@ -297,7 +299,7 @@
@Test(timeout = PER_TEST_TIMEOUT_MS)
public void testNativeEncoder() {
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
assertTrue("No suitable codecs found for mimetype: " + mMime, (mediaCodecs.size() > 0));
for (String codecName : mediaCodecs) {
Native nativeEncoder = new Native();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
index 1e10b37..f223242 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
@@ -5,6 +5,7 @@
import android.media.MediaFormat;
import android.os.Build;
import java.util.ArrayList;
+import java.util.List;
public class CodecUtils {
private CodecUtils() {}
@@ -15,7 +16,7 @@
* @param isEncoder Specifies encoder or decoder
* @return ArrayList of codec names
*/
- public static ArrayList<String> selectCodecs(String mimeType, boolean isEncoder) {
+ public static List<String> selectCodecs(String mimeType, boolean isEncoder) {
MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
ArrayList<String> supportedCodecs = new ArrayList<>();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
index e947ef6..e9b337d 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -28,7 +28,10 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import com.android.media.benchmark.library.IBufferXfer;
@@ -37,28 +40,28 @@
private static final boolean DEBUG = false;
private static final int kQueueDequeueTimeoutUs = 1000;
- private final Object mLock = new Object();
- private MediaCodec mCodec;
- private Surface mSurface = null;
- private boolean mRender = false;
- private ArrayList<BufferInfo> mInputBufferInfo;
- private Stats mStats;
- private String mMime;
+ protected final Object mLock = new Object();
+ protected MediaCodec mCodec;
+ protected Surface mSurface = null;
+ protected boolean mRender = false;
+ protected ArrayList<BufferInfo> mInputBufferInfo;
+ protected Stats mStats;
+ protected String mMime;
- private boolean mSawInputEOS;
- private boolean mSawOutputEOS;
- private boolean mSignalledError;
+ protected boolean mSawInputEOS;
+ protected boolean mSawOutputEOS;
+ protected boolean mSignalledError;
- private int mNumInFramesProvided;
- private int mNumInFramesRequired;
+ protected int mNumInFramesProvided;
+ protected int mNumInFramesRequired;
- private int mNumOutputFrame;
- private int mIndex;
+ protected int mNumOutputFrame;
+ protected int mIndex;
- private ArrayList<ByteBuffer> mInputBuffer;
- private FileOutputStream mOutputStream;
- private FrameReleaseQueue mFrameReleaseQueue = null;
- private IBufferXfer.ISendBuffer mIBufferSend = null;
+ protected ArrayList<ByteBuffer> mInputBuffer;
+ protected FileOutputStream mOutputStream;
+ protected FrameReleaseQueue mFrameReleaseQueue = null;
+ protected IBufferXfer.ISendBuffer mIBufferSend = null;
/* success for decoder */
public static final int DECODE_SUCCESS = 0;
@@ -71,7 +74,9 @@
@Override
public boolean receiveBuffer(IBufferXfer.BufferXferInfo info) {
MediaCodec codec = (MediaCodec)info.obj;
- codec.releaseOutputBuffer(info.idx, mRender);
+ if (info.isComplete) {
+ codec.releaseOutputBuffer(info.idx, mRender);
+ }
return true;
}
@Override
@@ -133,6 +138,49 @@
}
}
+ protected void setCallback(MediaCodec codec) {
+ codec.setCallback(new MediaCodec.Callback() {
+ @Override
+ public void onInputBufferAvailable(
+ @NonNull MediaCodec mediaCodec, int inputBufferId) {
+ try {
+ mStats.addInputTime();
+ onInputAvailable(inputBufferId, mediaCodec);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+ mStats.addOutputTime();
+ onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputFormatChanged(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+ Log.i(TAG, "Output format changed. Format: " + format.toString());
+ }
+
+ @Override
+ public void onError(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+ mSignalledError = true;
+ Log.e(TAG, "Codec Error: " + e.toString());
+ e.printStackTrace();
+ synchronized (mLock) { mLock.notify(); }
+ }
+ });
+
+
+ }
+
/**
* Decodes the given input buffer,
* provided valid list of buffer info and format are passed as inputs.
@@ -146,9 +194,10 @@
* DECODE_CREATE_ERROR for decoder not created
* @throws IOException if the codec cannot be created.
*/
- public int decode(@NonNull ArrayList<ByteBuffer> inputBuffer,
- @NonNull ArrayList<BufferInfo> inputBufferInfo, final boolean asyncMode,
- @NonNull MediaFormat format, String codecName) throws IOException {
+ public int decode(@NonNull List<ByteBuffer> inputBuffer,
+ @NonNull List<BufferInfo> inputBufferInfo, final boolean asyncMode,
+ @NonNull MediaFormat format, String codecName)
+ throws IOException, InterruptedException {
mInputBuffer = new ArrayList<>(inputBuffer.size());
mInputBuffer.addAll(inputBuffer);
mInputBufferInfo = new ArrayList<>(inputBufferInfo.size());
@@ -170,64 +219,34 @@
mFrameReleaseQueue.setMediaCodec(mCodec);
mFrameReleaseQueue.setMime(mMime);
}
+
if (asyncMode) {
- mCodec.setCallback(new MediaCodec.Callback() {
- @Override
- public void onInputBufferAvailable(
- @NonNull MediaCodec mediaCodec, int inputBufferId) {
- try {
- mStats.addInputTime();
- onInputAvailable(inputBufferId, mediaCodec);
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, e.toString());
- }
- }
-
- @Override
- public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
- int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
- mStats.addOutputTime();
- onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
- if (mSawOutputEOS) {
- synchronized (mLock) { mLock.notify(); }
- }
- }
-
- @Override
- public void onOutputFormatChanged(
- @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
- Log.i(TAG, "Output format changed. Format: " + format.toString());
- }
-
- @Override
- public void onError(
- @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
- mSignalledError = true;
- Log.e(TAG, "Codec Error: " + e.toString());
- e.printStackTrace();
- synchronized (mLock) { mLock.notify(); }
- }
- });
+ setCallback(mCodec);
}
int isEncoder = 0;
if (DEBUG) {
Log.d(TAG, "Media Format : " + format.toString());
}
mCodec.configure(format, mSurface, null, isEncoder);
+
mCodec.start();
- Log.i(TAG, "Codec started ");
+ Log.i(TAG, "Codec started async mode ? " + asyncMode);
long eTime = mStats.getCurTime();
mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
mStats.setStartTime();
if (asyncMode) {
try {
- synchronized (mLock) { mLock.wait(); }
- if (mSignalledError) {
- return DECODE_DECODER_ERROR;
+ synchronized (mLock) {
+ while (!mSawOutputEOS && !mSignalledError) {
+ mLock.wait();
+ }
+ if (mSignalledError) {
+ return DECODE_DECODER_ERROR;
+ }
}
} catch (InterruptedException e) {
- e.printStackTrace();
+ Log.e(TAG, "Error in waiting");
+ throw e;
}
} else {
while (!mSawOutputEOS && !mSignalledError) {
@@ -319,7 +338,7 @@
return mCodec.getOutputFormat();
}
- private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
+ protected void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
if (inputBufferId >= 0) {
ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
BufferInfo bufInfo;
@@ -351,7 +370,7 @@
}
}
- private void onOutputAvailable(
+ protected void onOutputAvailable(
MediaCodec mediaCodec, int outputBufferId, BufferInfo outputBufferInfo) {
if (mSawOutputEOS || outputBufferId < 0) {
return;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
index 63d17ee..3aa38d1 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -200,7 +200,8 @@
* @throws IOException If the codec cannot be created.
*/
public int encode(String codecName, MediaFormat encodeFormat, String mime, int frameRate,
- int sampleRate, int frameSize, boolean asyncMode) throws IOException {
+ int sampleRate, int frameSize, boolean asyncMode)
+ throws IOException, InterruptedException {
mInputBufferSize = (mInputStream != null) ? mInputStream.getChannel().size() : 0;
mOffset = 0;
mFrameRate = frameRate;
@@ -275,12 +276,16 @@
mStats.setStartTime();
if (asyncMode) {
try {
- synchronized (mLock) { mLock.wait(); }
- if (mSignalledError) {
- return ENCODE_ENCODER_ERROR;
+ synchronized (mLock) {
+ while (!mSawOutputEOS && !mSignalledError) {
+ mLock.wait();
+ }
+ if (mSignalledError) {
+ return ENCODE_ENCODER_ERROR;
+ }
}
} catch (InterruptedException e) {
- e.printStackTrace();
+ throw e;
}
} else {
while (!mSawOutputEOS && !mSignalledError) {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
index f3024e7..1c0f810 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
@@ -76,6 +76,21 @@
public MediaCodec.BufferInfo getBufferInfo() { return this.mBufferInfo; }
/**
+ * Returns the maximum sample size for the selected track
+ * @return max sample size in the given track
+ */
+ public int getMaxSampleSize() {
+ int size = 0;
+ int maxSampleSize = 0;
+ while ((size = (int) mExtractor.getSampleSize()) != -1) {
+ maxSampleSize = Math.max(maxSampleSize, size);
+ mExtractor.advance();
+ }
+ mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ return maxSampleSize;
+ }
+
+ /**
* Returns the duration of the sample
*/
public long getClipDuration() { return this.mDurationUs; }
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
index 90731ed..20a2573 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
@@ -185,7 +185,7 @@
try {
mCodec.releaseOutputBuffer(curFrameInfo.bufferId, actualRender);
} catch (IllegalStateException e) {
- e.printStackTrace();
+ throw(e);
}
});
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
index a75962c..c97a35c 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
@@ -28,6 +28,7 @@
public Object obj;
int flag;
int bytesRead;
+ boolean isComplete = true;
long presentationTimeUs;
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
index ab55df5..3e6cee1 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
@@ -16,9 +16,9 @@
package com.android.media.benchmark.library;
-/**
+/*
* Class that manages the buffer senders
-*/
+ */
import com.android.media.benchmark.library.IBufferXfer;
import java.util.ArrayDeque;
import android.util.Log;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
new file mode 100644
index 0000000..cb92f06
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media.benchmark.library;
+
+import android.view.Surface;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.android.media.benchmark.library.IBufferXfer;
+import com.android.media.benchmark.library.Decoder;
+
+public class MultiAccessUnitDecoder extends Decoder {
+ private static final String TAG = "MultiAccessUnitDecoder";
+ private static final boolean DEBUG = false;
+ private final ArrayDeque<BufferInfo> mInputInfos = new ArrayDeque<>();
+
+ @Override
+ public void setCallback(MediaCodec codec) {
+ mCodec.setCallback(new MediaCodec.Callback() {
+ boolean isUsingLargeFrameMode = false;
+
+ @Override
+ public void onInputBufferAvailable(
+ @NonNull MediaCodec mediaCodec, int inputBufferId) {
+ try {
+ mStats.addInputTime();
+ if (isUsingLargeFrameMode) {
+ onInputsAvailable(inputBufferId, mediaCodec);
+ } else {
+ onInputAvailable(inputBufferId, mediaCodec);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+ mStats.addOutputTime();
+ onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputBuffersAvailable(
+ @NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull ArrayDeque<BufferInfo> infos) {
+ int i = 0;
+ while(i++ < infos.size()) {
+ mStats.addOutputTime();
+ }
+ onOutputsAvailable(mediaCodec, outputBufferId, infos);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputFormatChanged(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+ Log.i(TAG, "Output format changed. Format: " + format.toString());
+ final int maxOutputSize = format.getNumber(
+ MediaFormat.KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE, 0).intValue();
+ isUsingLargeFrameMode = (maxOutputSize > 0);
+ }
+
+ @Override
+ public void onError(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+ mSignalledError = true;
+ Log.e(TAG, "Codec Error: " + e.toString());
+ e.printStackTrace();
+ synchronized (mLock) { mLock.notify(); }
+ }
+ });
+
+ }
+ /**
+ * Decodes the given input buffer,
+ * provided valid list of buffer info and format are passed as inputs.
+ *
+ * @param inputBuffer Decode the provided list of ByteBuffers
+ * @param inputBufferInfo List of buffer info corresponding to provided input buffers
+ * @param asyncMode Will run on async implementation if true
+ * @param format For creating the decoder if codec name is empty and configuring it
+ * @param codecName Will create the decoder with codecName
+ * @return DECODE_SUCCESS if decode was successful, DECODE_DECODER_ERROR for fail,
+ * DECODE_CREATE_ERROR for decoder not created
+ * @throws IOException if the codec cannot be created.
+ */
+ @Override
+ public int decode(@NonNull List<ByteBuffer> inputBuffer,
+ @NonNull List<BufferInfo> inputBufferInfo, final boolean asyncMode,
+ @NonNull MediaFormat format, String codecName)
+ throws IOException, InterruptedException {
+ return super.decode(inputBuffer, inputBufferInfo, asyncMode, format, codecName);
+ }
+
+ private void onInputsAvailable(int inputBufferId, MediaCodec mediaCodec) {
+ if (inputBufferId >= 0) {
+ ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
+ BufferInfo bufInfo;
+ mInputInfos.clear();
+ int offset = 0;
+ while (mNumInFramesProvided < mNumInFramesRequired) {
+ bufInfo = mInputBufferInfo.get(mIndex);
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ if (inputCodecBuffer.remaining() < bufInfo.size) {
+ if (mInputInfos.size() == 0) {
+ Log.d(TAG, "SampleSize " + inputCodecBuffer.remaining()
+ + "greater than MediaCodec Buffer size " + bufInfo.size);
+ }
+ break;
+ }
+ inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+ bufInfo.offset = offset; offset += bufInfo.size;
+ mInputInfos.add(bufInfo);
+ mNumInFramesProvided++;
+ mIndex = mNumInFramesProvided % (mInputBufferInfo.size() - 1);
+ }
+ if (mNumInFramesProvided >= mNumInFramesRequired) {
+ mIndex = mInputBufferInfo.size() - 1;
+ bufInfo = mInputBufferInfo.get(mIndex);
+ if (inputCodecBuffer.remaining() > bufInfo.size) {
+ if ((bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
+ Log.e(TAG, "Error in EOS flag for Decoder");
+ }
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+ bufInfo.offset = offset; offset += bufInfo.size;
+ mInputInfos.add(bufInfo);
+ mNumInFramesProvided++;
+ }
+ }
+ if (mInputInfos.size() == 0) {
+ Log.d(TAG, " No inputs to queue");
+ } else {
+ mStats.addFrameSize(offset);
+ mediaCodec.queueInputBuffers(inputBufferId, mInputInfos);
+ }
+ }
+ }
+
+ private void onOutputsAvailable(MediaCodec mc, int outputBufferId,
+ ArrayDeque<BufferInfo> infos) {
+ if (mSawOutputEOS || outputBufferId < 0) {
+ return;
+ }
+ Iterator<BufferInfo> iter = infos.iterator();
+ while (iter.hasNext()) {
+ BufferInfo bufferInfo = iter.next();
+ mNumOutputFrame++;
+ if (DEBUG) {
+ Log.d(TAG,
+ "In OutputBufferAvailable ,"
+ + " output frame number = " + mNumOutputFrame
+ + " timestamp = " + bufferInfo.presentationTimeUs
+ + " size = " + bufferInfo.size);
+ }
+ if (mIBufferSend != null) {
+ IBufferXfer.BufferXferInfo info = new IBufferXfer.BufferXferInfo();
+ info.buf = mc.getOutputBuffer(outputBufferId);
+ info.idx = outputBufferId;
+ info.obj = mc;
+ info.bytesRead = bufferInfo.size;
+ info.presentationTimeUs = bufferInfo.presentationTimeUs;
+ info.flag = bufferInfo.flags;
+ info.isComplete = iter.hasNext() ? false : true;
+ mIBufferSend.sendBuffer(this, info);
+ }
+ mSawOutputEOS |= (bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ }
+ if (mOutputStream != null) {
+ try {
+ ByteBuffer outputBuffer = mc.getOutputBuffer(outputBufferId);
+ byte[] bytesOutput = new byte[outputBuffer.remaining()];
+ outputBuffer.get(bytesOutput);
+ mOutputStream.write(bytesOutput);
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+ }
+ }
+ if (mIBufferSend == null) {
+ mc.releaseOutputBuffer(outputBufferId, mRender);
+ }
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Large frame - saw output EOS");
+ }
+ // we don't support frame release queue for large audio frame
+ }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
index 340b539..786290d 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
@@ -23,6 +23,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.List;
public class Muxer {
private Stats mStats;
@@ -61,8 +62,8 @@
* @param inputBufferInfo Buffer information related to these samples
* @return Returns Status as 0 if write operation is successful, -1 otherwise
*/
- public int mux(int trackIndex, ArrayList<ByteBuffer> inputExtractedBuffer,
- ArrayList<MediaCodec.BufferInfo> inputBufferInfo) {
+ public int mux(int trackIndex, List<ByteBuffer> inputExtractedBuffer,
+ List<MediaCodec.BufferInfo> inputBufferInfo) {
mStats.setStartTime();
for (int sampleCount = 0; sampleCount < inputExtractedBuffer.size(); sampleCount++) {
try {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
index 0ebf798..17de1e7 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
@@ -23,6 +23,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.List;
/**
* Measures Performance.
@@ -88,9 +89,9 @@
public long getStartTime() { return mStartTimeNs; }
- public ArrayList<Long> getOutputTimers() { return mOutputTimer; }
+ public List<Long> getOutputTimers() { return mOutputTimer; }
- public ArrayList<Long> getInputTimers() { return mInputTimer; }
+ public List<Long> getInputTimers() { return mInputTimer; }
public long getTimeDiff(long sTime, long eTime) { return (eTime - sTime); }
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0d961bb..3f0bd70 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4065,7 +4065,13 @@
// FIXME could this be made local to while loop?
writeFrames = 0;
- cacheParameters_l();
+ {
+ audio_utils::lock_guard l(mutex());
+
+ cacheParameters_l();
+ checkSilentMode_l();
+ }
+
mSleepTimeUs = mIdleSleepTimeUs;
if (mType == MIXER || mType == SPATIALIZER) {
@@ -4090,8 +4096,6 @@
// suspended mode (for now) to help schedule the wait time until next iteration.
nsecs_t timeLoopNextNs = 0;
- checkSilentMode_l();
-
audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
sendCheckOutputStageEffectsEvent();
@@ -11609,6 +11613,7 @@
void BitPerfectThread::setTracksInternalMute(
std::map<audio_port_handle_t, bool>* tracksInternalMute) {
+ audio_utils::lock_guard _l(mutex());
for (auto& track : mTracks) {
if (auto it = tracksInternalMute->find(track->portId()); it != tracksInternalMute->end()) {
track->setInternalMute(it->second);
@@ -11625,6 +11630,11 @@
// Return the bit perfect track if all other tracks are muted
for (const auto& track : mActiveTracks) {
if (track->isBitPerfect()) {
+ if (track->getInternalMute()) {
+ // There can only be one bit-perfect client active. If it is mute internally,
+ // there is no need to stream bit-perfectly.
+ break;
+ }
bitPerfectTrack = track;
} else if (track->getFinalVolume() != 0.f) {
allOtherTracksMuted = false;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 87b5fd4..574307a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2379,8 +2379,8 @@
// the bit-perfect sink so that it is guaranteed only bit-perfect stream is active.
PortHandleVector clientsToInvalidate;
for (size_t i = 0; i < mOutputs.size(); i++) {
- if (mOutputs[i] == outputDesc ||
- mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty()) {
+ if (mOutputs[i] == outputDesc || (!mOutputs[i]->devices().isEmpty() &&
+ mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty())) {
continue;
}
for (const auto& c : mOutputs[i]->getClientIterable()) {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 4934203..ceb3d30 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -29,6 +29,9 @@
#include "ui/GraphicBufferMapper.h"
#include <cutils/properties.h>
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
namespace android {
@@ -388,6 +391,10 @@
mOldDataSpace == camera_stream::data_space &&
mOldFormat == camera_stream::format) {
mState = STATE_CONFIGURED;
+ if (flags::enable_stream_reconfiguration_for_unchanged_streams()
+ && streamReconfigured != nullptr) {
+ *streamReconfigured = true;
+ }
return OK;
}