diff options
author | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-03 00:10:54 +0000 |
---|---|---|
committer | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-03 00:10:54 +0000 |
commit | 88c9f95b1fde5a97ae8ffe96028be8a9e161985d (patch) | |
tree | 277074573350db6c26b8535135b25f8971f7359e /ash | |
parent | a885fb3eb3923eb83e0f635211a98ba4bde5ec89 (diff) | |
download | chromium_src-88c9f95b1fde5a97ae8ffe96028be8a9e161985d.zip chromium_src-88c9f95b1fde5a97ae8ffe96028be8a9e161985d.tar.gz chromium_src-88c9f95b1fde5a97ae8ffe96028be8a9e161985d.tar.bz2 |
ash: Make frequency of video activity reports more reliable.
This makes ash::VideoDetector maintain a circular buffer
containing timestamps of recent updates to each window
instead of maintaining a counter and resetting it once a
second. The old approach resulted in occasional longer
delays between reports of video activity, which could lead
the Chrome OS power manager to erroneously believe that the
activity had stopped.
BUG=265311
Review URL: https://chromiumcodereview.appspot.com/21128004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215414 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/wm/video_detector.cc | 34 | ||||
-rw-r--r-- | ash/wm/video_detector_unittest.cc | 33 |
2 files changed, 48 insertions, 19 deletions
diff --git a/ash/wm/video_detector.cc b/ash/wm/video_detector.cc index 7116bae..743b49c 100644 --- a/ash/wm/video_detector.cc +++ b/ash/wm/video_detector.cc @@ -22,32 +22,38 @@ const double VideoDetector::kNotifyIntervalSec = 1.0; // likely that a video is playing in it. class VideoDetector::WindowInfo { public: - WindowInfo() : num_video_updates_in_second_(0) {} + WindowInfo() : buffer_start_(0), buffer_size_(0) {} - // Handles an update within a window, returning true if this update made us - // believe that a video is playing in the window. true is returned at most - // once per second. + // Handles an update within a window, returning true if it appears that + // video is currently playing in the window. bool RecordUpdateAndCheckForVideo(const gfx::Rect& region, base::TimeTicks now) { if (region.width() < kMinUpdateWidth || region.height() < kMinUpdateHeight) return false; - if (second_start_time_.is_null() || - (now - second_start_time_).InSecondsF() >= 1.0) { - second_start_time_ = now; - num_video_updates_in_second_ = 0; + // If the buffer is full, drop the first timestamp. + if (buffer_size_ == static_cast<size_t>(kMinFramesPerSecond)) { + buffer_start_ = (buffer_start_ + 1) % kMinFramesPerSecond; + buffer_size_--; } - num_video_updates_in_second_++; - return num_video_updates_in_second_ == kMinFramesPerSecond; + update_times_[(buffer_start_ + buffer_size_) % kMinFramesPerSecond] = now; + buffer_size_++; + + return buffer_size_ == static_cast<size_t>(kMinFramesPerSecond) && + (now - update_times_[buffer_start_]).InSecondsF() <= 1.0; } private: - // Number of video-sized updates that we've seen in the second starting at - // |second_start_time_|. (Keeping a rolling window is overkill here.) - int num_video_updates_in_second_; + // Circular buffer containing update times of the last (up to + // |kMinFramesPerSecond|) video-sized updates to this window. + base::TimeTicks update_times_[kMinFramesPerSecond]; + + // Index into |update_times_| of the oldest update. + size_t buffer_start_; - base::TimeTicks second_start_time_; + // Number of updates stored in |update_times_|. + size_t buffer_size_; DISALLOW_COPY_AND_ASSIGN(WindowInfo); }; diff --git a/ash/wm/video_detector_unittest.cc b/ash/wm/video_detector_unittest.cc index 96e0787..01c79cf 100644 --- a/ash/wm/video_detector_unittest.cc +++ b/ash/wm/video_detector_unittest.cc @@ -132,15 +132,38 @@ TEST_F(VideoDetectorTest, Basic) { EXPECT_EQ(0, observer_->num_fullscreens()); EXPECT_EQ(1, observer_->num_not_fullscreens()); - // Spread out the frames over two seconds; we shouldn't detect video. + // Spread out the frames over a longer period of time, but send enough + // over a one-second window that the observer should be notified. observer_->reset_stats(); AdvanceTime(base::TimeDelta::FromSeconds(2)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); + + AdvanceTime(base::TimeDelta::FromMilliseconds(500)); + const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1; + base::TimeDelta kInterval = + base::TimeDelta::FromMilliseconds(1000 / kNumFrames); + for (int i = 0; i < kNumFrames; ++i) { + AdvanceTime(kInterval); detector_->OnWindowPaintScheduled(window.get(), update_region); - AdvanceTime(base::TimeDelta::FromSeconds(1)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) + } + EXPECT_EQ(1, observer_->num_invocations()); + + // Keep going and check that the observer is notified again. + for (int i = 0; i < kNumFrames; ++i) { + AdvanceTime(kInterval); detector_->OnWindowPaintScheduled(window.get(), update_region); - EXPECT_EQ(0, observer_->num_invocations()); + } + EXPECT_EQ(2, observer_->num_invocations()); + + // Send updates at a slower rate and check that the observer isn't notified. + base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds( + 1000 / (VideoDetector::kMinFramesPerSecond - 2)); + for (int i = 0; i < kNumFrames; ++i) { + AdvanceTime(kSlowInterval); + detector_->OnWindowPaintScheduled(window.get(), update_region); + } + EXPECT_EQ(2, observer_->num_invocations()); } TEST_F(VideoDetectorTest, Shutdown) { |