[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / watch_time_recorder_unittest.cc
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/mojo/services/watch_time_recorder.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/containers/contains.h"
14 #include "base/functional/bind.h"
15 #include "base/functional/callback_helpers.h"
16 #include "base/hash/hash.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h"
20 #include "base/test/metrics/histogram_tester.h"
21 #include "base/test/task_environment.h"
22 #include "base/test/test_message_loop.h"
23 #include "base/time/time.h"
24 #include "components/ukm/test_ukm_recorder.h"
25 #include "media/base/video_codecs.h"
26 #include "media/base/watch_time_keys.h"
27 #include "media/mojo/services/media_metrics_provider.h"
28 #include "mojo/public/cpp/bindings/remote.h"
29 #include "services/metrics/public/cpp/ukm_builders.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "url/gurl.h"
33
34 using UkmEntry = ukm::builders::Media_BasicPlayback;
35
36 namespace content {
37 class RenderFrameHostDelegate;
38 }  // namespace content
39
40 namespace media {
41
42 constexpr char kTestOrigin[] = "https://test.google.com/";
43
44 class WatchTimeRecorderTest : public testing::Test {
45  public:
46   WatchTimeRecorderTest()
47       : computation_keys_(
48             {WatchTimeKey::kAudioSrc, WatchTimeKey::kAudioMse,
49              WatchTimeKey::kAudioEme, WatchTimeKey::kAudioVideoSrc,
50              WatchTimeKey::kAudioVideoMse, WatchTimeKey::kAudioVideoEme}),
51         mtbr_keys_({kMeanTimeBetweenRebuffersAudioSrc,
52                     kMeanTimeBetweenRebuffersAudioMse,
53                     kMeanTimeBetweenRebuffersAudioEme,
54                     kMeanTimeBetweenRebuffersAudioVideoSrc,
55                     kMeanTimeBetweenRebuffersAudioVideoMse,
56                     kMeanTimeBetweenRebuffersAudioVideoEme}),
57         smooth_keys_({kRebuffersCountAudioSrc, kRebuffersCountAudioMse,
58                       kRebuffersCountAudioEme, kRebuffersCountAudioVideoSrc,
59                       kRebuffersCountAudioVideoMse,
60                       kRebuffersCountAudioVideoEme}),
61         discard_keys_({kDiscardedWatchTimeAudioSrc, kDiscardedWatchTimeAudioMse,
62                        kDiscardedWatchTimeAudioEme,
63                        kDiscardedWatchTimeAudioVideoSrc,
64                        kDiscardedWatchTimeAudioVideoMse,
65                        kDiscardedWatchTimeAudioVideoEme}) {
66     source_id_ = test_recorder_->GetNewSourceID();
67     ResetMetricRecorders();
68     MediaMetricsProvider::Create(
69         MediaMetricsProvider::BrowsingMode::kIncognito,
70         MediaMetricsProvider::FrameStatus::kTopFrame, GetSourceId(),
71         learning::FeatureValue(0), VideoDecodePerfHistory::SaveCallback(),
72         MediaMetricsProvider::GetLearningSessionCallback(),
73         base::BindRepeating(
74             &WatchTimeRecorderTest::GetRecordAggregateWatchTimeCallback,
75             base::Unretained(this)),
76         base::BindRepeating(&WatchTimeRecorderTest::IsShuttingDown,
77                             base::Unretained(this)),
78         provider_.BindNewPipeAndPassReceiver());
79   }
80
81   WatchTimeRecorderTest(const WatchTimeRecorderTest&) = delete;
82   WatchTimeRecorderTest& operator=(const WatchTimeRecorderTest&) = delete;
83
84   ~WatchTimeRecorderTest() override { base::RunLoop().RunUntilIdle(); }
85
86   void Initialize(mojom::PlaybackPropertiesPtr properties) {
87     provider_->Initialize(properties->is_mse,
88                           properties->is_mse ? mojom::MediaURLScheme::kUnknown
89                                              : mojom::MediaURLScheme::kHttp,
90                           properties->media_stream_type);
91     provider_->AcquireWatchTimeRecorder(std::move(properties),
92                                         wtr_.BindNewPipeAndPassReceiver());
93   }
94
95   void Initialize(
96       bool has_audio,
97       bool has_video,
98       bool is_mse,
99       bool is_encrypted,
100       mojom::MediaStreamType media_stream_type = mojom::MediaStreamType::kNone,
101       RendererType renderer_type = RendererType::kRendererImpl) {
102     Initialize(mojom::PlaybackProperties::New(
103         has_audio, has_video, false, false, is_mse, is_encrypted, false,
104         media_stream_type, renderer_type));
105   }
106
107   void ExpectWatchTime(const std::vector<base::StringPiece>& keys,
108                        base::TimeDelta value) {
109     for (int i = 0; i <= static_cast<int>(WatchTimeKey::kWatchTimeKeyMax);
110          ++i) {
111       const base::StringPiece test_key =
112           ConvertWatchTimeKeyToStringForUma(static_cast<WatchTimeKey>(i));
113       if (test_key.empty())
114         continue;
115       if (base::Contains(keys, test_key)) {
116         histogram_tester_->ExpectUniqueSample(test_key, value.InMilliseconds(),
117                                               1);
118       } else {
119         histogram_tester_->ExpectTotalCount(test_key, 0);
120       }
121     }
122   }
123
124   void ExpectHelper(const std::vector<base::StringPiece>& full_key_list,
125                     const std::vector<base::StringPiece>& keys,
126                     int64_t value) {
127     for (auto key : full_key_list) {
128       if (base::Contains(keys, key))
129         histogram_tester_->ExpectUniqueSample(key, value, 1);
130       else
131         histogram_tester_->ExpectTotalCount(key, 0);
132     }
133   }
134
135   void ExpectMtbrTime(const std::vector<base::StringPiece>& keys,
136                       base::TimeDelta value) {
137     ExpectHelper(mtbr_keys_, keys, value.InMilliseconds());
138   }
139
140   void ExpectZeroRebuffers(const std::vector<base::StringPiece>& keys) {
141     ExpectHelper(smooth_keys_, keys, 0);
142   }
143
144   void ExpectRebuffers(const std::vector<base::StringPiece>& keys, int count) {
145     ExpectHelper(smooth_keys_, keys, count);
146   }
147
148   void ExpectAacAudioCodecProfileHistogram(AudioCodecProfile profile) {
149     constexpr char kAudioCodecProfileHistogram[] =
150         "Media.AudioCodecProfile.AAC";
151     histogram_tester_->ExpectUniqueSample(kAudioCodecProfileHistogram,
152                                           static_cast<int64_t>(profile), 1);
153   }
154
155   void ExpectNoUkmWatchTime() {
156     // We always add a source in testing.
157     ASSERT_EQ(1u, test_recorder_->sources_count());
158     ASSERT_EQ(0u, test_recorder_->entries_count());
159   }
160
161   void ExpectUkmWatchTime(const std::vector<base::StringPiece>& keys,
162                           base::TimeDelta value) {
163     const auto& entries =
164         test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
165     EXPECT_EQ(1u, entries.size());
166     for (const auto* entry : entries) {
167       test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
168       for (auto key : keys) {
169         test_recorder_->ExpectEntryMetric(entry, key.data(),
170                                           value.InMilliseconds());
171       }
172     }
173   }
174
175   void ResetMetricRecorders() {
176     histogram_tester_ = std::make_unique<base::HistogramTester>();
177     // Ensure cleared global before attempting to create a new TestUkmReporter.
178     test_recorder_.reset();
179     test_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
180     test_recorder_->UpdateSourceURL(source_id_, GURL(kTestOrigin));
181   }
182
183   mojom::SecondaryPlaybackPropertiesPtr CreateSecondaryProperties() {
184     return mojom::SecondaryPlaybackProperties::New(
185         AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kUnknown,
186         H264PROFILE_MAIN, AudioDecoderType::kUnknown,
187         VideoDecoderType::kUnknown, EncryptionScheme::kUnencrypted,
188         EncryptionScheme::kUnencrypted, gfx::Size(800, 600));
189   }
190
191   ukm::SourceId GetSourceId() { return source_id_; }
192
193   MediaMetricsProvider::RecordAggregateWatchTimeCallback
194   GetRecordAggregateWatchTimeCallback() {
195     return base::BindRepeating(
196         [](base::WeakPtr<content::RenderFrameHostDelegate> delegate,
197            GURL last_committed_url, base::TimeDelta total_watch_time,
198            base::TimeDelta time_stamp, bool has_video, bool has_audio) {
199           // Do nothing as this mock callback will never be called.
200         },
201         nullptr, GURL());
202   }
203
204   MOCK_METHOD(bool, IsShuttingDown, ());
205   MOCK_METHOD0(GetCurrentMediaTime, base::TimeDelta());
206
207  protected:
208   base::test::SingleThreadTaskEnvironment task_environment_;
209   mojo::Remote<mojom::MediaMetricsProvider> provider_;
210   std::unique_ptr<base::HistogramTester> histogram_tester_;
211   std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_recorder_;
212   ukm::SourceId source_id_;
213   mojo::Remote<mojom::WatchTimeRecorder> wtr_;
214   const std::vector<WatchTimeKey> computation_keys_;
215   const std::vector<base::StringPiece> mtbr_keys_;
216   const std::vector<base::StringPiece> smooth_keys_;
217   const std::vector<base::StringPiece> discard_keys_;
218 };
219
220 TEST_F(WatchTimeRecorderTest, TestBasicReporting) {
221   constexpr base::TimeDelta kWatchTime1 = base::Seconds(25);
222   constexpr base::TimeDelta kWatchTime2 = base::Seconds(50);
223
224   for (int i = 0; i <= static_cast<int>(WatchTimeKey::kWatchTimeKeyMax); ++i) {
225     const WatchTimeKey key = static_cast<WatchTimeKey>(i);
226
227     auto key_str = ConvertWatchTimeKeyToStringForUma(key);
228     SCOPED_TRACE(key_str.empty() ? base::NumberToString(i)
229                                  : std::string(key_str));
230
231     // Values for |is_background| and |is_muted| don't matter in this test since
232     // they don't prevent the muted or background keys from being recorded.
233     Initialize(true, false, true, true);
234     wtr_->UpdateSecondaryProperties(CreateSecondaryProperties());
235
236     wtr_->RecordWatchTime(WatchTimeKey::kWatchTimeKeyMax, kWatchTime1);
237     wtr_->RecordWatchTime(key, kWatchTime1);
238     wtr_->RecordWatchTime(key, kWatchTime2);
239     base::RunLoop().RunUntilIdle();
240
241     // Nothing should be recorded yet since we haven't finalized.
242     ExpectWatchTime({}, base::TimeDelta());
243
244     // Only the requested key should be finalized.
245     wtr_->FinalizeWatchTime({key});
246     base::RunLoop().RunUntilIdle();
247
248     if (!key_str.empty())
249       ExpectWatchTime({key_str}, kWatchTime2);
250
251     // These keys are only reported for a full finalize.
252     ExpectMtbrTime({}, base::TimeDelta());
253     ExpectZeroRebuffers({});
254     ExpectNoUkmWatchTime();
255
256     // Verify nothing else is recorded except for what we finalized above.
257     ResetMetricRecorders();
258     wtr_.reset();
259     base::RunLoop().RunUntilIdle();
260     ExpectWatchTime({}, base::TimeDelta());
261     ExpectMtbrTime({}, base::TimeDelta());
262     ExpectZeroRebuffers({});
263
264     switch (key) {
265       case WatchTimeKey::kAudioAll:
266       case WatchTimeKey::kAudioBackgroundAll:
267       case WatchTimeKey::kAudioVideoAll:
268       case WatchTimeKey::kAudioVideoBackgroundAll:
269       case WatchTimeKey::kAudioVideoMutedAll:
270       case WatchTimeKey::kVideoAll:
271       case WatchTimeKey::kVideoBackgroundAll:
272         ExpectUkmWatchTime({UkmEntry::kWatchTimeName}, kWatchTime2);
273         break;
274
275       // These keys are not reported, instead we boolean flags for each type.
276       case WatchTimeKey::kAudioMse:
277       case WatchTimeKey::kAudioEme:
278       case WatchTimeKey::kAudioSrc:
279       case WatchTimeKey::kAudioEmbeddedExperience:
280       case WatchTimeKey::kAudioBackgroundMse:
281       case WatchTimeKey::kAudioBackgroundEme:
282       case WatchTimeKey::kAudioBackgroundSrc:
283       case WatchTimeKey::kAudioBackgroundEmbeddedExperience:
284       case WatchTimeKey::kAudioVideoMse:
285       case WatchTimeKey::kAudioVideoEme:
286       case WatchTimeKey::kAudioVideoSrc:
287       case WatchTimeKey::kAudioVideoEmbeddedExperience:
288       case WatchTimeKey::kAudioVideoMutedMse:
289       case WatchTimeKey::kAudioVideoMutedEme:
290       case WatchTimeKey::kAudioVideoMutedSrc:
291       case WatchTimeKey::kAudioVideoMutedEmbeddedExperience:
292       case WatchTimeKey::kAudioVideoBackgroundMse:
293       case WatchTimeKey::kAudioVideoBackgroundEme:
294       case WatchTimeKey::kAudioVideoBackgroundSrc:
295       case WatchTimeKey::kAudioVideoBackgroundEmbeddedExperience:
296       case WatchTimeKey::kVideoMse:
297       case WatchTimeKey::kVideoEme:
298       case WatchTimeKey::kVideoSrc:
299       case WatchTimeKey::kVideoEmbeddedExperience:
300       case WatchTimeKey::kVideoBackgroundMse:
301       case WatchTimeKey::kVideoBackgroundEme:
302       case WatchTimeKey::kVideoBackgroundSrc:
303       case WatchTimeKey::kVideoBackgroundEmbeddedExperience:
304       case WatchTimeKey::kAudioVideoMediaFoundationAll:
305       case WatchTimeKey::kAudioVideoMediaFoundationEme:
306         ExpectUkmWatchTime({}, base::TimeDelta());
307         break;
308
309       // These keys roll up into the battery watch time field.
310       case WatchTimeKey::kAudioBattery:
311       case WatchTimeKey::kAudioBackgroundBattery:
312       case WatchTimeKey::kAudioVideoBattery:
313       case WatchTimeKey::kAudioVideoMutedBattery:
314       case WatchTimeKey::kAudioVideoBackgroundBattery:
315       case WatchTimeKey::kVideoBattery:
316       case WatchTimeKey::kVideoBackgroundBattery:
317         ExpectUkmWatchTime({UkmEntry::kWatchTime_BatteryName}, kWatchTime2);
318         break;
319
320       // These keys roll up into the AC watch time field.
321       case WatchTimeKey::kAudioAc:
322       case WatchTimeKey::kAudioBackgroundAc:
323       case WatchTimeKey::kAudioVideoAc:
324       case WatchTimeKey::kAudioVideoBackgroundAc:
325       case WatchTimeKey::kAudioVideoMutedAc:
326       case WatchTimeKey::kVideoAc:
327       case WatchTimeKey::kVideoBackgroundAc:
328         ExpectUkmWatchTime({UkmEntry::kWatchTime_ACName}, kWatchTime2);
329         break;
330
331       case WatchTimeKey::kAudioVideoDisplayFullscreen:
332       case WatchTimeKey::kAudioVideoMutedDisplayFullscreen:
333       case WatchTimeKey::kVideoDisplayFullscreen:
334         ExpectUkmWatchTime({UkmEntry::kWatchTime_DisplayFullscreenName},
335                            kWatchTime2);
336         break;
337
338       case WatchTimeKey::kAudioVideoDisplayInline:
339       case WatchTimeKey::kAudioVideoMutedDisplayInline:
340       case WatchTimeKey::kVideoDisplayInline:
341         ExpectUkmWatchTime({UkmEntry::kWatchTime_DisplayInlineName},
342                            kWatchTime2);
343         break;
344
345       case WatchTimeKey::kAudioVideoDisplayPictureInPicture:
346       case WatchTimeKey::kAudioVideoMutedDisplayPictureInPicture:
347       case WatchTimeKey::kVideoDisplayPictureInPicture:
348         ExpectUkmWatchTime({UkmEntry::kWatchTime_DisplayPictureInPictureName},
349                            kWatchTime2);
350         break;
351
352       case WatchTimeKey::kAudioNativeControlsOn:
353       case WatchTimeKey::kAudioVideoNativeControlsOn:
354       case WatchTimeKey::kAudioVideoMutedNativeControlsOn:
355       case WatchTimeKey::kVideoNativeControlsOn:
356         ExpectUkmWatchTime({UkmEntry::kWatchTime_NativeControlsOnName},
357                            kWatchTime2);
358         break;
359
360       case WatchTimeKey::kAudioNativeControlsOff:
361       case WatchTimeKey::kAudioVideoNativeControlsOff:
362       case WatchTimeKey::kAudioVideoMutedNativeControlsOff:
363       case WatchTimeKey::kVideoNativeControlsOff:
364         ExpectUkmWatchTime({UkmEntry::kWatchTime_NativeControlsOffName},
365                            kWatchTime2);
366         break;
367     }
368
369     ResetMetricRecorders();
370   }
371 }
372
373 TEST_F(WatchTimeRecorderTest, TestBasicReportingMediaStream) {
374   constexpr base::TimeDelta kWatchTime1 = base::Seconds(25);
375   constexpr base::TimeDelta kWatchTime2 = base::Seconds(50);
376
377   for (int i = 0; i <= static_cast<int>(WatchTimeKey::kWatchTimeKeyMax); ++i) {
378     const WatchTimeKey key = static_cast<WatchTimeKey>(i);
379
380     auto key_str = ConvertWatchTimeKeyToStringForUma(key);
381     SCOPED_TRACE(key_str.empty() ? base::NumberToString(i)
382                                  : std::string(key_str));
383
384     // Values for |is_background| and |is_muted| don't matter in this test since
385     // they don't prevent the muted or background keys from being recorded.
386     Initialize(true, false, true, true,
387                mojom::MediaStreamType::kLocalDeviceCapture);
388     wtr_->UpdateSecondaryProperties(CreateSecondaryProperties());
389
390     wtr_->RecordWatchTime(WatchTimeKey::kWatchTimeKeyMax, kWatchTime1);
391     wtr_->RecordWatchTime(key, kWatchTime1);
392     wtr_->RecordWatchTime(key, kWatchTime2);
393     base::RunLoop().RunUntilIdle();
394
395     // Nothing should be recorded yet since we haven't finalized.
396     ExpectWatchTime({}, base::TimeDelta());
397
398     // Only the requested key should be finalized.
399     wtr_->FinalizeWatchTime({key});
400     base::RunLoop().RunUntilIdle();
401
402     if (!key_str.empty())
403       ExpectWatchTime({}, base::TimeDelta());
404
405     ExpectMtbrTime({}, base::TimeDelta());
406     ExpectZeroRebuffers({});
407     ExpectNoUkmWatchTime();
408
409     ResetMetricRecorders();
410     wtr_.reset();
411     base::RunLoop().RunUntilIdle();
412     ExpectWatchTime({}, base::TimeDelta());
413     ExpectMtbrTime({}, base::TimeDelta());
414     ExpectZeroRebuffers({});
415
416     // UKM watch time should be recorded even with no UMA.
417     switch (key) {
418       case WatchTimeKey::kAudioAll:
419       case WatchTimeKey::kAudioBackgroundAll:
420       case WatchTimeKey::kAudioVideoAll:
421       case WatchTimeKey::kAudioVideoBackgroundAll:
422       case WatchTimeKey::kAudioVideoMutedAll:
423       case WatchTimeKey::kVideoAll:
424       case WatchTimeKey::kVideoBackgroundAll:
425         ExpectUkmWatchTime({UkmEntry::kWatchTimeName}, kWatchTime2);
426         break;
427
428       // These keys are not reported, instead we boolean flags for each type.
429       case WatchTimeKey::kAudioMse:
430       case WatchTimeKey::kAudioEme:
431       case WatchTimeKey::kAudioSrc:
432       case WatchTimeKey::kAudioEmbeddedExperience:
433       case WatchTimeKey::kAudioBackgroundMse:
434       case WatchTimeKey::kAudioBackgroundEme:
435       case WatchTimeKey::kAudioBackgroundSrc:
436       case WatchTimeKey::kAudioBackgroundEmbeddedExperience:
437       case WatchTimeKey::kAudioVideoMse:
438       case WatchTimeKey::kAudioVideoEme:
439       case WatchTimeKey::kAudioVideoSrc:
440       case WatchTimeKey::kAudioVideoEmbeddedExperience:
441       case WatchTimeKey::kAudioVideoMutedMse:
442       case WatchTimeKey::kAudioVideoMutedEme:
443       case WatchTimeKey::kAudioVideoMutedSrc:
444       case WatchTimeKey::kAudioVideoMutedEmbeddedExperience:
445       case WatchTimeKey::kAudioVideoBackgroundMse:
446       case WatchTimeKey::kAudioVideoBackgroundEme:
447       case WatchTimeKey::kAudioVideoBackgroundSrc:
448       case WatchTimeKey::kAudioVideoBackgroundEmbeddedExperience:
449       case WatchTimeKey::kVideoMse:
450       case WatchTimeKey::kVideoEme:
451       case WatchTimeKey::kVideoSrc:
452       case WatchTimeKey::kVideoEmbeddedExperience:
453       case WatchTimeKey::kVideoBackgroundMse:
454       case WatchTimeKey::kVideoBackgroundEme:
455       case WatchTimeKey::kVideoBackgroundSrc:
456       case WatchTimeKey::kVideoBackgroundEmbeddedExperience:
457       case WatchTimeKey::kAudioVideoMediaFoundationAll:
458       case WatchTimeKey::kAudioVideoMediaFoundationEme:
459         ExpectUkmWatchTime({}, base::TimeDelta());
460         break;
461
462       // These keys roll up into the battery watch time field.
463       case WatchTimeKey::kAudioBattery:
464       case WatchTimeKey::kAudioBackgroundBattery:
465       case WatchTimeKey::kAudioVideoBattery:
466       case WatchTimeKey::kAudioVideoMutedBattery:
467       case WatchTimeKey::kAudioVideoBackgroundBattery:
468       case WatchTimeKey::kVideoBattery:
469       case WatchTimeKey::kVideoBackgroundBattery:
470         ExpectUkmWatchTime({UkmEntry::kWatchTime_BatteryName}, kWatchTime2);
471         break;
472
473       // These keys roll up into the AC watch time field.
474       case WatchTimeKey::kAudioAc:
475       case WatchTimeKey::kAudioBackgroundAc:
476       case WatchTimeKey::kAudioVideoAc:
477       case WatchTimeKey::kAudioVideoBackgroundAc:
478       case WatchTimeKey::kAudioVideoMutedAc:
479       case WatchTimeKey::kVideoAc:
480       case WatchTimeKey::kVideoBackgroundAc:
481         ExpectUkmWatchTime({UkmEntry::kWatchTime_ACName}, kWatchTime2);
482         break;
483
484       case WatchTimeKey::kAudioVideoDisplayFullscreen:
485       case WatchTimeKey::kAudioVideoMutedDisplayFullscreen:
486       case WatchTimeKey::kVideoDisplayFullscreen:
487         ExpectUkmWatchTime({UkmEntry::kWatchTime_DisplayFullscreenName},
488                            kWatchTime2);
489         break;
490
491       case WatchTimeKey::kAudioVideoDisplayInline:
492       case WatchTimeKey::kAudioVideoMutedDisplayInline:
493       case WatchTimeKey::kVideoDisplayInline:
494         ExpectUkmWatchTime({UkmEntry::kWatchTime_DisplayInlineName},
495                            kWatchTime2);
496         break;
497
498       case WatchTimeKey::kAudioVideoDisplayPictureInPicture:
499       case WatchTimeKey::kAudioVideoMutedDisplayPictureInPicture:
500       case WatchTimeKey::kVideoDisplayPictureInPicture:
501         ExpectUkmWatchTime({UkmEntry::kWatchTime_DisplayPictureInPictureName},
502                            kWatchTime2);
503         break;
504
505       case WatchTimeKey::kAudioNativeControlsOn:
506       case WatchTimeKey::kAudioVideoNativeControlsOn:
507       case WatchTimeKey::kAudioVideoMutedNativeControlsOn:
508       case WatchTimeKey::kVideoNativeControlsOn:
509         ExpectUkmWatchTime({UkmEntry::kWatchTime_NativeControlsOnName},
510                            kWatchTime2);
511         break;
512
513       case WatchTimeKey::kAudioNativeControlsOff:
514       case WatchTimeKey::kAudioVideoNativeControlsOff:
515       case WatchTimeKey::kAudioVideoMutedNativeControlsOff:
516       case WatchTimeKey::kVideoNativeControlsOff:
517         ExpectUkmWatchTime({UkmEntry::kWatchTime_NativeControlsOffName},
518                            kWatchTime2);
519         break;
520     }
521
522     ResetMetricRecorders();
523   }
524 }
525
526 TEST_F(WatchTimeRecorderTest, TestRebufferingMetrics) {
527   Initialize(true, false, true, true);
528
529   constexpr base::TimeDelta kWatchTime = base::Seconds(50);
530   for (auto key : computation_keys_)
531     wtr_->RecordWatchTime(key, kWatchTime);
532   wtr_->UpdateUnderflowCount(1);
533   wtr_->UpdateUnderflowCount(2);
534
535   // Trigger finalization of everything.
536   wtr_->FinalizeWatchTime({});
537   base::RunLoop().RunUntilIdle();
538
539   ExpectMtbrTime(mtbr_keys_, kWatchTime / 2);
540   ExpectRebuffers(smooth_keys_, 2);
541
542   // Now rerun the test without any rebuffering.
543   ResetMetricRecorders();
544   for (auto key : computation_keys_)
545     wtr_->RecordWatchTime(key, kWatchTime);
546   wtr_->FinalizeWatchTime({});
547   base::RunLoop().RunUntilIdle();
548
549   ExpectMtbrTime({}, base::TimeDelta());
550   ExpectZeroRebuffers(smooth_keys_);
551
552   // Now rerun the test with a small amount of watch time and ensure rebuffering
553   // isn't recorded because we haven't met the watch time requirements.
554   ResetMetricRecorders();
555   constexpr base::TimeDelta kWatchTimeShort = base::Seconds(5);
556   for (auto key : computation_keys_)
557     wtr_->RecordWatchTime(key, kWatchTimeShort);
558   wtr_->UpdateUnderflowCount(1);
559   wtr_->UpdateUnderflowCount(2);
560   wtr_->FinalizeWatchTime({});
561   base::RunLoop().RunUntilIdle();
562
563   // Nothing should be logged since this doesn't meet requirements.
564   ExpectMtbrTime({}, base::TimeDelta());
565   for (auto key : smooth_keys_)
566     histogram_tester_->ExpectTotalCount(key, 0);
567 }
568
569 TEST_F(WatchTimeRecorderTest, TestRebufferingMetricsMediaStream) {
570   Initialize(true, false, true, true,
571              mojom::MediaStreamType::kLocalDeviceCapture);
572
573   constexpr base::TimeDelta kWatchTime = base::Seconds(50);
574   for (auto key : computation_keys_)
575     wtr_->RecordWatchTime(key, kWatchTime);
576   wtr_->UpdateUnderflowCount(1);
577   wtr_->UpdateUnderflowCount(2);
578
579   // Trigger finalization of everything.
580   wtr_->FinalizeWatchTime({});
581   base::RunLoop().RunUntilIdle();
582
583   ExpectMtbrTime({}, base::TimeDelta());
584   ExpectRebuffers({}, 0);
585
586   // Now rerun the test without any rebuffering.
587   ResetMetricRecorders();
588   for (auto key : computation_keys_)
589     wtr_->RecordWatchTime(key, kWatchTime);
590   wtr_->FinalizeWatchTime({});
591   base::RunLoop().RunUntilIdle();
592
593   ExpectMtbrTime({}, base::TimeDelta());
594   ExpectRebuffers({}, 0);
595 }
596
597 TEST_F(WatchTimeRecorderTest, TestDiscardMetrics) {
598   Initialize(true, false, true, true);
599   wtr_->UpdateSecondaryProperties(CreateSecondaryProperties());
600
601   constexpr base::TimeDelta kWatchTime = base::Seconds(5);
602   for (auto key : computation_keys_)
603     wtr_->RecordWatchTime(key, kWatchTime);
604
605   // Trigger finalization of everything.
606   wtr_.reset();
607   base::RunLoop().RunUntilIdle();
608
609   // No standard watch time should be recorded because it falls below the
610   // reporting threshold.
611   ExpectWatchTime({}, base::TimeDelta());
612
613   // Verify the time was instead logged to the discard keys.
614   for (auto key : discard_keys_) {
615     histogram_tester_->ExpectUniqueSample(key, kWatchTime.InMilliseconds(), 1);
616   }
617
618   // UKM watch time won't be logged because we aren't sending "All" keys.
619   ExpectUkmWatchTime({}, base::TimeDelta());
620 }
621
622 TEST_F(WatchTimeRecorderTest, TestDiscardMetricsMediaStream) {
623   Initialize(true, false, true, true,
624              mojom::MediaStreamType::kLocalDeviceCapture);
625   wtr_->UpdateSecondaryProperties(CreateSecondaryProperties());
626
627   constexpr base::TimeDelta kWatchTime = base::Seconds(5);
628   for (auto key : computation_keys_)
629     wtr_->RecordWatchTime(key, kWatchTime);
630
631   // Trigger finalization of everything.
632   wtr_.reset();
633   base::RunLoop().RunUntilIdle();
634
635   // No watch time and no discard metrics should be logged.
636   ExpectWatchTime({}, base::TimeDelta());
637   for (auto key : discard_keys_) {
638     histogram_tester_->ExpectTotalCount(key, 0);
639   }
640
641   // UKM watch time won't be logged because we aren't sending "All" keys.
642   ExpectUkmWatchTime({}, base::TimeDelta());
643 }
644
645 #define EXPECT_UKM(name, value) \
646   test_recorder_->ExpectEntryMetric(entry, name, value)
647 #define EXPECT_NO_UKM(name) \
648   EXPECT_FALSE(test_recorder_->EntryHasMetric(entry, name))
649 #define EXPECT_HAS_UKM(name) \
650   EXPECT_TRUE(test_recorder_->EntryHasMetric(entry, name));
651
652 TEST_F(WatchTimeRecorderTest, TestFinalizeNoDuplication) {
653   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
654       true, true, false, false, false, false, false,
655       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
656   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
657       CreateSecondaryProperties();
658   Initialize(properties.Clone());
659   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
660
661   // Verify that UKM is reported along with the watch time.
662   constexpr base::TimeDelta kWatchTime = base::Seconds(4);
663   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime);
664
665   // Finalize everything. UKM is only recorded at destruction, so this should do
666   // nothing.
667   wtr_->FinalizeWatchTime({});
668   base::RunLoop().RunUntilIdle();
669
670   // No watch time should have been recorded since this is below the UMA report
671   // threshold.
672   ExpectWatchTime({}, base::TimeDelta());
673   ExpectMtbrTime({}, base::TimeDelta());
674   ExpectZeroRebuffers({});
675   ExpectNoUkmWatchTime();
676
677   const auto& empty_entries =
678       test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
679   EXPECT_EQ(0u, empty_entries.size());
680
681   // Verify UKM is logged at destruction time.
682   ResetMetricRecorders();
683   wtr_.reset();
684   base::RunLoop().RunUntilIdle();
685   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
686   EXPECT_EQ(1u, entries.size());
687   for (const auto* entry : entries) {
688     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
689
690     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
691     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
692     EXPECT_UKM(UkmEntry::kAudioCodecName,
693                static_cast<int>(secondary_properties->audio_codec));
694     EXPECT_UKM(UkmEntry::kVideoCodecName,
695                static_cast<int>(secondary_properties->video_codec));
696     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
697                static_cast<int64_t>(secondary_properties->audio_codec_profile));
698     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
699                secondary_properties->video_codec_profile);
700     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
701     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
702     EXPECT_UKM(
703         UkmEntry::kAudioEncryptionSchemeName,
704         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
705     EXPECT_UKM(
706         UkmEntry::kVideoEncryptionSchemeName,
707         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
708     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
709     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
710     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
711                static_cast<int64_t>(properties->media_stream_type));
712     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
713     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
714     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
715     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
716     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
717                secondary_properties->natural_size.width());
718     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
719                secondary_properties->natural_size.height());
720     EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime.InMilliseconds());
721     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 0);
722     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 0);
723     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
724     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
725
726     EXPECT_NO_UKM(UkmEntry::kMeanTimeBetweenRebuffersName);
727     EXPECT_NO_UKM(UkmEntry::kWatchTime_ACName);
728     EXPECT_NO_UKM(UkmEntry::kWatchTime_BatteryName);
729     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOnName);
730     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOffName);
731     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayFullscreenName);
732     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayInlineName);
733     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName);
734   }
735 }
736
737 TEST_F(WatchTimeRecorderTest, FinalizeWithoutWatchTime) {
738   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
739       true, true, false, false, false, false, false,
740       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
741   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
742       CreateSecondaryProperties();
743   Initialize(properties.Clone());
744   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
745
746   // Finalize everything. UKM is only recorded at destruction, so this should do
747   // nothing.
748   wtr_->FinalizeWatchTime({});
749   base::RunLoop().RunUntilIdle();
750
751   // No watch time should have been recorded even though a finalize event will
752   // be sent, however a UKM entry with the playback properties will still be
753   // generated.
754   ExpectWatchTime({}, base::TimeDelta());
755   ExpectMtbrTime({}, base::TimeDelta());
756   ExpectZeroRebuffers({});
757   ExpectNoUkmWatchTime();
758
759   const auto& empty_entries =
760       test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
761   EXPECT_EQ(0u, empty_entries.size());
762
763   // Destructing the recorder should generate a UKM report though.
764   ResetMetricRecorders();
765   wtr_.reset();
766   base::RunLoop().RunUntilIdle();
767   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
768   EXPECT_EQ(1u, entries.size());
769   for (const auto* entry : entries) {
770     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
771
772     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
773     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
774     EXPECT_UKM(UkmEntry::kAudioCodecName,
775                static_cast<int>(secondary_properties->audio_codec));
776     EXPECT_UKM(UkmEntry::kVideoCodecName,
777                static_cast<int>(secondary_properties->video_codec));
778     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
779                static_cast<int64_t>(secondary_properties->audio_codec_profile));
780     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
781                secondary_properties->video_codec_profile);
782     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
783     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
784     EXPECT_UKM(
785         UkmEntry::kAudioEncryptionSchemeName,
786         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
787     EXPECT_UKM(
788         UkmEntry::kVideoEncryptionSchemeName,
789         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
790     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
791     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
792     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
793                static_cast<int64_t>(properties->media_stream_type));
794     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
795     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
796     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
797     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
798     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
799                secondary_properties->natural_size.width());
800     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
801                secondary_properties->natural_size.height());
802     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 0);
803     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 0);
804     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
805     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
806
807     EXPECT_NO_UKM(UkmEntry::kMeanTimeBetweenRebuffersName);
808     EXPECT_NO_UKM(UkmEntry::kWatchTimeName);
809     EXPECT_NO_UKM(UkmEntry::kWatchTime_ACName);
810     EXPECT_NO_UKM(UkmEntry::kWatchTime_BatteryName);
811     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOnName);
812     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOffName);
813     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayFullscreenName);
814     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayInlineName);
815     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName);
816   }
817 }
818
819 TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideo) {
820   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
821       true, true, false, false, false, false, false,
822       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
823   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
824       mojom::SecondaryPlaybackProperties::New(
825           AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kXHE_AAC,
826           H264PROFILE_MAIN, AudioDecoderType::kUnknown,
827           VideoDecoderType::kUnknown, EncryptionScheme::kCenc,
828           EncryptionScheme::kCbcs, gfx::Size(800, 600));
829   Initialize(properties.Clone());
830   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
831
832   constexpr base::TimeDelta kWatchTime = base::Seconds(4);
833   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime);
834   wtr_.reset();
835   base::RunLoop().RunUntilIdle();
836
837   ExpectAacAudioCodecProfileHistogram(
838       secondary_properties->audio_codec_profile);
839
840   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
841   EXPECT_EQ(1u, entries.size());
842   for (const auto* entry : entries) {
843     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
844
845     EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime.InMilliseconds());
846     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
847     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
848     EXPECT_UKM(UkmEntry::kAudioCodecName,
849                static_cast<int>(secondary_properties->audio_codec));
850     EXPECT_UKM(UkmEntry::kVideoCodecName,
851                static_cast<int>(secondary_properties->video_codec));
852     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
853                static_cast<int64_t>(secondary_properties->audio_codec_profile));
854     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
855                secondary_properties->video_codec_profile);
856     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
857     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
858     EXPECT_UKM(
859         UkmEntry::kAudioEncryptionSchemeName,
860         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
861     EXPECT_UKM(
862         UkmEntry::kVideoEncryptionSchemeName,
863         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
864     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
865     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
866     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
867                static_cast<int64_t>(properties->media_stream_type));
868     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
869     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
870     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
871     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
872     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
873                secondary_properties->natural_size.width());
874     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
875                secondary_properties->natural_size.height());
876     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
877     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 0);
878     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 0);
879     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
880
881     EXPECT_NO_UKM(UkmEntry::kMeanTimeBetweenRebuffersName);
882     EXPECT_NO_UKM(UkmEntry::kWatchTime_ACName);
883     EXPECT_NO_UKM(UkmEntry::kWatchTime_BatteryName);
884     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOnName);
885     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOffName);
886     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayFullscreenName);
887     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayInlineName);
888     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName);
889   }
890 }
891
892 TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideoWithExtras) {
893   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
894       true, true, false, false, true, true, false,
895       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
896   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
897       mojom::SecondaryPlaybackProperties::New(
898           AudioCodec::kOpus, VideoCodec::kVP9, AudioCodecProfile::kUnknown,
899           VP9PROFILE_PROFILE0, AudioDecoderType::kUnknown,
900           VideoDecoderType::kUnknown, EncryptionScheme::kUnencrypted,
901           EncryptionScheme::kUnencrypted, gfx::Size(800, 600));
902   Initialize(properties.Clone());
903   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
904
905   constexpr base::TimeDelta kWatchTime = base::Seconds(54);
906   const base::TimeDelta kWatchTime2 = kWatchTime * 2;
907   const base::TimeDelta kWatchTime3 = kWatchTime / 3;
908   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime2);
909   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAc, kWatchTime);
910
911   // Ensure partial finalize does not affect final report.
912   wtr_->FinalizeWatchTime({WatchTimeKey::kAudioVideoAc});
913   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoBattery, kWatchTime);
914   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoNativeControlsOn, kWatchTime);
915   wtr_->FinalizeWatchTime({WatchTimeKey::kAudioVideoNativeControlsOn});
916   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoNativeControlsOff, kWatchTime);
917   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoDisplayFullscreen,
918                         kWatchTime3);
919   wtr_->FinalizeWatchTime({WatchTimeKey::kAudioVideoDisplayFullscreen});
920   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoDisplayInline, kWatchTime3);
921   wtr_->FinalizeWatchTime({WatchTimeKey::kAudioVideoDisplayInline});
922   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoDisplayPictureInPicture,
923                         kWatchTime3);
924   wtr_->UpdateUnderflowCount(3);
925   constexpr base::TimeDelta kUnderflowDuration = base::Milliseconds(500);
926   wtr_->UpdateUnderflowDuration(2, kUnderflowDuration);
927   wtr_->UpdateVideoDecodeStats(10, 2);
928   wtr_->OnError(PIPELINE_ERROR_DECODE);
929
930   secondary_properties->audio_decoder = AudioDecoderType::kMojo;
931   secondary_properties->video_decoder = VideoDecoderType::kMojo;
932   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
933
934   wtr_->SetAutoplayInitiated(true);
935
936   wtr_->OnDurationChanged(base::Seconds(9500));
937
938   wtr_.reset();
939   base::RunLoop().RunUntilIdle();
940
941   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
942   EXPECT_EQ(1u, entries.size());
943   for (const auto* entry : entries) {
944     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
945     EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime2.InMilliseconds());
946     EXPECT_UKM(UkmEntry::kWatchTime_ACName, kWatchTime.InMilliseconds());
947     EXPECT_UKM(UkmEntry::kWatchTime_BatteryName, kWatchTime.InMilliseconds());
948     EXPECT_UKM(UkmEntry::kWatchTime_NativeControlsOnName,
949                kWatchTime.InMilliseconds());
950     EXPECT_UKM(UkmEntry::kWatchTime_NativeControlsOffName,
951                kWatchTime.InMilliseconds());
952     EXPECT_UKM(UkmEntry::kWatchTime_DisplayFullscreenName,
953                kWatchTime3.InMilliseconds());
954     EXPECT_UKM(UkmEntry::kWatchTime_DisplayInlineName,
955                kWatchTime3.InMilliseconds());
956     EXPECT_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName,
957                kWatchTime3.InMilliseconds());
958     EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
959                kWatchTime2.InMilliseconds() / 3);
960     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
961
962     // Values taken from .cc private enumeration (and should never change).
963     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 2);
964     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 5);
965
966     // Duration should be rounded up.
967     EXPECT_UKM(UkmEntry::kDurationName, 10000000);
968
969     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
970     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
971     EXPECT_UKM(UkmEntry::kAudioCodecName,
972                static_cast<int>(secondary_properties->audio_codec));
973     EXPECT_UKM(UkmEntry::kVideoCodecName,
974                static_cast<int>(secondary_properties->video_codec));
975     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
976                static_cast<int64_t>(secondary_properties->audio_codec_profile));
977     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
978                secondary_properties->video_codec_profile);
979     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
980     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
981     EXPECT_UKM(
982         UkmEntry::kAudioEncryptionSchemeName,
983         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
984     EXPECT_UKM(
985         UkmEntry::kVideoEncryptionSchemeName,
986         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
987     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
988     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
989     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
990                static_cast<int64_t>(properties->media_stream_type));
991     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_ERROR_DECODE);
992     EXPECT_UKM(UkmEntry::kRebuffersCountName, 3);
993     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 2);
994     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName,
995                kUnderflowDuration.InMilliseconds());
996     EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, 10);
997     EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, 2);
998     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
999                secondary_properties->natural_size.width());
1000     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1001                secondary_properties->natural_size.height());
1002     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, true);
1003   }
1004 }
1005
1006 TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideoBackgroundMuted) {
1007   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1008       true, true, true, true, false, false, false,
1009       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1010   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
1011       CreateSecondaryProperties();
1012   Initialize(properties.Clone());
1013   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
1014
1015   constexpr base::TimeDelta kWatchTime = base::Seconds(54);
1016   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoBackgroundAll, kWatchTime);
1017   wtr_.reset();
1018   base::RunLoop().RunUntilIdle();
1019
1020   if (secondary_properties->audio_codec == AudioCodec::kAAC) {
1021     ExpectAacAudioCodecProfileHistogram(
1022         secondary_properties->audio_codec_profile);
1023   }
1024
1025   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1026   EXPECT_EQ(1u, entries.size());
1027   for (const auto* entry : entries) {
1028     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1029
1030     EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime.InMilliseconds());
1031     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1032     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1033     EXPECT_UKM(UkmEntry::kAudioCodecName,
1034                static_cast<int>(secondary_properties->audio_codec));
1035     EXPECT_UKM(UkmEntry::kVideoCodecName,
1036                static_cast<int>(secondary_properties->video_codec));
1037     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1038                static_cast<int64_t>(secondary_properties->audio_codec_profile));
1039     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1040                secondary_properties->video_codec_profile);
1041     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1042     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1043     EXPECT_UKM(
1044         UkmEntry::kAudioEncryptionSchemeName,
1045         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
1046     EXPECT_UKM(
1047         UkmEntry::kVideoEncryptionSchemeName,
1048         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
1049     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1050     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1051     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1052                static_cast<int64_t>(properties->media_stream_type));
1053     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
1054     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
1055     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1056     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1057     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1058                secondary_properties->natural_size.width());
1059     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1060                secondary_properties->natural_size.height());
1061     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1062     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 0);
1063     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 0);
1064     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1065
1066     EXPECT_NO_UKM(UkmEntry::kDurationName);
1067     EXPECT_NO_UKM(UkmEntry::kMeanTimeBetweenRebuffersName);
1068     EXPECT_NO_UKM(UkmEntry::kWatchTime_ACName);
1069     EXPECT_NO_UKM(UkmEntry::kWatchTime_BatteryName);
1070     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOnName);
1071     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOffName);
1072     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayFullscreenName);
1073     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayInlineName);
1074     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName);
1075   }
1076 }
1077
1078 TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideoDuration) {
1079   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1080       true, true, false, false, false, false, false,
1081       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1082   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
1083       CreateSecondaryProperties();
1084   Initialize(properties.Clone());
1085   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
1086
1087   wtr_->OnDurationChanged(base::Seconds(12345));
1088   wtr_.reset();
1089   base::RunLoop().RunUntilIdle();
1090
1091   if (secondary_properties->audio_codec == AudioCodec::kAAC) {
1092     ExpectAacAudioCodecProfileHistogram(
1093         secondary_properties->audio_codec_profile);
1094   }
1095
1096   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1097   EXPECT_EQ(1u, entries.size());
1098   for (const auto* entry : entries) {
1099     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1100
1101     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1102     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1103     EXPECT_UKM(UkmEntry::kAudioCodecName,
1104                static_cast<int>(secondary_properties->audio_codec));
1105     EXPECT_UKM(UkmEntry::kVideoCodecName,
1106                static_cast<int>(secondary_properties->video_codec));
1107     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1108                static_cast<int64_t>(secondary_properties->audio_codec_profile));
1109     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1110                secondary_properties->video_codec_profile);
1111     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1112     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1113     EXPECT_UKM(
1114         UkmEntry::kAudioEncryptionSchemeName,
1115         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
1116     EXPECT_UKM(
1117         UkmEntry::kVideoEncryptionSchemeName,
1118         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
1119     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1120     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1121     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1122                static_cast<int64_t>(properties->media_stream_type));
1123     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
1124     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
1125     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1126     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1127     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1128                secondary_properties->natural_size.width());
1129     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1130                secondary_properties->natural_size.height());
1131     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1132     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 0);
1133     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 0);
1134     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1135
1136     // Duration should be rounded to the most significant digit.
1137     EXPECT_UKM(UkmEntry::kDurationName, 10000000);
1138
1139     EXPECT_NO_UKM(UkmEntry::kMeanTimeBetweenRebuffersName);
1140     EXPECT_NO_UKM(UkmEntry::kWatchTime_ACName);
1141     EXPECT_NO_UKM(UkmEntry::kWatchTime_BatteryName);
1142     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOnName);
1143     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOffName);
1144     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayFullscreenName);
1145     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayInlineName);
1146     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName);
1147   }
1148 }
1149
1150 TEST_F(WatchTimeRecorderTest, BasicUkmAudioVideoDurationInfinite) {
1151   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1152       true, true, false, false, false, false, false,
1153       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1154   mojom::SecondaryPlaybackPropertiesPtr secondary_properties =
1155       CreateSecondaryProperties();
1156   Initialize(properties.Clone());
1157   wtr_->UpdateSecondaryProperties(secondary_properties.Clone());
1158
1159   wtr_->OnDurationChanged(kInfiniteDuration);
1160   wtr_.reset();
1161   base::RunLoop().RunUntilIdle();
1162
1163   if (secondary_properties->audio_codec == AudioCodec::kAAC) {
1164     ExpectAacAudioCodecProfileHistogram(
1165         secondary_properties->audio_codec_profile);
1166   }
1167
1168   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1169   EXPECT_EQ(1u, entries.size());
1170   for (const auto* entry : entries) {
1171     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1172
1173     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1174     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1175     EXPECT_UKM(UkmEntry::kAudioCodecName,
1176                static_cast<int>(secondary_properties->audio_codec));
1177     EXPECT_UKM(UkmEntry::kVideoCodecName,
1178                static_cast<int>(secondary_properties->video_codec));
1179     EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1180                static_cast<int64_t>(secondary_properties->audio_codec_profile));
1181     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1182                secondary_properties->video_codec_profile);
1183     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1184     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1185     EXPECT_UKM(
1186         UkmEntry::kAudioEncryptionSchemeName,
1187         static_cast<int64_t>(secondary_properties->audio_encryption_scheme));
1188     EXPECT_UKM(
1189         UkmEntry::kVideoEncryptionSchemeName,
1190         static_cast<int64_t>(secondary_properties->video_encryption_scheme));
1191     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1192     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1193     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1194                static_cast<int64_t>(properties->media_stream_type));
1195     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
1196     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
1197     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1198     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1199     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1200                secondary_properties->natural_size.width());
1201     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1202                secondary_properties->natural_size.height());
1203     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1204     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 0);
1205     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 0);
1206     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1207
1208     // Duration should be unrecorded when infinite.
1209     EXPECT_NO_UKM(UkmEntry::kDurationName);
1210     EXPECT_NO_UKM(UkmEntry::kWatchTimeName);
1211     EXPECT_NO_UKM(UkmEntry::kMeanTimeBetweenRebuffersName);
1212     EXPECT_NO_UKM(UkmEntry::kWatchTime_ACName);
1213     EXPECT_NO_UKM(UkmEntry::kWatchTime_BatteryName);
1214     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOnName);
1215     EXPECT_NO_UKM(UkmEntry::kWatchTime_NativeControlsOffName);
1216     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayFullscreenName);
1217     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayInlineName);
1218     EXPECT_NO_UKM(UkmEntry::kWatchTime_DisplayPictureInPictureName);
1219   }
1220 }
1221
1222 TEST_F(WatchTimeRecorderTest, BasicUkmMediaStreamType) {
1223   std::vector<mojom::MediaStreamType> media_stream_types{
1224       mojom::MediaStreamType::kLocalElementCapture,
1225       mojom::MediaStreamType::kLocalDeviceCapture,
1226       mojom::MediaStreamType::kLocalTabCapture,
1227       mojom::MediaStreamType::kLocalDesktopCapture,
1228       mojom::MediaStreamType::kLocalDisplayCapture,
1229       mojom::MediaStreamType::kRemote,
1230       mojom::MediaStreamType::kNone,
1231   };
1232
1233   for (const auto& media_stream_type : media_stream_types) {
1234     mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1235         true, true, false, false, false, false, false, media_stream_type,
1236         RendererType::kRendererImpl);
1237     Initialize(properties.Clone());
1238     wtr_->UpdateSecondaryProperties(CreateSecondaryProperties());
1239
1240     constexpr base::TimeDelta kWatchTime = base::Seconds(1);
1241     wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime);
1242     wtr_.reset();
1243     base::RunLoop().RunUntilIdle();
1244
1245     const auto& entries =
1246         test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1247     ASSERT_EQ(1u, entries.size());
1248
1249     // Check that the media stream type is set correctly.
1250     for (const auto* entry : entries) {
1251       EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1252                  static_cast<int64_t>(media_stream_type));
1253     }
1254     ResetMetricRecorders();
1255   }
1256 }
1257
1258 // Might happen due to timing issues, so ensure no crashes.
1259 TEST_F(WatchTimeRecorderTest, NoSecondaryProperties) {
1260   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1261       true, true, false, false, true, true, false,
1262       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1263   Initialize(properties.Clone());
1264
1265   constexpr base::TimeDelta kWatchTime = base::Seconds(54);
1266   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime);
1267   wtr_.reset();
1268   base::RunLoop().RunUntilIdle();
1269   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1270   EXPECT_EQ(0u, entries.size());
1271 }
1272
1273 TEST_F(WatchTimeRecorderTest, SingleSecondaryPropertiesUnknownToKnown) {
1274   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1275       true, true, false, false, true, true, false,
1276       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1277   mojom::SecondaryPlaybackPropertiesPtr secondary_properties1 =
1278       mojom::SecondaryPlaybackProperties::New(
1279           AudioCodec::kUnknown, VideoCodec::kUnknown,
1280           AudioCodecProfile::kUnknown, VIDEO_CODEC_PROFILE_UNKNOWN,
1281           AudioDecoderType::kUnknown, VideoDecoderType::kUnknown,
1282           EncryptionScheme::kUnencrypted, EncryptionScheme::kUnencrypted,
1283           gfx::Size(800, 600));
1284   Initialize(properties.Clone());
1285   wtr_->UpdateSecondaryProperties(secondary_properties1.Clone());
1286
1287   constexpr base::TimeDelta kWatchTime = base::Seconds(54);
1288   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime);
1289
1290   mojom::SecondaryPlaybackPropertiesPtr secondary_properties2 =
1291       mojom::SecondaryPlaybackProperties::New(
1292           AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kXHE_AAC,
1293           H264PROFILE_MAIN, AudioDecoderType::kFFmpeg,
1294           VideoDecoderType::kFFmpeg, EncryptionScheme::kUnencrypted,
1295           EncryptionScheme::kUnencrypted, gfx::Size(800, 600));
1296   wtr_->UpdateSecondaryProperties(secondary_properties2.Clone());
1297
1298   wtr_.reset();
1299   base::RunLoop().RunUntilIdle();
1300
1301   // Since we only transitioned unknown values to known values, there should be
1302   // only a single UKM entry.
1303   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1304   EXPECT_EQ(1u, entries.size());
1305   for (const auto* entry : entries) {
1306     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1307     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1308     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1309     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1310     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1311     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1312     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1313     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1314                static_cast<int64_t>(properties->media_stream_type));
1315     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1316     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
1317     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1318     EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime.InMilliseconds());
1319     EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 1);
1320     EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 2);
1321     EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
1322     EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1323     EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1324     EXPECT_UKM(UkmEntry::kAudioCodecName,
1325                static_cast<int>(secondary_properties2->audio_codec));
1326     EXPECT_UKM(UkmEntry::kVideoCodecName,
1327                static_cast<int>(secondary_properties2->video_codec));
1328     EXPECT_UKM(
1329         UkmEntry::kAudioCodecProfileName,
1330         static_cast<int64_t>(secondary_properties2->audio_codec_profile));
1331     EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1332                secondary_properties2->video_codec_profile);
1333     EXPECT_UKM(
1334         UkmEntry::kAudioEncryptionSchemeName,
1335         static_cast<int64_t>(secondary_properties2->audio_encryption_scheme));
1336     EXPECT_UKM(
1337         UkmEntry::kVideoEncryptionSchemeName,
1338         static_cast<int64_t>(secondary_properties2->video_encryption_scheme));
1339     EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1340                secondary_properties2->natural_size.width());
1341     EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1342                secondary_properties2->natural_size.height());
1343     EXPECT_NO_UKM(UkmEntry::kDurationName);
1344   }
1345 }
1346
1347 TEST_F(WatchTimeRecorderTest, MultipleSecondaryPropertiesNoFinalize) {
1348   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1349       true, true, false, false, true, true, false,
1350       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1351   mojom::SecondaryPlaybackPropertiesPtr secondary_properties1 =
1352       mojom::SecondaryPlaybackProperties::New(
1353           AudioCodec::kOpus, VideoCodec::kVP9, AudioCodecProfile::kUnknown,
1354           VP9PROFILE_PROFILE0, AudioDecoderType::kMojo, VideoDecoderType::kMojo,
1355           EncryptionScheme::kUnencrypted, EncryptionScheme::kUnencrypted,
1356           gfx::Size(400, 300));
1357   Initialize(properties.Clone());
1358   wtr_->UpdateSecondaryProperties(secondary_properties1.Clone());
1359
1360   constexpr base::TimeDelta kUnderflowDuration = base::Milliseconds(250);
1361   constexpr base::TimeDelta kWatchTime1 = base::Seconds(54);
1362   const int kUnderflowCount1 = 2;
1363   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime1);
1364   wtr_->UpdateUnderflowCount(kUnderflowCount1);
1365   wtr_->UpdateUnderflowDuration(kUnderflowCount1, kUnderflowDuration);
1366
1367   constexpr int kDecodedFrameCount1 = 10;
1368   constexpr int kDroppedFrameCount1 = 2;
1369   wtr_->UpdateVideoDecodeStats(kDecodedFrameCount1, kDroppedFrameCount1);
1370
1371   mojom::SecondaryPlaybackPropertiesPtr secondary_properties2 =
1372       mojom::SecondaryPlaybackProperties::New(
1373           AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kUnknown,
1374           H264PROFILE_MAIN, AudioDecoderType::kFFmpeg,
1375           VideoDecoderType::kFFmpeg, EncryptionScheme::kCenc,
1376           EncryptionScheme::kCenc, gfx::Size(800, 600));
1377   wtr_->UpdateSecondaryProperties(secondary_properties2.Clone());
1378
1379   constexpr base::TimeDelta kWatchTime2 = base::Seconds(25);
1380   const int kUnderflowCount2 = 3;
1381
1382   // Watch time and underflow counts continue to accumulate during property
1383   // changes, so we report the sum here instead of just kWatchTime2.
1384   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll,
1385                         kWatchTime1 + kWatchTime2);
1386   wtr_->UpdateUnderflowCount(kUnderflowCount1 + kUnderflowCount2);
1387   wtr_->OnError(PIPELINE_ERROR_DECODE);
1388   wtr_->OnDurationChanged(base::Seconds(5125));
1389
1390   constexpr int kDecodedFrameCount2 = 20;
1391   constexpr int kDroppedFrameCount2 = 10;
1392   wtr_->UpdateVideoDecodeStats(kDecodedFrameCount1 + kDecodedFrameCount2,
1393                                kDroppedFrameCount1 + kDroppedFrameCount2);
1394
1395   wtr_.reset();
1396   base::RunLoop().RunUntilIdle();
1397
1398   // All records should have the following:
1399   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1400   EXPECT_EQ(2u, entries.size());
1401   for (const auto* entry : entries) {
1402     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1403     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1404     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1405     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1406     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1407     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1408     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1409     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1410                static_cast<int64_t>(properties->media_stream_type));
1411     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1412     EXPECT_UKM(UkmEntry::kDurationName, 5000000);
1413     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1414
1415     // All records inherit the final pipeline status code.
1416     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_ERROR_DECODE);
1417   }
1418
1419   // The first record should have...
1420   auto* entry = entries[0];
1421   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime1.InMilliseconds());
1422   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1423              kWatchTime1.InMilliseconds() / kUnderflowCount1);
1424   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 2);
1425   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 5);
1426   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount1);
1427   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, kUnderflowCount1);
1428   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName,
1429              kUnderflowDuration.InMilliseconds());
1430   EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, kDecodedFrameCount1);
1431   EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, kDroppedFrameCount1);
1432   EXPECT_UKM(UkmEntry::kAudioCodecName,
1433              static_cast<int>(secondary_properties1->audio_codec));
1434   EXPECT_UKM(UkmEntry::kVideoCodecName,
1435              static_cast<int>(secondary_properties1->video_codec));
1436   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1437              static_cast<int64_t>(secondary_properties1->audio_codec_profile));
1438   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1439              secondary_properties1->video_codec_profile);
1440   EXPECT_UKM(
1441       UkmEntry::kAudioEncryptionSchemeName,
1442       static_cast<int64_t>(secondary_properties1->audio_encryption_scheme));
1443   EXPECT_UKM(
1444       UkmEntry::kVideoEncryptionSchemeName,
1445       static_cast<int64_t>(secondary_properties1->video_encryption_scheme));
1446   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1447              secondary_properties1->natural_size.width());
1448   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1449              secondary_properties1->natural_size.height());
1450
1451   // The second record should have...
1452   entry = entries[1];
1453   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime2.InMilliseconds());
1454   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1455              kWatchTime2.InMilliseconds() / kUnderflowCount2);
1456   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 1);
1457   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 2);
1458   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount2);
1459   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1460   EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, kDecodedFrameCount2);
1461   EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, kDroppedFrameCount2);
1462
1463   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1464   EXPECT_UKM(UkmEntry::kAudioCodecName,
1465              static_cast<int>(secondary_properties2->audio_codec));
1466   EXPECT_UKM(UkmEntry::kVideoCodecName,
1467              static_cast<int>(secondary_properties2->video_codec));
1468   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1469              static_cast<int64_t>(secondary_properties2->audio_codec_profile));
1470   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1471              secondary_properties2->video_codec_profile);
1472   EXPECT_UKM(
1473       UkmEntry::kAudioEncryptionSchemeName,
1474       static_cast<int64_t>(secondary_properties2->audio_encryption_scheme));
1475   EXPECT_UKM(
1476       UkmEntry::kVideoEncryptionSchemeName,
1477       static_cast<int64_t>(secondary_properties2->video_encryption_scheme));
1478   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1479              secondary_properties2->natural_size.width());
1480   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1481              secondary_properties2->natural_size.height());
1482 }
1483
1484 TEST_F(WatchTimeRecorderTest, MultipleSecondaryPropertiesNoFinalizeNo2ndWT) {
1485   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1486       true, true, false, false, true, true, false,
1487       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1488   mojom::SecondaryPlaybackPropertiesPtr secondary_properties1 =
1489       mojom::SecondaryPlaybackProperties::New(
1490           AudioCodec::kOpus, VideoCodec::kVP9, AudioCodecProfile::kUnknown,
1491           VP9PROFILE_PROFILE0, AudioDecoderType::kMojo, VideoDecoderType::kMojo,
1492           EncryptionScheme::kUnencrypted, EncryptionScheme::kUnencrypted,
1493           gfx::Size(400, 300));
1494   Initialize(properties.Clone());
1495   wtr_->UpdateSecondaryProperties(secondary_properties1.Clone());
1496
1497   constexpr base::TimeDelta kUnderflowDuration = base::Milliseconds(250);
1498   constexpr base::TimeDelta kWatchTime1 = base::Seconds(54);
1499   const int kUnderflowCount1 = 2;
1500   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime1);
1501   wtr_->UpdateUnderflowCount(kUnderflowCount1);
1502   wtr_->UpdateUnderflowDuration(kUnderflowCount1, kUnderflowDuration);
1503
1504   constexpr int kDecodedFrameCount1 = 10;
1505   constexpr int kDroppedFrameCount1 = 2;
1506   wtr_->UpdateVideoDecodeStats(kDecodedFrameCount1, kDroppedFrameCount1);
1507
1508   mojom::SecondaryPlaybackPropertiesPtr secondary_properties2 =
1509       mojom::SecondaryPlaybackProperties::New(
1510           AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kXHE_AAC,
1511           H264PROFILE_MAIN, AudioDecoderType::kFFmpeg,
1512           VideoDecoderType::kFFmpeg, EncryptionScheme::kUnencrypted,
1513           EncryptionScheme::kUnencrypted, gfx::Size(800, 600));
1514   wtr_->UpdateSecondaryProperties(secondary_properties2.Clone());
1515
1516   // Don't record any watch time to the new record, it should report zero watch
1517   // time upon destruction. This ensures there's always a Finalize to prevent
1518   // UKM was receiving negative values from the previous unfinalized record.
1519   wtr_.reset();
1520   base::RunLoop().RunUntilIdle();
1521
1522   // All records should have the following:
1523   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1524   EXPECT_EQ(2u, entries.size());
1525   for (const auto* entry : entries) {
1526     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1527     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1528     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1529     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1530     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1531     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1532     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1533     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1534                static_cast<int64_t>(properties->media_stream_type));
1535     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1536     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_OK);
1537     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1538     EXPECT_NO_UKM(UkmEntry::kDurationName);
1539   }
1540
1541   // The first record should have...
1542   auto* entry = entries[0];
1543   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime1.InMilliseconds());
1544   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1545              kWatchTime1.InMilliseconds() / kUnderflowCount1);
1546   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 2);
1547   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 5);
1548   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount1);
1549   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, kUnderflowCount1);
1550   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName,
1551              kUnderflowDuration.InMilliseconds());
1552   EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, kDecodedFrameCount1);
1553   EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, kDroppedFrameCount1);
1554   EXPECT_UKM(UkmEntry::kAudioCodecName,
1555              static_cast<int>(secondary_properties1->audio_codec));
1556   EXPECT_UKM(UkmEntry::kVideoCodecName,
1557              static_cast<int>(secondary_properties1->video_codec));
1558   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1559              static_cast<int64_t>(secondary_properties1->audio_codec_profile));
1560   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1561              secondary_properties1->video_codec_profile);
1562   EXPECT_UKM(
1563       UkmEntry::kAudioEncryptionSchemeName,
1564       static_cast<int64_t>(secondary_properties1->audio_encryption_scheme));
1565   EXPECT_UKM(
1566       UkmEntry::kVideoEncryptionSchemeName,
1567       static_cast<int64_t>(secondary_properties1->video_encryption_scheme));
1568   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1569              secondary_properties1->natural_size.width());
1570   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1571              secondary_properties1->natural_size.height());
1572
1573   // The second record should have...
1574   entry = entries[1];
1575   EXPECT_UKM(UkmEntry::kWatchTimeName, 0);
1576   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 1);
1577   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 2);
1578   EXPECT_UKM(UkmEntry::kRebuffersCountName, 0);
1579   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1580   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1581   EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, 0);
1582   EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, 0);
1583   EXPECT_UKM(UkmEntry::kAudioCodecName,
1584              static_cast<int>(secondary_properties2->audio_codec));
1585   EXPECT_UKM(UkmEntry::kVideoCodecName,
1586              static_cast<int>(secondary_properties2->video_codec));
1587   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1588              static_cast<int64_t>(secondary_properties2->audio_codec_profile));
1589   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1590              secondary_properties2->video_codec_profile);
1591   EXPECT_UKM(
1592       UkmEntry::kAudioEncryptionSchemeName,
1593       static_cast<int64_t>(secondary_properties2->audio_encryption_scheme));
1594   EXPECT_UKM(
1595       UkmEntry::kVideoEncryptionSchemeName,
1596       static_cast<int64_t>(secondary_properties2->video_encryption_scheme));
1597   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1598              secondary_properties2->natural_size.width());
1599   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1600              secondary_properties2->natural_size.height());
1601 }
1602
1603 TEST_F(WatchTimeRecorderTest, MultipleSecondaryPropertiesWithFinalize) {
1604   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1605       true, true, false, false, true, true, false,
1606       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1607   mojom::SecondaryPlaybackPropertiesPtr secondary_properties1 =
1608       mojom::SecondaryPlaybackProperties::New(
1609           AudioCodec::kOpus, VideoCodec::kVP9, AudioCodecProfile::kUnknown,
1610           VP9PROFILE_PROFILE0, AudioDecoderType::kMojo, VideoDecoderType::kMojo,
1611           EncryptionScheme::kCbcs, EncryptionScheme::kCbcs,
1612           gfx::Size(400, 300));
1613   Initialize(properties.Clone());
1614   wtr_->UpdateSecondaryProperties(secondary_properties1.Clone());
1615
1616   constexpr base::TimeDelta kUnderflowDuration = base::Milliseconds(250);
1617   constexpr base::TimeDelta kWatchTime1 = base::Seconds(54);
1618   const int kUnderflowCount1 = 2;
1619   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime1);
1620   wtr_->UpdateUnderflowCount(kUnderflowCount1);
1621   wtr_->UpdateUnderflowDuration(kUnderflowCount1, kUnderflowDuration);
1622
1623   constexpr int kDecodedFrameCount1 = 10;
1624   constexpr int kDroppedFrameCount1 = 2;
1625   wtr_->UpdateVideoDecodeStats(kDecodedFrameCount1, kDroppedFrameCount1);
1626
1627   // Force a finalize here so that the there is no unfinalized watch time at the
1628   // time of the secondary property update.
1629   wtr_->FinalizeWatchTime({});
1630
1631   mojom::SecondaryPlaybackPropertiesPtr secondary_properties2 =
1632       mojom::SecondaryPlaybackProperties::New(
1633           AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kXHE_AAC,
1634           H264PROFILE_MAIN, AudioDecoderType::kFFmpeg,
1635           VideoDecoderType::kFFmpeg, EncryptionScheme::kUnencrypted,
1636           EncryptionScheme::kUnencrypted, gfx::Size(800, 600));
1637   wtr_->UpdateSecondaryProperties(secondary_properties2.Clone());
1638
1639   constexpr base::TimeDelta kWatchTime2 = base::Seconds(25);
1640   const int kUnderflowCount2 = 3;
1641
1642   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime2);
1643   wtr_->UpdateUnderflowCount(kUnderflowCount2);
1644   wtr_->OnError(PIPELINE_ERROR_DECODE);
1645
1646   wtr_.reset();
1647   base::RunLoop().RunUntilIdle();
1648
1649   // All records should have the following:
1650   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1651   EXPECT_EQ(2u, entries.size());
1652   for (const auto* entry : entries) {
1653     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1654     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1655     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1656     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1657     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1658     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1659     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1660     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1661                static_cast<int64_t>(properties->media_stream_type));
1662     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1663     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1664     EXPECT_NO_UKM(UkmEntry::kDurationName);
1665
1666     // All records inherit the final pipeline status code.
1667     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_ERROR_DECODE);
1668   }
1669
1670   // The first record should have...
1671   auto* entry = entries[0];
1672   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime1.InMilliseconds());
1673   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1674              kWatchTime1.InMilliseconds() / kUnderflowCount1);
1675   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 2);
1676   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 5);
1677   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount1);
1678   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, kUnderflowCount1);
1679   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName,
1680              kUnderflowDuration.InMilliseconds());
1681   EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, kDecodedFrameCount1);
1682   EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, kDroppedFrameCount1);
1683   EXPECT_UKM(UkmEntry::kAudioCodecName,
1684              static_cast<int>(secondary_properties1->audio_codec));
1685   EXPECT_UKM(UkmEntry::kVideoCodecName,
1686              static_cast<int>(secondary_properties1->video_codec));
1687   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1688              static_cast<int64_t>(secondary_properties1->audio_codec_profile));
1689   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1690              secondary_properties1->video_codec_profile);
1691   EXPECT_UKM(
1692       UkmEntry::kAudioEncryptionSchemeName,
1693       static_cast<int64_t>(secondary_properties1->audio_encryption_scheme));
1694   EXPECT_UKM(
1695       UkmEntry::kVideoEncryptionSchemeName,
1696       static_cast<int64_t>(secondary_properties1->video_encryption_scheme));
1697   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1698              secondary_properties1->natural_size.width());
1699   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1700              secondary_properties1->natural_size.height());
1701
1702   // The second record should have...
1703   entry = entries[1];
1704   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime2.InMilliseconds());
1705   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1706              kWatchTime2.InMilliseconds() / kUnderflowCount2);
1707   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 1);
1708   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 2);
1709   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount2);
1710   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 0);
1711   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName, 0);
1712   EXPECT_UKM(UkmEntry::kVideoFramesDecodedName, 0);
1713   EXPECT_UKM(UkmEntry::kVideoFramesDroppedName, 0);
1714   EXPECT_UKM(UkmEntry::kAudioCodecName,
1715              static_cast<int>(secondary_properties2->audio_codec));
1716   EXPECT_UKM(UkmEntry::kVideoCodecName,
1717              static_cast<int>(secondary_properties2->video_codec));
1718   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1719              static_cast<int64_t>(secondary_properties2->audio_codec_profile));
1720   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1721              secondary_properties2->video_codec_profile);
1722   EXPECT_UKM(
1723       UkmEntry::kAudioEncryptionSchemeName,
1724       static_cast<int64_t>(secondary_properties2->audio_encryption_scheme));
1725   EXPECT_UKM(
1726       UkmEntry::kVideoEncryptionSchemeName,
1727       static_cast<int64_t>(secondary_properties2->video_encryption_scheme));
1728   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1729              secondary_properties2->natural_size.width());
1730   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1731              secondary_properties2->natural_size.height());
1732 }
1733
1734 TEST_F(WatchTimeRecorderTest, MultipleSecondaryPropertiesRebufferCarryover) {
1735   mojom::PlaybackPropertiesPtr properties = mojom::PlaybackProperties::New(
1736       true, true, false, false, true, true, false,
1737       mojom::MediaStreamType::kNone, RendererType::kRendererImpl);
1738   mojom::SecondaryPlaybackPropertiesPtr secondary_properties1 =
1739       mojom::SecondaryPlaybackProperties::New(
1740           AudioCodec::kOpus, VideoCodec::kVP9, AudioCodecProfile::kUnknown,
1741           VP9PROFILE_PROFILE0, AudioDecoderType::kMojo, VideoDecoderType::kMojo,
1742           EncryptionScheme::kCbcs, EncryptionScheme::kCbcs,
1743           gfx::Size(400, 300));
1744   Initialize(properties.Clone());
1745   wtr_->UpdateSecondaryProperties(secondary_properties1.Clone());
1746
1747   constexpr base::TimeDelta kUnderflowDuration = base::Milliseconds(250);
1748   constexpr base::TimeDelta kWatchTime1 = base::Seconds(54);
1749   const int kUnderflowCount1 = 2;
1750   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll, kWatchTime1);
1751   wtr_->UpdateUnderflowCount(kUnderflowCount1);
1752
1753   // Complete all but one of the rebuffers in this update.
1754   wtr_->UpdateUnderflowDuration(kUnderflowCount1 - 1, kUnderflowDuration);
1755
1756   mojom::SecondaryPlaybackPropertiesPtr secondary_properties2 =
1757       mojom::SecondaryPlaybackProperties::New(
1758           AudioCodec::kAAC, VideoCodec::kH264, AudioCodecProfile::kXHE_AAC,
1759           H264PROFILE_MAIN, AudioDecoderType::kFFmpeg,
1760           VideoDecoderType::kFFmpeg, EncryptionScheme::kUnencrypted,
1761           EncryptionScheme::kUnencrypted, gfx::Size(800, 600));
1762   wtr_->UpdateSecondaryProperties(secondary_properties2.Clone());
1763
1764   constexpr base::TimeDelta kWatchTime2 = base::Seconds(25);
1765   const int kUnderflowCount2 = 3;
1766
1767   // Watch time and underflow counts continue to accumulate during property
1768   // changes, so we report the sum here instead of just kWatchTime2.
1769   wtr_->RecordWatchTime(WatchTimeKey::kAudioVideoAll,
1770                         kWatchTime1 + kWatchTime2);
1771   wtr_->UpdateUnderflowCount(kUnderflowCount1 + kUnderflowCount2);
1772
1773   // Complete the last underflow in the new property set. Unfortunately this
1774   // means it will now be associated with this block of watch time. Use a non
1775   // integer multiplier to avoid incorrect carry over being hidden.
1776   wtr_->UpdateUnderflowDuration(kUnderflowCount1, kUnderflowDuration * 1.5);
1777
1778   wtr_->OnError(PIPELINE_ERROR_DECODE);
1779   wtr_->OnDurationChanged(base::Seconds(5125));
1780
1781   wtr_.reset();
1782   base::RunLoop().RunUntilIdle();
1783
1784   // All records should have the following:
1785   const auto& entries = test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
1786   EXPECT_EQ(2u, entries.size());
1787   for (const auto* entry : entries) {
1788     test_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestOrigin));
1789     EXPECT_UKM(UkmEntry::kIsBackgroundName, properties->is_background);
1790     EXPECT_UKM(UkmEntry::kIsMutedName, properties->is_muted);
1791     EXPECT_UKM(UkmEntry::kHasAudioName, properties->has_audio);
1792     EXPECT_UKM(UkmEntry::kHasVideoName, properties->has_video);
1793     EXPECT_UKM(UkmEntry::kIsEMEName, properties->is_eme);
1794     EXPECT_UKM(UkmEntry::kIsMSEName, properties->is_mse);
1795     EXPECT_UKM(UkmEntry::kMediaStreamTypeName,
1796                static_cast<int64_t>(properties->media_stream_type));
1797     EXPECT_UKM(UkmEntry::kAutoplayInitiatedName, false);
1798     EXPECT_UKM(UkmEntry::kDurationName, 5000000);
1799     EXPECT_HAS_UKM(UkmEntry::kPlayerIDName);
1800
1801     // All records inherit the final pipeline status code.
1802     EXPECT_UKM(UkmEntry::kLastPipelineStatusName, PIPELINE_ERROR_DECODE);
1803   }
1804
1805   // The first record should have...
1806   auto* entry = entries[0];
1807   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime1.InMilliseconds());
1808   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1809              kWatchTime1.InMilliseconds() / kUnderflowCount1);
1810   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 2);
1811   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 5);
1812   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount1);
1813   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, kUnderflowCount1 - 1);
1814   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName,
1815              kUnderflowDuration.InMilliseconds());
1816   EXPECT_UKM(UkmEntry::kAudioCodecName,
1817              static_cast<int>(secondary_properties1->audio_codec));
1818   EXPECT_UKM(UkmEntry::kVideoCodecName,
1819              static_cast<int>(secondary_properties1->video_codec));
1820   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1821              static_cast<int64_t>(secondary_properties1->audio_codec_profile));
1822   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1823              secondary_properties1->video_codec_profile);
1824   EXPECT_UKM(
1825       UkmEntry::kAudioEncryptionSchemeName,
1826       static_cast<int64_t>(secondary_properties1->audio_encryption_scheme));
1827   EXPECT_UKM(
1828       UkmEntry::kVideoEncryptionSchemeName,
1829       static_cast<int64_t>(secondary_properties1->video_encryption_scheme));
1830   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1831              secondary_properties1->natural_size.width());
1832   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1833              secondary_properties1->natural_size.height());
1834
1835   // The second record should have...
1836   entry = entries[1];
1837   EXPECT_UKM(UkmEntry::kWatchTimeName, kWatchTime2.InMilliseconds());
1838   EXPECT_UKM(UkmEntry::kMeanTimeBetweenRebuffersName,
1839              kWatchTime2.InMilliseconds() / kUnderflowCount2);
1840   EXPECT_UKM(UkmEntry::kAudioDecoderNameName, 1);
1841   EXPECT_UKM(UkmEntry::kVideoDecoderNameName, 2);
1842   EXPECT_UKM(UkmEntry::kRebuffersCountName, kUnderflowCount2);
1843   EXPECT_UKM(UkmEntry::kCompletedRebuffersCountName, 1);
1844   EXPECT_UKM(UkmEntry::kCompletedRebuffersDurationName,
1845              (kUnderflowDuration * 1.5 - kUnderflowDuration).InMilliseconds());
1846   EXPECT_UKM(UkmEntry::kAudioCodecName,
1847              static_cast<int>(secondary_properties2->audio_codec));
1848   EXPECT_UKM(UkmEntry::kVideoCodecName,
1849              static_cast<int>(secondary_properties2->video_codec));
1850   EXPECT_UKM(UkmEntry::kAudioCodecProfileName,
1851              static_cast<int64_t>(secondary_properties2->audio_codec_profile));
1852   EXPECT_UKM(UkmEntry::kVideoCodecProfileName,
1853              secondary_properties2->video_codec_profile);
1854   EXPECT_UKM(
1855       UkmEntry::kAudioEncryptionSchemeName,
1856       static_cast<int64_t>(secondary_properties2->audio_encryption_scheme));
1857   EXPECT_UKM(
1858       UkmEntry::kVideoEncryptionSchemeName,
1859       static_cast<int64_t>(secondary_properties2->video_encryption_scheme));
1860   EXPECT_UKM(UkmEntry::kVideoNaturalWidthName,
1861              secondary_properties2->natural_size.width());
1862   EXPECT_UKM(UkmEntry::kVideoNaturalHeightName,
1863              secondary_properties2->natural_size.height());
1864 }
1865
1866 #undef EXPECT_UKM
1867 #undef EXPECT_NO_UKM
1868 #undef EXPECT_HAS_UKM
1869
1870 }  // namespace media