Add MediaMetrics support to MediaParser
Includes: - Java changes to collect the metrics. - JNI changes to plumb metrics to the MediaMetrics service. - statsd atoms.proto changes for data transmission. Bug: 158742256 Test: atest CtsMediaParserTestCases Test: atest CtsMediaParserHostTestCases Test: Manually using dumpsys. Change-Id: If51ee018da3056231910cd9c18f1b938a5c0e343 Merged-In: If51ee018da3056231910cd9c18f1b938a5c0e343
This commit is contained in:
@@ -35,7 +35,6 @@ java_library {
|
|||||||
libs: [
|
libs: [
|
||||||
"framework_media_annotation",
|
"framework_media_annotation",
|
||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"exoplayer2-extractor"
|
"exoplayer2-extractor"
|
||||||
],
|
],
|
||||||
@@ -101,10 +100,33 @@ java_sdk_library {
|
|||||||
impl_library_visibility: ["//frameworks/av/apex:__subpackages__"],
|
impl_library_visibility: ["//frameworks/av/apex:__subpackages__"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
java_library {
|
java_library {
|
||||||
name: "framework_media_annotation",
|
name: "framework_media_annotation",
|
||||||
srcs: [":framework-media-annotation-srcs"],
|
srcs: [":framework-media-annotation-srcs"],
|
||||||
installable: false,
|
installable: false,
|
||||||
sdk_version: "core_current",
|
sdk_version: "core_current",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_library_shared {
|
||||||
|
name: "libmediaparser-jni",
|
||||||
|
srcs: [
|
||||||
|
"jni/android_media_MediaParserJNI.cpp",
|
||||||
|
],
|
||||||
|
header_libs: ["jni_headers"],
|
||||||
|
shared_libs: [
|
||||||
|
"libandroid",
|
||||||
|
"liblog",
|
||||||
|
"libmediametrics",
|
||||||
|
],
|
||||||
|
cflags: [
|
||||||
|
"-Wall",
|
||||||
|
"-Werror",
|
||||||
|
"-Wno-unused-parameter",
|
||||||
|
"-Wunreachable-code",
|
||||||
|
"-Wunused",
|
||||||
|
],
|
||||||
|
apex_available: [
|
||||||
|
"com.android.media",
|
||||||
|
],
|
||||||
|
min_sdk_version: "29",
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses media container formats and extracts contained media samples and metadata.
|
* Parses media container formats and extracts contained media samples and metadata.
|
||||||
@@ -882,6 +884,7 @@ public final class MediaParser {
|
|||||||
// Private constants.
|
// Private constants.
|
||||||
|
|
||||||
private static final String TAG = "MediaParser";
|
private static final String TAG = "MediaParser";
|
||||||
|
private static final String JNI_LIBRARY_NAME = "mediaparser-jni";
|
||||||
private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
|
private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
|
||||||
private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
|
private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
|
||||||
private static final String TS_MODE_SINGLE_PMT = "single_pmt";
|
private static final String TS_MODE_SINGLE_PMT = "single_pmt";
|
||||||
@@ -889,6 +892,14 @@ public final class MediaParser {
|
|||||||
private static final String TS_MODE_HLS = "hls";
|
private static final String TS_MODE_HLS = "hls";
|
||||||
private static final int BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY = 6;
|
private static final int BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY = 6;
|
||||||
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
|
||||||
|
private static final String MEDIAMETRICS_ELEMENT_SEPARATOR = "|";
|
||||||
|
private static final int MEDIAMETRICS_MAX_STRING_SIZE = 200;
|
||||||
|
private static final int MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH;
|
||||||
|
/**
|
||||||
|
* Intentional error introduced to reported metrics to prevent identification of the parsed
|
||||||
|
* media. Note: Increasing this value may cause older hostside CTS tests to fail.
|
||||||
|
*/
|
||||||
|
private static final float MEDIAMETRICS_DITHER = .02f;
|
||||||
|
|
||||||
@IntDef(
|
@IntDef(
|
||||||
value = {
|
value = {
|
||||||
@@ -920,7 +931,7 @@ public final class MediaParser {
|
|||||||
@NonNull @ParserName String name, @NonNull OutputConsumer outputConsumer) {
|
@NonNull @ParserName String name, @NonNull OutputConsumer outputConsumer) {
|
||||||
String[] nameAsArray = new String[] {name};
|
String[] nameAsArray = new String[] {name};
|
||||||
assertValidNames(nameAsArray);
|
assertValidNames(nameAsArray);
|
||||||
return new MediaParser(outputConsumer, /* sniff= */ false, name);
|
return new MediaParser(outputConsumer, /* createdByName= */ true, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -940,7 +951,7 @@ public final class MediaParser {
|
|||||||
if (parserNames.length == 0) {
|
if (parserNames.length == 0) {
|
||||||
parserNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
|
parserNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
|
||||||
}
|
}
|
||||||
return new MediaParser(outputConsumer, /* sniff= */ true, parserNames);
|
return new MediaParser(outputConsumer, /* createdByName= */ false, parserNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Misc static methods.
|
// Misc static methods.
|
||||||
@@ -1052,6 +1063,14 @@ public final class MediaParser {
|
|||||||
private long mPendingSeekPosition;
|
private long mPendingSeekPosition;
|
||||||
private long mPendingSeekTimeMicros;
|
private long mPendingSeekTimeMicros;
|
||||||
private boolean mLoggedSchemeInitDataCreationException;
|
private boolean mLoggedSchemeInitDataCreationException;
|
||||||
|
private boolean mReleased;
|
||||||
|
|
||||||
|
// MediaMetrics fields.
|
||||||
|
private final boolean mCreatedByName;
|
||||||
|
private final SparseArray<Format> mTrackFormats;
|
||||||
|
private String mLastObservedExceptionName;
|
||||||
|
private long mDurationMillis;
|
||||||
|
private long mResourceByteCount;
|
||||||
|
|
||||||
// Public methods.
|
// Public methods.
|
||||||
|
|
||||||
@@ -1166,11 +1185,16 @@ public final class MediaParser {
|
|||||||
if (mExtractorInput == null) {
|
if (mExtractorInput == null) {
|
||||||
// TODO: For efficiency, the same implementation should be used, by providing a
|
// TODO: For efficiency, the same implementation should be used, by providing a
|
||||||
// clearBuffers() method, or similar.
|
// clearBuffers() method, or similar.
|
||||||
|
long resourceLength = seekableInputReader.getLength();
|
||||||
|
if (resourceLength == -1) {
|
||||||
|
mResourceByteCount = -1;
|
||||||
|
}
|
||||||
|
if (mResourceByteCount != -1) {
|
||||||
|
mResourceByteCount += resourceLength;
|
||||||
|
}
|
||||||
mExtractorInput =
|
mExtractorInput =
|
||||||
new DefaultExtractorInput(
|
new DefaultExtractorInput(
|
||||||
mExoDataReader,
|
mExoDataReader, seekableInputReader.getPosition(), resourceLength);
|
||||||
seekableInputReader.getPosition(),
|
|
||||||
seekableInputReader.getLength());
|
|
||||||
}
|
}
|
||||||
mExoDataReader.mInputReader = seekableInputReader;
|
mExoDataReader.mInputReader = seekableInputReader;
|
||||||
|
|
||||||
@@ -1195,7 +1219,10 @@ public final class MediaParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mExtractor == null) {
|
if (mExtractor == null) {
|
||||||
throw UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
|
UnrecognizedInputFormatException exception =
|
||||||
|
UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
|
||||||
|
mLastObservedExceptionName = exception.getClass().getName();
|
||||||
|
throw exception;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1223,8 +1250,13 @@ public final class MediaParser {
|
|||||||
int result;
|
int result;
|
||||||
try {
|
try {
|
||||||
result = mExtractor.read(mExtractorInput, mPositionHolder);
|
result = mExtractor.read(mExtractorInput, mPositionHolder);
|
||||||
} catch (ParserException e) {
|
} catch (Exception e) {
|
||||||
throw new ParsingException(e);
|
mLastObservedExceptionName = e.getClass().getName();
|
||||||
|
if (e instanceof ParserException) {
|
||||||
|
throw new ParsingException((ParserException) e);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (result == Extractor.RESULT_END_OF_INPUT) {
|
if (result == Extractor.RESULT_END_OF_INPUT) {
|
||||||
mExtractorInput = null;
|
mExtractorInput = null;
|
||||||
@@ -1264,21 +1296,64 @@ public final class MediaParser {
|
|||||||
* invoked.
|
* invoked.
|
||||||
*/
|
*/
|
||||||
public void release() {
|
public void release() {
|
||||||
// TODO: Dump media metrics here.
|
|
||||||
mExtractorInput = null;
|
mExtractorInput = null;
|
||||||
mExtractor = null;
|
mExtractor = null;
|
||||||
|
if (mReleased) {
|
||||||
|
// Nothing to do.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mReleased = true;
|
||||||
|
|
||||||
|
String trackMimeTypes = buildMediaMetricsString(format -> format.sampleMimeType);
|
||||||
|
String trackCodecs = buildMediaMetricsString(format -> format.codecs);
|
||||||
|
int videoWidth = -1;
|
||||||
|
int videoHeight = -1;
|
||||||
|
for (int i = 0; i < mTrackFormats.size(); i++) {
|
||||||
|
Format format = mTrackFormats.valueAt(i);
|
||||||
|
if (format.width != Format.NO_VALUE && format.height != Format.NO_VALUE) {
|
||||||
|
videoWidth = format.width;
|
||||||
|
videoHeight = format.height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String alteredParameters =
|
||||||
|
String.join(
|
||||||
|
MEDIAMETRICS_ELEMENT_SEPARATOR,
|
||||||
|
mParserParameters.keySet().toArray(new String[0]));
|
||||||
|
alteredParameters =
|
||||||
|
alteredParameters.substring(
|
||||||
|
0,
|
||||||
|
Math.min(
|
||||||
|
alteredParameters.length(),
|
||||||
|
MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH));
|
||||||
|
|
||||||
|
nativeSubmitMetrics(
|
||||||
|
mParserName,
|
||||||
|
mCreatedByName,
|
||||||
|
String.join(MEDIAMETRICS_ELEMENT_SEPARATOR, mParserNamesPool),
|
||||||
|
mLastObservedExceptionName,
|
||||||
|
addDither(mResourceByteCount),
|
||||||
|
addDither(mDurationMillis),
|
||||||
|
trackMimeTypes,
|
||||||
|
trackCodecs,
|
||||||
|
alteredParameters,
|
||||||
|
videoWidth,
|
||||||
|
videoHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private methods.
|
// Private methods.
|
||||||
|
|
||||||
private MediaParser(OutputConsumer outputConsumer, boolean sniff, String... parserNamesPool) {
|
private MediaParser(
|
||||||
|
OutputConsumer outputConsumer, boolean createdByName, String... parserNamesPool) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
throw new UnsupportedOperationException("Android version must be R or greater.");
|
throw new UnsupportedOperationException("Android version must be R or greater.");
|
||||||
}
|
}
|
||||||
mParserParameters = new HashMap<>();
|
mParserParameters = new HashMap<>();
|
||||||
mOutputConsumer = outputConsumer;
|
mOutputConsumer = outputConsumer;
|
||||||
mParserNamesPool = parserNamesPool;
|
mParserNamesPool = parserNamesPool;
|
||||||
mParserName = sniff ? PARSER_NAME_UNKNOWN : parserNamesPool[0];
|
mCreatedByName = createdByName;
|
||||||
|
mParserName = createdByName ? parserNamesPool[0] : PARSER_NAME_UNKNOWN;
|
||||||
mPositionHolder = new PositionHolder();
|
mPositionHolder = new PositionHolder();
|
||||||
mExoDataReader = new InputReadingDataReader();
|
mExoDataReader = new InputReadingDataReader();
|
||||||
removePendingSeek();
|
removePendingSeek();
|
||||||
@@ -1286,6 +1361,24 @@ public final class MediaParser {
|
|||||||
mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
|
mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
|
||||||
mSchemeInitDataConstructor = getSchemeInitDataConstructor();
|
mSchemeInitDataConstructor = getSchemeInitDataConstructor();
|
||||||
mMuxedCaptionFormats = new ArrayList<>();
|
mMuxedCaptionFormats = new ArrayList<>();
|
||||||
|
|
||||||
|
// MediaMetrics.
|
||||||
|
mTrackFormats = new SparseArray<>();
|
||||||
|
mLastObservedExceptionName = "";
|
||||||
|
mDurationMillis = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildMediaMetricsString(Function<Format, String> formatFieldGetter) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < mTrackFormats.size(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
stringBuilder.append(MEDIAMETRICS_ELEMENT_SEPARATOR);
|
||||||
|
}
|
||||||
|
String fieldValue = formatFieldGetter.apply(mTrackFormats.valueAt(i));
|
||||||
|
stringBuilder.append(fieldValue != null ? fieldValue : "");
|
||||||
|
}
|
||||||
|
return stringBuilder.substring(
|
||||||
|
0, Math.min(stringBuilder.length(), MEDIAMETRICS_MAX_STRING_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMuxedCaptionFormats(List<MediaFormat> mediaFormats) {
|
private void setMuxedCaptionFormats(List<MediaFormat> mediaFormats) {
|
||||||
@@ -1528,6 +1621,10 @@ public final class MediaParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
|
public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
|
||||||
|
long durationUs = exoplayerSeekMap.getDurationUs();
|
||||||
|
if (durationUs != C.TIME_UNSET) {
|
||||||
|
mDurationMillis = C.usToMs(durationUs);
|
||||||
|
}
|
||||||
if (mExposeChunkIndexAsMediaFormat && exoplayerSeekMap instanceof ChunkIndex) {
|
if (mExposeChunkIndexAsMediaFormat && exoplayerSeekMap instanceof ChunkIndex) {
|
||||||
ChunkIndex chunkIndex = (ChunkIndex) exoplayerSeekMap;
|
ChunkIndex chunkIndex = (ChunkIndex) exoplayerSeekMap;
|
||||||
MediaFormat mediaFormat = new MediaFormat();
|
MediaFormat mediaFormat = new MediaFormat();
|
||||||
@@ -1575,6 +1672,7 @@ public final class MediaParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void format(Format format) {
|
public void format(Format format) {
|
||||||
|
mTrackFormats.put(mTrackIndex, format);
|
||||||
mOutputConsumer.onTrackDataFound(
|
mOutputConsumer.onTrackDataFound(
|
||||||
mTrackIndex,
|
mTrackIndex,
|
||||||
new TrackData(
|
new TrackData(
|
||||||
@@ -2031,6 +2129,20 @@ public final class MediaParser {
|
|||||||
return new SeekPoint(exoPlayerSeekPoint.timeUs, exoPlayerSeekPoint.position);
|
return new SeekPoint(exoPlayerSeekPoint.timeUs, exoPlayerSeekPoint.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Introduces random error to the given metric value in order to prevent the identification of
|
||||||
|
* the parsed media.
|
||||||
|
*/
|
||||||
|
private static long addDither(long value) {
|
||||||
|
// Generate a random in [0, 1].
|
||||||
|
double randomDither = ThreadLocalRandom.current().nextFloat();
|
||||||
|
// Clamp the random number to [0, 2 * MEDIAMETRICS_DITHER].
|
||||||
|
randomDither *= 2 * MEDIAMETRICS_DITHER;
|
||||||
|
// Translate the random number to [1 - MEDIAMETRICS_DITHER, 1 + MEDIAMETRICS_DITHER].
|
||||||
|
randomDither += 1 - MEDIAMETRICS_DITHER;
|
||||||
|
return value != -1 ? (long) (value * randomDither) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertValidNames(@NonNull String[] names) {
|
private static void assertValidNames(@NonNull String[] names) {
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
if (!EXTRACTOR_FACTORIES_BY_NAME.containsKey(name)) {
|
if (!EXTRACTOR_FACTORIES_BY_NAME.containsKey(name)) {
|
||||||
@@ -2070,9 +2182,26 @@ public final class MediaParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Native methods.
|
||||||
|
|
||||||
|
private native void nativeSubmitMetrics(
|
||||||
|
String parserName,
|
||||||
|
boolean createdByName,
|
||||||
|
String parserPool,
|
||||||
|
String lastObservedExceptionName,
|
||||||
|
long resourceByteCount,
|
||||||
|
long durationMillis,
|
||||||
|
String trackMimeTypes,
|
||||||
|
String trackCodecs,
|
||||||
|
String alteredParameters,
|
||||||
|
int videoWidth,
|
||||||
|
int videoHeight);
|
||||||
|
|
||||||
// Static initialization.
|
// Static initialization.
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
System.loadLibrary(JNI_LIBRARY_NAME);
|
||||||
|
|
||||||
// Using a LinkedHashMap to keep the insertion order when iterating over the keys.
|
// Using a LinkedHashMap to keep the insertion order when iterating over the keys.
|
||||||
LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
|
LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
|
||||||
// Parsers are ordered to match ExoPlayer's DefaultExtractorsFactory extractor ordering,
|
// Parsers are ordered to match ExoPlayer's DefaultExtractorsFactory extractor ordering,
|
||||||
@@ -2125,6 +2254,15 @@ public final class MediaParser {
|
|||||||
// We do not check PARAMETER_EXPOSE_CAPTION_FORMATS here, and we do it in setParameters
|
// We do not check PARAMETER_EXPOSE_CAPTION_FORMATS here, and we do it in setParameters
|
||||||
// instead. Checking that the value is a List is insufficient to catch wrong parameter
|
// instead. Checking that the value is a List is insufficient to catch wrong parameter
|
||||||
// value types.
|
// value types.
|
||||||
|
int sumOfParameterNameLengths =
|
||||||
|
expectedTypeByParameterName.keySet().stream()
|
||||||
|
.map(String::length)
|
||||||
|
.reduce(0, Integer::sum);
|
||||||
|
sumOfParameterNameLengths += PARAMETER_EXPOSE_CAPTION_FORMATS.length();
|
||||||
|
// Add space for any required separators.
|
||||||
|
MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH =
|
||||||
|
sumOfParameterNameLengths + expectedTypeByParameterName.size();
|
||||||
|
|
||||||
EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
|
EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
92
apex/media/framework/jni/android_media_MediaParserJNI.cpp
Normal file
92
apex/media/framework/jni/android_media_MediaParserJNI.cpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include <media/MediaMetrics.h>
|
||||||
|
|
||||||
|
#define JNI_FUNCTION(RETURN_TYPE, NAME, ...) \
|
||||||
|
extern "C" { \
|
||||||
|
JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
|
||||||
|
##__VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
|
||||||
|
##__VA_ARGS__)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr char kMediaMetricsKey[] = "mediaparser";
|
||||||
|
|
||||||
|
constexpr char kAttributeParserName[] = "android.media.mediaparser.parserName";
|
||||||
|
constexpr char kAttributeCreatedByName[] = "android.media.mediaparser.createdByName";
|
||||||
|
constexpr char kAttributeParserPool[] = "android.media.mediaparser.parserPool";
|
||||||
|
constexpr char kAttributeLastException[] = "android.media.mediaparser.lastException";
|
||||||
|
constexpr char kAttributeResourceByteCount[] = "android.media.mediaparser.resourceByteCount";
|
||||||
|
constexpr char kAttributeDurationMillis[] = "android.media.mediaparser.durationMillis";
|
||||||
|
constexpr char kAttributeTrackMimeTypes[] = "android.media.mediaparser.trackMimeTypes";
|
||||||
|
constexpr char kAttributeTrackCodecs[] = "android.media.mediaparser.trackCodecs";
|
||||||
|
constexpr char kAttributeAlteredParameters[] = "android.media.mediaparser.alteredParameters";
|
||||||
|
constexpr char kAttributeVideoWidth[] = "android.media.mediaparser.videoWidth";
|
||||||
|
constexpr char kAttributeVideoHeight[] = "android.media.mediaparser.videoHeight";
|
||||||
|
|
||||||
|
// Util class to handle string resource management.
|
||||||
|
class JstringHandle {
|
||||||
|
public:
|
||||||
|
JstringHandle(JNIEnv* env, jstring value) : mEnv(env), mJstringValue(value) {
|
||||||
|
mCstringValue = env->GetStringUTFChars(value, /* isCopy= */ nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
~JstringHandle() {
|
||||||
|
if (mCstringValue != nullptr) {
|
||||||
|
mEnv->ReleaseStringUTFChars(mJstringValue, mCstringValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char* value() const {
|
||||||
|
return mCstringValue != nullptr ? mCstringValue : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEnv* mEnv;
|
||||||
|
jstring mJstringValue;
|
||||||
|
const char* mCstringValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
JNI_FUNCTION(void, nativeSubmitMetrics, jstring parserNameJstring, jboolean createdByName,
|
||||||
|
jstring parserPoolJstring, jstring lastExceptionJstring, jlong resourceByteCount,
|
||||||
|
jlong durationMillis, jstring trackMimeTypesJstring, jstring trackCodecsJstring,
|
||||||
|
jstring alteredParameters, jint videoWidth, jint videoHeight) {
|
||||||
|
mediametrics_handle_t item(mediametrics_create(kMediaMetricsKey));
|
||||||
|
mediametrics_setCString(item, kAttributeParserName,
|
||||||
|
JstringHandle(env, parserNameJstring).value());
|
||||||
|
mediametrics_setInt32(item, kAttributeCreatedByName, createdByName ? 1 : 0);
|
||||||
|
mediametrics_setCString(item, kAttributeParserPool,
|
||||||
|
JstringHandle(env, parserPoolJstring).value());
|
||||||
|
mediametrics_setCString(item, kAttributeLastException,
|
||||||
|
JstringHandle(env, lastExceptionJstring).value());
|
||||||
|
mediametrics_setInt64(item, kAttributeResourceByteCount, resourceByteCount);
|
||||||
|
mediametrics_setInt64(item, kAttributeDurationMillis, durationMillis);
|
||||||
|
mediametrics_setCString(item, kAttributeTrackMimeTypes,
|
||||||
|
JstringHandle(env, trackMimeTypesJstring).value());
|
||||||
|
mediametrics_setCString(item, kAttributeTrackCodecs,
|
||||||
|
JstringHandle(env, trackCodecsJstring).value());
|
||||||
|
mediametrics_setCString(item, kAttributeAlteredParameters,
|
||||||
|
JstringHandle(env, alteredParameters).value());
|
||||||
|
mediametrics_setInt32(item, kAttributeVideoWidth, videoWidth);
|
||||||
|
mediametrics_setInt32(item, kAttributeVideoHeight, videoHeight);
|
||||||
|
mediametrics_selfRecord(item);
|
||||||
|
mediametrics_delete(item);
|
||||||
|
}
|
||||||
@@ -486,6 +486,8 @@ message Atom {
|
|||||||
303 [(module) = "network_tethering"];
|
303 [(module) = "network_tethering"];
|
||||||
ImeTouchReported ime_touch_reported = 304 [(module) = "sysui"];
|
ImeTouchReported ime_touch_reported = 304 [(module) = "sysui"];
|
||||||
|
|
||||||
|
MediametricsMediaParserReported mediametrics_mediaparser_reported = 316;
|
||||||
|
|
||||||
// StatsdStats tracks platform atoms with ids upto 500.
|
// StatsdStats tracks platform atoms with ids upto 500.
|
||||||
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
|
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
|
||||||
}
|
}
|
||||||
@@ -7918,6 +7920,72 @@ message MediametricsExtractorReported {
|
|||||||
optional android.stats.mediametrics.ExtractorData extractor_data = 5 [(android.os.statsd.log_mode) = MODE_BYTES];
|
optional android.stats.mediametrics.ExtractorData extractor_data = 5 [(android.os.statsd.log_mode) = MODE_BYTES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track MediaParser (parsing video/audio streams from containers) usage
|
||||||
|
* Logged from:
|
||||||
|
*
|
||||||
|
* frameworks/av/services/mediametrics/statsd_mediaparser.cpp
|
||||||
|
* frameworks/base/apex/media/framework/jni/android_media_MediaParserJNI.cpp
|
||||||
|
*/
|
||||||
|
message MediametricsMediaParserReported {
|
||||||
|
optional int64 timestamp_nanos = 1;
|
||||||
|
optional string package_name = 2;
|
||||||
|
optional int64 package_version_code = 3;
|
||||||
|
|
||||||
|
// MediaParser specific data.
|
||||||
|
/**
|
||||||
|
* The name of the parser selected for parsing the media, or an empty string
|
||||||
|
* if no parser was selected.
|
||||||
|
*/
|
||||||
|
optional string parser_name = 4;
|
||||||
|
/**
|
||||||
|
* Whether the parser was created by name. 1 represents true, and 0
|
||||||
|
* represents false.
|
||||||
|
*/
|
||||||
|
optional int32 created_by_name = 5;
|
||||||
|
/**
|
||||||
|
* The parser names in the sniffing pool separated by "|".
|
||||||
|
*/
|
||||||
|
optional string parser_pool = 6;
|
||||||
|
/**
|
||||||
|
* The fully qualified name of the last encountered exception, or an empty
|
||||||
|
* string if no exception was encountered.
|
||||||
|
*/
|
||||||
|
optional string last_exception = 7;
|
||||||
|
/**
|
||||||
|
* The size of the parsed media in bytes, or -1 if unknown. Note this value
|
||||||
|
* contains intentional random error to prevent media content
|
||||||
|
* identification.
|
||||||
|
*/
|
||||||
|
optional int64 resource_byte_count = 8;
|
||||||
|
/**
|
||||||
|
* The duration of the media in milliseconds, or -1 if unknown. Note this
|
||||||
|
* value contains intentional random error to prevent media content
|
||||||
|
* identification.
|
||||||
|
*/
|
||||||
|
optional int64 duration_millis = 9;
|
||||||
|
/**
|
||||||
|
* The MIME types of the tracks separated by "|".
|
||||||
|
*/
|
||||||
|
optional string track_mime_types = 10;
|
||||||
|
/**
|
||||||
|
* The tracks' RFC 6381 codec strings separated by "|".
|
||||||
|
*/
|
||||||
|
optional string track_codecs = 11;
|
||||||
|
/**
|
||||||
|
* Concatenation of the parameters altered by the client, separated by "|".
|
||||||
|
*/
|
||||||
|
optional string altered_parameters = 12;
|
||||||
|
/**
|
||||||
|
* The video width in pixels, or -1 if unknown or not applicable.
|
||||||
|
*/
|
||||||
|
optional int32 video_width = 13;
|
||||||
|
/**
|
||||||
|
* The video height in pixels, or -1 if unknown or not applicable.
|
||||||
|
*/
|
||||||
|
optional int32 video_height = 14;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track how we arbitrate between microphone/input requests.
|
* Track how we arbitrate between microphone/input requests.
|
||||||
* Logged from
|
* Logged from
|
||||||
|
|||||||
Reference in New Issue
Block a user