1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "statsd_codec"
19 #include <utils/Log.h>
20
21 #include <dirent.h>
22 #include <inttypes.h>
23 #include <pthread.h>
24 #include <pwd.h>
25 #include <stdint.h>
26 #include <string>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32
33 #include <stats_media_metrics.h>
34 #include <stats_event.h>
35
36 #include <frameworks/proto_logging/stats/message/mediametrics_message.pb.h>
37 #include <mediametricsservice/cleaner.h>
38 #include <mediametricsservice/iface_statsd.h>
39 #include <mediametricsservice/MediaMetricsService.h>
40 #include <mediametricsservice/StringUtils.h>
41 #include <mediametricsservice/ValidateId.h>
42
43 namespace android {
44
45 using stats::media_metrics::stats_write;
46 using stats::media_metrics::MEDIA_CODEC_RENDERED;
47 using stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_UNKNOWN;
48 using stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_INVALID;
49 using stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO;
50 using stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNKNOWN;
51 using stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNDETERMINED;
52 using stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_24_3_2_PULLDOWN;
53 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_NONE;
54 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HLG;
55 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10;
56 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10_PLUS;
57 using stats::media_metrics::MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_DOLBY_VISION;
58
59 static const int BITRATE_UNKNOWN =
60 stats::media_metrics::MEDIA_CODEC_RENDERED__BITRATE__BITRATE_UNKNOWN;
61
62 static const std::pair<char const *, int> CODEC_LOOKUP[] = {
63 { "avc", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AVC },
64 { "h264", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AVC },
65 { "hevc", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_HEVC },
66 { "h265", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_HEVC },
67 { "vp8", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_VP8 },
68 { "vp9", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_VP9 },
69 { "av1", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AV1 },
70 { "av01", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_AV1 },
71 { "dolby-vision", stats::media_metrics::MEDIA_CODEC_RENDERED__CODEC__CODEC_HEVC },
72 };
73
74 static const int32_t RESOLUTION_LOOKUP[] = {
75 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_MAX_SIZE,
76 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_32K,
77 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_16K,
78 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_8K_UHD,
79 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_8K_UHD_ALMOST,
80 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_4K_UHD_ALMOST,
81 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1440X2560,
82 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080X2400,
83 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080X2340,
84 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080P_FHD,
85 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_1080P_FHD_ALMOST,
86 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_720P_HD,
87 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_720P_HD_ALMOST,
88 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_576X1024,
89 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_540X960,
90 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_480X854,
91 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_480X640,
92 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_360X640,
93 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_352X640,
94 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_VERY_LOW,
95 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_SMALLEST,
96 stats::media_metrics::MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO,
97 };
98
99 static const int32_t FRAMERATE_LOOKUP[] = {
100 stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_24,
101 stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_25,
102 stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_30,
103 stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_50,
104 stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_60,
105 stats::media_metrics::MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_120,
106 };
107
getMetricsCodecEnum(const std::string & mime,const std::string & componentName)108 static int32_t getMetricsCodecEnum(const std::string &mime, const std::string &componentName) {
109 for (const auto & codecStrAndEnum : CODEC_LOOKUP) {
110 if (strcasestr(mime.c_str(), codecStrAndEnum.first) != nullptr ||
111 strcasestr(componentName.c_str(), codecStrAndEnum.first) != nullptr) {
112 return codecStrAndEnum.second;
113 }
114 }
115 return MEDIA_CODEC_RENDERED__CODEC__CODEC_UNKNOWN;
116 }
117
getMetricsResolutionEnum(int32_t width,int32_t height)118 static int32_t getMetricsResolutionEnum(int32_t width, int32_t height) {
119 if (width == 0 || height == 0) {
120 return MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO;
121 }
122 int64_t pixels = int64_t(width) * height / 1000;
123 if (width < 0 || height < 0 || pixels > RESOLUTION_LOOKUP[0]) {
124 return MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_INVALID;
125 }
126 for (int32_t resolutionEnum : RESOLUTION_LOOKUP) {
127 if (pixels > resolutionEnum) {
128 return resolutionEnum;
129 }
130 }
131 return MEDIA_CODEC_RENDERED__RESOLUTION__RESOLUTION_ZERO;
132 }
133
getMetricsFramerateEnum(float inFramerate)134 static int32_t getMetricsFramerateEnum(float inFramerate) {
135 if (inFramerate == -1.0f) {
136 return MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNDETERMINED;
137 }
138 if (inFramerate == -2.0f) {
139 return MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_24_3_2_PULLDOWN;
140 }
141 int framerate = int(inFramerate * 100); // Table is in hundredths of frames per second
142 static const int framerateTolerance = 40; // Tolerance is 0.4 frames per second - table is 100s
143 for (int32_t framerateEnum : FRAMERATE_LOOKUP) {
144 if (abs(framerate - framerateEnum) < framerateTolerance) {
145 return framerateEnum;
146 }
147 }
148 return MEDIA_CODEC_RENDERED__CONTENT_FRAMERATE__FRAMERATE_UNKNOWN;
149 }
150
getMetricsHdrFormatEnum(std::string & mime,std::string & componentName,int32_t configColorTransfer,int32_t parsedColorTransfer,int32_t hdr10StaticInfo,int32_t hdr10PlusInfo)151 static int32_t getMetricsHdrFormatEnum(std::string &mime, std::string &componentName,
152 int32_t configColorTransfer, int32_t parsedColorTransfer,
153 int32_t hdr10StaticInfo, int32_t hdr10PlusInfo) {
154 if (hdr10PlusInfo) {
155 return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10_PLUS;
156 }
157 if (hdr10StaticInfo) {
158 return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HDR10;
159 }
160 // 7 = COLOR_TRANSFER_HLG in MediaCodecConstants.h
161 if (configColorTransfer == 7 || parsedColorTransfer == 7) {
162 return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_HLG;
163 }
164 if (strcasestr(mime.c_str(), "dolby-vision") != nullptr ||
165 strcasestr(componentName.c_str(), "dvhe") != nullptr ||
166 strcasestr(componentName.c_str(), "dvav") != nullptr ||
167 strcasestr(componentName.c_str(), "dav1") != nullptr) {
168 return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_DOLBY_VISION;
169 }
170 return MEDIA_CODEC_RENDERED__HDR_FORMAT__HDR_FORMAT_NONE;
171 }
172
parseVector(const std::string & str,std::vector<int32_t> * vector)173 static void parseVector(const std::string &str, std::vector<int32_t> *vector) {
174 if (!mediametrics::stringutils::parseVector(str, vector)) {
175 ALOGE("failed to parse integer vector from '%s'", str.c_str());
176 }
177 }
178
statsd_codec(const std::shared_ptr<const mediametrics::Item> & item,const std::shared_ptr<mediametrics::StatsdLog> & statsdLog)179 bool statsd_codec(const std::shared_ptr<const mediametrics::Item>& item,
180 const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
181 {
182 if (item == nullptr) return false;
183
184 AStatsEvent* event = AStatsEvent_obtain();
185 AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_CODEC_REPORTED);
186
187 const nsecs_t timestampNanos = MediaMetricsService::roundTime(item->getTimestamp());
188 AStatsEvent_writeInt64(event, timestampNanos);
189
190 // packageName deprecated for calling_uid and statsd support as of U-QPR2
191 std::string packageName = "";
192 AStatsEvent_writeString(event, packageName.c_str());
193
194 // packageVersion depreccated for calling_uid and statsd support as of U-QPR2
195 int64_t packageVersionCode = 0;
196 AStatsEvent_writeInt64(event, packageVersionCode);
197
198 int64_t mediaApexVersion = 0;
199 AStatsEvent_writeInt64(event, mediaApexVersion);
200
201 // the rest into our own proto
202 //
203 ::android::stats::mediametrics_message::CodecData metrics_proto;
204
205 // flesh out the protobuf we'll hand off with our data
206 //
207 std::string codec;
208 if (item->getString("android.media.mediacodec.codec", &codec)) {
209 metrics_proto.set_codec(codec);
210 }
211 AStatsEvent_writeString(event, codec.c_str());
212
213 std::string mime;
214 if (item->getString("android.media.mediacodec.mime", &mime)) {
215 metrics_proto.set_mime(mime);
216 }
217 AStatsEvent_writeString(event, mime.c_str());
218
219 std::string mode;
220 if (item->getString("android.media.mediacodec.mode", &mode)) {
221 metrics_proto.set_mode(mode);
222 }
223 AStatsEvent_writeString(event, mode.c_str());
224
225 int32_t isEncoder = -1;
226 if (item->getInt32("android.media.mediacodec.encoder", &isEncoder)) {
227 metrics_proto.set_encoder(isEncoder);
228 }
229 AStatsEvent_writeInt32(event, isEncoder);
230
231 int32_t isSecure = -1;
232 if (item->getInt32("android.media.mediacodec.secure", &isSecure)) {
233 metrics_proto.set_secure(isSecure);
234 }
235 AStatsEvent_writeInt32(event, isSecure);
236
237 int32_t isHardware = -1;
238 item->getInt32("android.media.mediacodec.hardware", &isHardware);
239 // not logged to MediaCodecReported or MediametricsCodecReported
240
241 int32_t isTunneled = -1;
242 item->getInt32("android.media.mediacodec.tunneled", &isTunneled);
243 // not logged to MediaCodecReported or MediametricsCodecReported
244
245 int32_t width = -1;
246 if (item->getInt32("android.media.mediacodec.width", &width)) {
247 metrics_proto.set_width(width);
248 }
249 AStatsEvent_writeInt32(event, width);
250
251 int32_t height = -1;
252 if (item->getInt32("android.media.mediacodec.height", &height)) {
253 metrics_proto.set_height(height);
254 }
255 AStatsEvent_writeInt32(event, height);
256
257 int32_t rotation = -1;
258 if (item->getInt32("android.media.mediacodec.rotation-degrees", &rotation)) {
259 metrics_proto.set_rotation(rotation);
260 }
261 AStatsEvent_writeInt32(event, rotation);
262
263 int32_t crypto = -1;
264 if (item->getInt32("android.media.mediacodec.crypto", &crypto)) {
265 metrics_proto.set_crypto(crypto);
266 }
267 AStatsEvent_writeInt32(event, crypto);
268
269 int32_t profile = -1;
270 if (item->getInt32("android.media.mediacodec.profile", &profile)) {
271 metrics_proto.set_profile(profile);
272 }
273 AStatsEvent_writeInt32(event, profile);
274
275 int32_t level = -1;
276 if (item->getInt32("android.media.mediacodec.level", &level)) {
277 metrics_proto.set_level(level);
278 }
279 AStatsEvent_writeInt32(event, level);
280
281
282 int32_t maxWidth = -1;
283 if ( item->getInt32("android.media.mediacodec.maxwidth", &maxWidth)) {
284 metrics_proto.set_max_width(maxWidth);
285 }
286 AStatsEvent_writeInt32(event, maxWidth);
287
288 int32_t maxHeight = -1;
289 if ( item->getInt32("android.media.mediacodec.maxheight", &maxHeight)) {
290 metrics_proto.set_max_height(maxHeight);
291 }
292 AStatsEvent_writeInt32(event, maxHeight);
293
294 int32_t errorCode = -1;
295 if ( item->getInt32("android.media.mediacodec.errcode", &errorCode)) {
296 metrics_proto.set_error_code(errorCode);
297 }
298 AStatsEvent_writeInt32(event, errorCode);
299
300 std::string errorState;
301 if ( item->getString("android.media.mediacodec.errstate", &errorState)) {
302 metrics_proto.set_error_state(errorState);
303 }
304 AStatsEvent_writeString(event, errorState.c_str());
305
306 int64_t latencyMax = -1;
307 if (item->getInt64("android.media.mediacodec.latency.max", &latencyMax)) {
308 metrics_proto.set_latency_max(latencyMax);
309 }
310 AStatsEvent_writeInt64(event, latencyMax);
311
312 int64_t latencyMin = -1;
313 if (item->getInt64("android.media.mediacodec.latency.min", &latencyMin)) {
314 metrics_proto.set_latency_min(latencyMin);
315 }
316 AStatsEvent_writeInt64(event, latencyMin);
317
318 int64_t latencyAvg = -1;
319 if (item->getInt64("android.media.mediacodec.latency.avg", &latencyAvg)) {
320 metrics_proto.set_latency_avg(latencyAvg);
321 }
322 AStatsEvent_writeInt64(event, latencyAvg);
323
324 int64_t latencyCount = -1;
325 if (item->getInt64("android.media.mediacodec.latency.n", &latencyCount)) {
326 metrics_proto.set_latency_count(latencyCount);
327 }
328 AStatsEvent_writeInt64(event, latencyCount);
329
330 int64_t latencyUnknown = -1;
331 if (item->getInt64("android.media.mediacodec.latency.unknown", &latencyUnknown)) {
332 metrics_proto.set_latency_unknown(latencyUnknown);
333 }
334 AStatsEvent_writeInt64(event, latencyUnknown);
335
336 int32_t queueSecureInputBufferError = -1;
337 if (item->getInt32("android.media.mediacodec.queueSecureInputBufferError",
338 &queueSecureInputBufferError)) {
339 metrics_proto.set_queue_secure_input_buffer_error(queueSecureInputBufferError);
340 }
341 AStatsEvent_writeInt32(event, queueSecureInputBufferError);
342
343 int32_t queueInputBufferError = -1;
344 if (item->getInt32("android.media.mediacodec.queueInputBufferError", &queueInputBufferError)) {
345 metrics_proto.set_queue_input_buffer_error(queueInputBufferError);
346 }
347 AStatsEvent_writeInt32(event, queueInputBufferError);
348
349 std::string bitrateMode;
350 if (item->getString("android.media.mediacodec.bitrate_mode", &bitrateMode)) {
351 metrics_proto.set_bitrate_mode(bitrateMode);
352 }
353 AStatsEvent_writeString(event, bitrateMode.c_str());
354
355 int32_t bitrate = -1;
356 if (item->getInt32("android.media.mediacodec.bitrate", &bitrate)) {
357 metrics_proto.set_bitrate(bitrate);
358 }
359 AStatsEvent_writeInt32(event, bitrate);
360
361 int64_t lifetimeMillis = -1;
362 if (item->getInt64("android.media.mediacodec.lifetimeMs", &lifetimeMillis)) {
363 lifetimeMillis = mediametrics::bucket_time_minutes(lifetimeMillis);
364 metrics_proto.set_lifetime_millis(lifetimeMillis);
365 }
366 AStatsEvent_writeInt64(event, lifetimeMillis);
367
368 int64_t playbackDurationSec = -1;
369 item->getInt64("android.media.mediacodec.playback-duration-sec", &playbackDurationSec);
370 // DO NOT record playback-duration in the metrics_proto - it should only
371 // exist in the flattened atom
372 AStatsEvent_writeInt64(event, playbackDurationSec);
373
374 std::string sessionId;
375 if (item->getString("android.media.mediacodec.log-session-id", &sessionId)) {
376 sessionId = mediametrics::ValidateId::get()->validateId(sessionId);
377 metrics_proto.set_log_session_id(sessionId);
378 }
379 AStatsEvent_writeString(event, sessionId.c_str());
380
381 int32_t channelCount = -1;
382 if (item->getInt32("android.media.mediacodec.channelCount", &channelCount)) {
383 metrics_proto.set_channel_count(channelCount);
384 }
385 AStatsEvent_writeInt32(event, channelCount);
386
387 int32_t sampleRate = -1;
388 if (item->getInt32("android.media.mediacodec.sampleRate", &sampleRate)) {
389 metrics_proto.set_sample_rate(sampleRate);
390 }
391 AStatsEvent_writeInt32(event, sampleRate);
392
393 // TODO PWG may want these fuzzed up a bit to obscure some precision
394 int64_t bytes = -1;
395 if (item->getInt64("android.media.mediacodec.vencode.bytes", &bytes)) {
396 metrics_proto.set_video_encode_bytes(bytes);
397 }
398 AStatsEvent_writeInt64(event, bytes);
399
400 int64_t frames = -1;
401 if (item->getInt64("android.media.mediacodec.vencode.frames", &frames)) {
402 metrics_proto.set_video_encode_frames(frames);
403 }
404 AStatsEvent_writeInt64(event, frames);
405
406 int64_t inputBytes = -1;
407 if (item->getInt64("android.media.mediacodec.video.input.bytes", &inputBytes)) {
408 metrics_proto.set_video_input_bytes(inputBytes);
409 }
410 AStatsEvent_writeInt64(event, inputBytes);
411
412 int64_t inputFrames = -1;
413 if (item->getInt64("android.media.mediacodec.video.input.frames", &inputFrames)) {
414 metrics_proto.set_video_input_frames(inputFrames);
415 }
416 AStatsEvent_writeInt64(event, inputFrames);
417
418 int64_t durationUs = -1;
419 if (item->getInt64("android.media.mediacodec.vencode.durationUs", &durationUs)) {
420 metrics_proto.set_video_encode_duration_us(durationUs);
421 }
422 AStatsEvent_writeInt64(event, durationUs);
423
424 int32_t colorFormat = -1;
425 if (item->getInt32("android.media.mediacodec.color-format", &colorFormat)) {
426 metrics_proto.set_color_format(colorFormat);
427 }
428 AStatsEvent_writeInt32(event, colorFormat);
429
430 double frameRate = -1.0;
431 if (item->getDouble("android.media.mediacodec.frame-rate", &frameRate)) {
432 metrics_proto.set_frame_rate(frameRate);
433 }
434 AStatsEvent_writeFloat(event, (float) frameRate);
435
436 double captureRate = -1.0;
437 if (item->getDouble("android.media.mediacodec.capture-rate", &captureRate)) {
438 metrics_proto.set_capture_rate(captureRate);
439 }
440 AStatsEvent_writeFloat(event, (float) captureRate);
441
442 double operatingRate = -1.0;
443 if (item->getDouble("android.media.mediacodec.operating-rate", &operatingRate)) {
444 metrics_proto.set_operating_rate(operatingRate);
445 }
446 AStatsEvent_writeFloat(event, (float) operatingRate);
447
448 int32_t priority = -1;
449 if (item->getInt32("android.media.mediacodec.priority", &priority)) {
450 metrics_proto.set_priority(priority);
451 }
452 AStatsEvent_writeInt32(event, priority);
453
454 int32_t qpIMin = -1;
455 if (item->getInt32("android.media.mediacodec.video-qp-i-min", &qpIMin)) {
456 metrics_proto.set_video_qp_i_min(qpIMin);
457 }
458 AStatsEvent_writeInt32(event, qpIMin);
459
460 int32_t qpIMax = -1;
461 if (item->getInt32("android.media.mediacodec.video-qp-i-max", &qpIMax)) {
462 metrics_proto.set_video_qp_i_max(qpIMax);
463 }
464 AStatsEvent_writeInt32(event, qpIMax);
465
466 int32_t qpPMin = -1;
467 if (item->getInt32("android.media.mediacodec.video-qp-p-min", &qpPMin)) {
468 metrics_proto.set_video_qp_p_min(qpPMin);
469 }
470 AStatsEvent_writeInt32(event, qpPMin);
471
472 int32_t qpPMax = -1;
473 if (item->getInt32("android.media.mediacodec.video-qp-p-max", &qpPMax)) {
474 metrics_proto.set_video_qp_p_max(qpPMax);
475 }
476 AStatsEvent_writeInt32(event, qpPMax);
477
478 int32_t qpBMin = -1;
479 if (item->getInt32("android.media.mediacodec.video-qp-b-min", &qpBMin)) {
480 metrics_proto.set_video_qp_b_min(qpBMin);
481 }
482 AStatsEvent_writeInt32(event, qpBMin);
483
484 int32_t qpBMax = -1;
485 if (item->getInt32("android.media.mediacodec.video-qp-b-max", &qpBMax)) {
486 metrics_proto.set_video_qp_b_max(qpBMax);
487 }
488 AStatsEvent_writeInt32(event, qpBMax);
489
490 int32_t originalBitrate = -1;
491 if (item->getInt32("android.media.mediacodec.original.bitrate", &originalBitrate)) {
492 metrics_proto.set_original_bitrate(originalBitrate);
493 }
494 AStatsEvent_writeInt32(event, originalBitrate);
495
496 int32_t shapingEnhanced = -1;
497 if ( item->getInt32("android.media.mediacodec.shaped", &shapingEnhanced)) {
498 metrics_proto.set_shaping_enhanced(shapingEnhanced);
499 }
500 AStatsEvent_writeInt32(event, shapingEnhanced);
501
502 int32_t qpIMinOri = -1;
503 if ( item->getInt32("android.media.mediacodec.original-video-qp-i-min", &qpIMinOri)) {
504 metrics_proto.set_original_video_qp_i_min(qpIMinOri);
505 }
506 AStatsEvent_writeInt32(event, qpIMinOri);
507
508 int32_t qpIMaxOri = -1;
509 if ( item->getInt32("android.media.mediacodec.original-video-qp-i-max", &qpIMaxOri)) {
510 metrics_proto.set_original_video_qp_i_max(qpIMaxOri);
511 }
512 AStatsEvent_writeInt32(event, qpIMaxOri);
513
514 int32_t qpPMinOri = -1;
515 if ( item->getInt32("android.media.mediacodec.original-video-qp-p-min", &qpPMinOri)) {
516 metrics_proto.set_original_video_qp_p_min(qpPMinOri);
517 }
518 AStatsEvent_writeInt32(event, qpPMinOri);
519
520 int32_t qpPMaxOri = -1;
521 if ( item->getInt32("android.media.mediacodec.original-video-qp-p-max", &qpPMaxOri)) {
522 metrics_proto.set_original_video_qp_p_max(qpPMaxOri);
523 }
524 AStatsEvent_writeInt32(event, qpPMaxOri);
525
526 int32_t qpBMinOri = -1;
527 if ( item->getInt32("android.media.mediacodec.original-video-qp-b-min", &qpBMinOri)) {
528 metrics_proto.set_original_video_qp_b_min(qpBMinOri);
529 }
530 AStatsEvent_writeInt32(event, qpBMinOri);
531
532 int32_t qpBMaxOri = -1;
533 if ( item->getInt32("android.media.mediacodec.original-video-qp-b-max", &qpBMaxOri)) {
534 metrics_proto.set_original_video_qp_b_max(qpBMaxOri);
535 }
536 AStatsEvent_writeInt32(event, qpBMaxOri);
537
538 int32_t configColorStandard = -1;
539 if (item->getInt32("android.media.mediacodec.config-color-standard", &configColorStandard)) {
540 metrics_proto.set_config_color_standard(configColorStandard);
541 }
542 AStatsEvent_writeInt32(event, configColorStandard);
543
544 int32_t configColorRange = -1;
545 if (item->getInt32("android.media.mediacodec.config-color-range", &configColorRange)) {
546 metrics_proto.set_config_color_range(configColorRange);
547 }
548 AStatsEvent_writeInt32(event, configColorRange);
549
550 int32_t configColorTransfer = -1;
551 if (item->getInt32("android.media.mediacodec.config-color-transfer", &configColorTransfer)) {
552 metrics_proto.set_config_color_transfer(configColorTransfer);
553 }
554 AStatsEvent_writeInt32(event, configColorTransfer);
555
556 int32_t parsedColorStandard = -1;
557 if (item->getInt32("android.media.mediacodec.parsed-color-standard", &parsedColorStandard)) {
558 metrics_proto.set_parsed_color_standard(parsedColorStandard);
559 }
560 AStatsEvent_writeInt32(event, parsedColorStandard);
561
562 int32_t parsedColorRange = -1;
563 if (item->getInt32("android.media.mediacodec.parsed-color-range", &parsedColorRange)) {
564 metrics_proto.set_parsed_color_range(parsedColorRange);
565 }
566 AStatsEvent_writeInt32(event, parsedColorRange);
567
568 int32_t parsedColorTransfer = -1;
569 if (item->getInt32("android.media.mediacodec.parsed-color-transfer", &parsedColorTransfer)) {
570 metrics_proto.set_parsed_color_transfer(parsedColorTransfer);
571 }
572 AStatsEvent_writeInt32(event, parsedColorTransfer);
573
574 int32_t hdrStaticInfo = -1;
575 if (item->getInt32("android.media.mediacodec.hdr-static-info", &hdrStaticInfo)) {
576 metrics_proto.set_hdr_static_info(hdrStaticInfo);
577 }
578 AStatsEvent_writeInt32(event, hdrStaticInfo);
579
580 int32_t hdr10PlusInfo = -1;
581 if (item->getInt32("android.media.mediacodec.hdr10-plus-info", &hdr10PlusInfo)) {
582 metrics_proto.set_hdr10_plus_info(hdr10PlusInfo);
583 }
584 AStatsEvent_writeInt32(event, hdr10PlusInfo);
585
586 int32_t hdrFormat = -1;
587 if (item->getInt32("android.media.mediacodec.hdr-format", &hdrFormat)) {
588 metrics_proto.set_hdr_format(hdrFormat);
589 }
590 AStatsEvent_writeInt32(event, hdrFormat);
591
592 int64_t codecId = 0;
593 if (item->getInt64("android.media.mediacodec.id", &codecId)) {
594 metrics_proto.set_codec_id(codecId);
595 }
596 AStatsEvent_writeInt64(event, codecId);
597
598 int32_t arrayMode = -1;
599 if (item->getInt32("android.media.mediacodec.array-mode", &arrayMode)) {
600 metrics_proto.set_array_mode(arrayMode);
601 }
602 AStatsEvent_writeInt32(event, arrayMode);
603
604 int32_t operationMode = -1;
605 if (item->getInt32("android.media.mediacodec.operation-mode", &operationMode)) {
606 metrics_proto.set_operation_mode(operationMode);
607 }
608 AStatsEvent_writeInt32(event, operationMode);
609
610 int32_t outputSurface = -1;
611 if (item->getInt32("android.media.mediacodec.output-surface", &outputSurface)) {
612 metrics_proto.set_output_surface(outputSurface);
613 }
614 AStatsEvent_writeInt32(event, outputSurface);
615
616 int32_t appMaxInputSize = -1;
617 if (item->getInt32("android.media.mediacodec.app-max-input-size", &appMaxInputSize)) {
618 metrics_proto.set_app_max_input_size(appMaxInputSize);
619 }
620 AStatsEvent_writeInt32(event, appMaxInputSize);
621
622 int32_t usedMaxInputSize = -1;
623 if (item->getInt32("android.media.mediacodec.used-max-input-size", &usedMaxInputSize)) {
624 metrics_proto.set_used_max_input_size(usedMaxInputSize);
625 }
626 AStatsEvent_writeInt32(event, usedMaxInputSize);
627
628 int32_t codecMaxInputSize = -1;
629 if (item->getInt32("android.media.mediacodec.codec-max-input-size", &codecMaxInputSize)) {
630 metrics_proto.set_codec_max_input_size(codecMaxInputSize);
631 }
632 AStatsEvent_writeInt32(event, codecMaxInputSize);
633
634 int32_t flushCount = -1;
635 if (item->getInt32("android.media.mediacodec.flush-count", &flushCount)) {
636 metrics_proto.set_flush_count(flushCount);
637 }
638 AStatsEvent_writeInt32(event, flushCount);
639
640 int32_t setSurfaceCount = -1;
641 if (item->getInt32("android.media.mediacodec.set-surface-count", &setSurfaceCount)) {
642 metrics_proto.set_set_surface_count(setSurfaceCount);
643 }
644 AStatsEvent_writeInt32(event, setSurfaceCount);
645
646 int32_t resolutionChangeCount = -1;
647 if (item->getInt32("android.media.mediacodec.resolution-change-count",
648 &resolutionChangeCount)) {
649 metrics_proto.set_resolution_change_count(resolutionChangeCount);
650 }
651 AStatsEvent_writeInt32(event, resolutionChangeCount);
652
653 int32_t componentColorFormat = -1;
654 if (item->getInt32("android.media.mediacodec.component-color-format", &componentColorFormat)) {
655 metrics_proto.set_component_color_format(componentColorFormat);
656 }
657 AStatsEvent_writeInt32(event, componentColorFormat);
658
659 uid_t app_uid = item->getUid();
660 metrics_proto.set_caller_uid(app_uid);
661 AStatsEvent_writeInt32(event, app_uid);
662
663 int64_t pixelFormat = -1;
664 if (item->getInt64("android.media.mediacodec.pixel-format", &pixelFormat)) {
665 metrics_proto.set_pixel_format(pixelFormat);
666 }
667 AStatsEvent_writeInt64(event, pixelFormat);
668
669 int64_t firstRenderTimeUs = -1;
670 item->getInt64("android.media.mediacodec.first-render-time-us", &firstRenderTimeUs);
671 int64_t framesReleased = -1;
672 item->getInt64("android.media.mediacodec.frames-released", &framesReleased);
673 int64_t framesRendered = -1;
674 item->getInt64("android.media.mediacodec.frames-rendered", &framesRendered);
675 int64_t framesDropped = -1;
676 item->getInt64("android.media.mediacodec.frames-dropped", &framesDropped);
677 int64_t framesSkipped = -1;
678 item->getInt64("android.media.mediacodec.frames-skipped", &framesSkipped);
679 double framerateContent = -1;
680 item->getDouble("android.media.mediacodec.framerate-content", &framerateContent);
681 double framerateActual = -1;
682 item->getDouble("android.media.mediacodec.framerate-actual", &framerateActual);
683 int64_t freezeScore = -1;
684 item->getInt64("android.media.mediacodec.freeze-score", &freezeScore);
685 double freezeRate = -1;
686 item->getDouble("android.media.mediacodec.freeze-rate", &freezeRate);
687 std::string freezeScoreHistogramStr;
688 item->getString("android.media.mediacodec.freeze-score-histogram", &freezeScoreHistogramStr);
689 std::string freezeScoreHistogramBucketsStr;
690 item->getString("android.media.mediacodec.freeze-score-histogram-buckets",
691 &freezeScoreHistogramBucketsStr);
692 std::string freezeDurationMsHistogramStr;
693 item->getString("android.media.mediacodec.freeze-duration-ms-histogram",
694 &freezeDurationMsHistogramStr);
695 std::string freezeDurationMsHistogramBucketsStr;
696 item->getString("android.media.mediacodec.freeze-duration-ms-histogram-buckets",
697 &freezeDurationMsHistogramBucketsStr);
698 std::string freezeDistanceMsHistogramStr;
699 item->getString("android.media.mediacodec.freeze-distance-ms-histogram",
700 &freezeDistanceMsHistogramStr);
701 std::string freezeDistanceMsHistogramBucketsStr;
702 item->getString("android.media.mediacodec.freeze-distance-ms-histogram-buckets",
703 &freezeDistanceMsHistogramBucketsStr);
704 int64_t judderScore = -1;
705 item->getInt64("android.media.mediacodec.judder-score", &judderScore);
706 double judderRate = -1;
707 item->getDouble("android.media.mediacodec.judder-rate", &judderRate);
708 std::string judderScoreHistogramStr;
709 item->getString("android.media.mediacodec.judder-score-histogram", &judderScoreHistogramStr);
710 std::string judderScoreHistogramBucketsStr;
711 item->getString("android.media.mediacodec.judder-score-histogram-buckets",
712 &judderScoreHistogramBucketsStr);
713
714 int err = AStatsEvent_write(event);
715 if (err < 0) {
716 ALOGE("Failed to write codec metrics to statsd (%d)", err);
717 }
718 AStatsEvent_release(event);
719
720 if (framesRendered > 0) {
721 int32_t statsUid = item->getUid();
722 int64_t statsCodecId = codecId;
723 char const *statsLogSessionId = sessionId.c_str();
724 int32_t statsIsHardware = isHardware;
725 int32_t statsIsSecure = isSecure;
726 int32_t statsIsTunneled = isTunneled;
727 int32_t statsCodec = getMetricsCodecEnum(mime, codec);
728 int32_t statsResolution = getMetricsResolutionEnum(width, height);
729 int32_t statsBitrate = BITRATE_UNKNOWN;
730 int32_t statsContentFramerate = getMetricsFramerateEnum(framerateContent);
731 int32_t statsActualFramerate = getMetricsFramerateEnum(framerateActual);
732 int32_t statsHdrFormat = getMetricsHdrFormatEnum(mime, codec, configColorTransfer,
733 parsedColorTransfer, hdrStaticInfo,
734 hdr10PlusInfo);
735 int64_t statsFirstRenderTimeUs = firstRenderTimeUs;
736 int64_t statsPlaybackDurationSeconds = playbackDurationSec;
737 int64_t statsFramesTotal = framesReleased + framesSkipped;
738 int64_t statsFramesReleased = framesReleased;
739 int64_t statsFramesRendered = framesRendered;
740 int64_t statsFramesDropped = framesDropped;
741 int64_t statsFramesSkipped = framesSkipped;
742 float statsFrameDropRate = float(double(framesDropped) / statsFramesTotal);
743 float statsFrameSkipRate = float(double(framesSkipped) / statsFramesTotal);
744 float statsFrameSkipDropRate = float(double(framesSkipped + framesDropped) /
745 statsFramesTotal);
746 int64_t statsFreezeScore = freezeScore;
747 float statsFreezeRate = freezeRate;
748 std::vector<int32_t> statsFreezeDurationMsHistogram;
749 parseVector(freezeDurationMsHistogramStr, &statsFreezeDurationMsHistogram);
750 std::vector<int32_t> statsFreezeDurationMsHistogramBuckets;
751 parseVector(freezeDurationMsHistogramBucketsStr, &statsFreezeDurationMsHistogramBuckets);
752 std::vector<int32_t> statsFreezeDistanceMsHistogram;
753 parseVector(freezeDistanceMsHistogramStr, &statsFreezeDistanceMsHistogram);
754 std::vector<int32_t> statsFreezeDistanceMsHistogramBuckets;
755 parseVector(freezeDistanceMsHistogramBucketsStr, &statsFreezeDistanceMsHistogramBuckets);
756 int64_t statsJudderScore = judderScore;
757 float statsJudderRate = judderRate;
758 std::vector<int32_t> statsJudderScoreHistogram;
759 parseVector(judderScoreHistogramStr, &statsJudderScoreHistogram);
760 std::vector<int32_t> statsJudderScoreHistogramBuckets;
761 parseVector(judderScoreHistogramBucketsStr, &statsJudderScoreHistogramBuckets);
762 int result = stats_write(
763 MEDIA_CODEC_RENDERED,
764 statsUid,
765 statsCodecId,
766 statsLogSessionId,
767 statsIsHardware,
768 statsIsSecure,
769 statsIsTunneled,
770 statsCodec,
771 statsResolution,
772 statsBitrate,
773 statsContentFramerate,
774 statsActualFramerate,
775 statsHdrFormat,
776 statsFirstRenderTimeUs,
777 statsPlaybackDurationSeconds,
778 statsFramesTotal,
779 statsFramesReleased,
780 statsFramesRendered,
781 statsFramesDropped,
782 statsFramesSkipped,
783 statsFrameDropRate,
784 statsFrameSkipRate,
785 statsFrameSkipDropRate,
786 statsFreezeScore,
787 statsFreezeRate,
788 statsFreezeDurationMsHistogram,
789 statsFreezeDurationMsHistogramBuckets,
790 statsFreezeDistanceMsHistogram,
791 statsFreezeDistanceMsHistogramBuckets,
792 statsJudderScore,
793 statsJudderRate,
794 statsJudderScoreHistogram,
795 statsJudderScoreHistogramBuckets);
796 ALOGE_IF(result < 0, "Failed to record MEDIA_CODEC_RENDERED atom (%d)", result);
797 }
798
799 std::string serialized;
800 if (!metrics_proto.SerializeToString(&serialized)) {
801 ALOGE("Failed to serialize codec metrics");
802 return false;
803 }
804 const stats::media_metrics::BytesField bf_serialized(serialized.c_str(), serialized.size());
805 const int result = stats::media_metrics::stats_write(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED,
806 timestampNanos, packageName.c_str(), packageVersionCode,
807 mediaApexVersion,
808 bf_serialized);
809
810 std::stringstream log;
811 log << "result:" << result << " {"
812 << " mediametrics_codec_reported:"
813 << stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED
814 << " timestamp_nanos:" << timestampNanos
815 << " package_name:" << packageName
816 << " package_version_code:" << packageVersionCode
817 << " media_apex_version:" << mediaApexVersion
818 << " codec:" << codec
819 << " mime:" << mime
820 << " mode:" << mode
821 << " encoder:" << isEncoder
822 << " secure:" << isSecure
823 << " width:" << width
824 << " height:" << height
825 << " rotation:" << rotation
826 << " crypto:" << crypto
827 << " profile:" << profile
828 << " level:" << level
829 << " max_width:" << maxWidth
830 << " max_height:" << maxHeight
831 << " error_code:" << errorCode
832 << " error_state:" << errorState
833 << " latency_max:" << latencyMax
834 << " latency_min:" << latencyMin
835 << " latency_avg:" << latencyAvg
836 << " latency_count:" << latencyCount
837 << " latency_unknown:" << latencyUnknown
838 << " queue_input_buffer_error:" << queueInputBufferError
839 << " queue_secure_input_buffer_error:" << queueSecureInputBufferError
840 << " bitrate_mode:" << bitrateMode
841 << " bitrate:" << bitrate
842 << " original_bitrate:" << originalBitrate
843 << " lifetime_millis:" << lifetimeMillis
844 << " playback_duration_seconds:" << playbackDurationSec
845 << " log_session_id:" << sessionId
846 << " channel_count:" << channelCount
847 << " sample_rate:" << sampleRate
848 << " encode_bytes:" << bytes
849 << " encode_frames:" << frames
850 << " encode_duration_us:" << durationUs
851 << " color_format:" << colorFormat
852 << " frame_rate:" << frameRate
853 << " capture_rate:" << captureRate
854 << " operating_rate:" << operatingRate
855 << " priority:" << priority
856 << " shaping_enhanced:" << shapingEnhanced
857 << " qp_i_min:" << qpIMin
858 << " qp_i_max:" << qpIMax
859 << " qp_p_min:" << qpPMin
860 << " qp_p_max:" << qpPMax
861 << " qp_b_min:" << qpBMin
862 << " qp_b_max:" << qpBMax
863 << " original_qp_i_min:" << qpIMinOri
864 << " original_qp_i_max:" << qpIMaxOri
865 << " original_qp_p_min:" << qpPMinOri
866 << " original_qp_p_max:" << qpPMaxOri
867 << " original_qp_b_min:" << qpBMinOri
868 << " original_qp_b_max:" << qpBMaxOri
869 << " app_uid:" << app_uid
870 << " }";
871 statsdLog->log(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED, log.str());
872
873
874 return true;
875 }
876
877 } // namespace android
878