blob: 32eb8b877500ae663ac1a95d90fd3880b03718ae [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/android/chrome_jni_headers/ChromePowerModeVoter_jni.h"
#include <memory>
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "components/power_scheduler/power_mode.h"
#include "components/power_scheduler/power_mode_arbiter.h"
#include "components/power_scheduler/power_mode_voter.h"
#include "content/public/browser/browser_thread.h"
namespace {
// Only accessed on the Android UI thread and only after native initialization
// which means its well after C++ initialization order issues. We could make
// these static variables inside recordViewTreeDrawsUMA() to prevent them being
// global but it would add a thread safe access on a hot UI path so we avoid
// that here.
base::TimeTicks g_android_view_ondraw_emitted = base::TimeTicks();
int g_android_view_ondraw_count = 0;
void RecordOnViewTreeDrawUMA() {
DCHECK(!content::BrowserThread::IsThreadInitialized(
content::BrowserThread::UI) ||
content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// This is the first onDraw we've seen so start counting from now.
if (g_android_view_ondraw_emitted.is_null()) {
g_android_view_ondraw_count = 1;
g_android_view_ondraw_emitted = base::TimeTicks::Now();
return;
}
base::TimeTicks curr = base::TimeTicks::Now();
if (curr - g_android_view_ondraw_emitted > base::Seconds(30)) {
// a 144hz monitor refreshes 120 times a second so 3600 frames in 30
// seconds. So 10000 should be more than enough for now (famous last words).
UMA_HISTOGRAM_COUNTS_10000("Android.View.onDraw.30Seconds",
g_android_view_ondraw_count);
g_android_view_ondraw_emitted = curr;
g_android_view_ondraw_count = 1;
return;
}
++g_android_view_ondraw_count;
}
} // namespace
static void JNI_ChromePowerModeVoter_OnChromeActivityStateChange(
JNIEnv* env,
jboolean active) {
static base::NoDestructor<std::unique_ptr<power_scheduler::PowerModeVoter>>
voter(power_scheduler::PowerModeArbiter::GetInstance()->NewVoter(
"PowerModeVoter.NonWebActivity"));
(*voter)->VoteFor(active ? power_scheduler::PowerMode::kIdle
: power_scheduler::PowerMode::kNonWebActivity);
}
static void JNI_ChromePowerModeVoter_OnViewTreeDraw(JNIEnv* env) {
static base::NoDestructor<power_scheduler::DebouncedPowerModeVoter> voter(
"PowerModeVoter.Animation.Java",
power_scheduler::PowerModeVoter::kAnimationTimeout);
RecordOnViewTreeDrawUMA();
voter->VoteFor(power_scheduler::PowerMode::kAnimation);
voter->ResetVoteAfterTimeout();
}
static void JNI_ChromePowerModeVoter_OnCoordinatorTouchEvent(JNIEnv* env) {
static base::NoDestructor<std::unique_ptr<power_scheduler::PowerModeVoter>>
voter(power_scheduler::PowerModeArbiter::GetInstance()->NewVoter(
"PowerModeVoter.Input.Java"));
(*voter)->VoteFor(power_scheduler::PowerMode::kResponse);
(*voter)->ResetVoteAfterTimeout(
power_scheduler::PowerModeVoter::kResponseTimeout);
}