Commit a94e1adf authored by Jia's avatar Jia Committed by Commit Bot

[On-device adaptive brightness] Only adjust brightness after model is sufficiently trained

Adapter now keeps track of number of model iterations and only starts changing
brightness based on min_model_iteration_count.

Bug: 881215
Change-Id: Ie9dcf15090f2e808630ad82a2bd2cfebad7cf00a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1621477
Commit-Queue: Jia Meng <jiameng@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Reviewed-by: default avatarMichael Martis <martis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662908}
parent 260e2831
......@@ -208,6 +208,7 @@ void Adapter::OnUserBrightnessChangeRequested() {
decision_at_first_recent_user_brightness_request_ =
CanAdjustBrightness(now);
first_recent_user_brightness_request_time_ = now;
model_iteration_count_at_user_brightness_change_ = model_.iteration_count;
}
if (params_.user_adjustment_effect != UserAdjustmentEffect::kContinueAuto) {
......@@ -383,6 +384,15 @@ void Adapter::InitParams(const ModelConfig& model_config) {
params_.user_adjustment_effect =
static_cast<UserAdjustmentEffect>(user_adjustment_effect_as_int);
params_.min_model_iteration_count = base::GetFieldTrialParamByFeatureAsInt(
features::kAutoScreenBrightness, "min_model_iteration_count",
params_.min_model_iteration_count);
if (params_.min_model_iteration_count <= 0) {
LogParameterError(ParameterError::kAdapterError);
enabled_by_model_configs_ = false;
return;
}
UMA_HISTOGRAM_ENUMERATION("AutoScreenBrightness.UserAdjustmentEffect",
params_.user_adjustment_effect);
}
......@@ -510,6 +520,13 @@ Adapter::AdapterDecision Adapter::CanAdjustBrightness(base::TimeTicks now) {
return decision;
}
if (params_.model_curve == ModelCurve::kPersonal &&
model_.iteration_count < params_.min_model_iteration_count) {
decision.no_brightness_change_cause =
NoBrightnessChangeCause::kWaitingForTrainedPersonalCurve;
return decision;
}
// Wait until we've had enough ALS data to calc avg.
if (now - als_init_time_ < params_.auto_brightness_als_horizon) {
decision.no_brightness_change_cause =
......@@ -603,6 +620,12 @@ void Adapter::AdjustBrightness(BrightnessChangeCause cause,
UMA_HISTOGRAM_ENUMERATION("AutoScreenBrightness.BrightnessChange.Cause",
cause);
if (params_.model_curve == ModelCurve::kPersonal) {
UMA_HISTOGRAM_COUNTS_1000(
"AutoScreenBrightness.BrightnessChange.ModelIteration",
model_.iteration_count);
}
WriteLogMessages(log_als_avg, brightness, cause);
model_brightness_change_counter_++;
......@@ -764,6 +787,13 @@ void Adapter::LogAdapterDecision(
base::UmaHistogramCounts1000(histogram_prefix + "Unknown.AlsStd",
logged_stddev);
}
// Log model iteration count.
if (params_.model_curve == ModelCurve::kPersonal) {
base::UmaHistogramCounts1000(
histogram_prefix + "ModelIteration",
model_iteration_count_at_user_brightness_change_);
}
}
} // namespace auto_screen_brightness
......
......@@ -86,7 +86,7 @@ class Adapter : public AlsReader::Observer,
double darkening_log_lux_threshold = 0.6;
double stabilization_threshold = 0.15;
ModelCurve model_curve = ModelCurve::kLatest;
ModelCurve model_curve = ModelCurve::kPersonal;
// Average ambient value is calculated over the past
// |auto_brightness_als_horizon|. This is only used for brightness update,
......@@ -98,6 +98,10 @@ class Adapter : public AlsReader::Observer,
UserAdjustmentEffect::kDisableAuto;
std::string metrics_key;
// If |model_curve| is |kPersonal| then we only use a personal curve if the
// the model has been trained at least |min_model_iteration_count|.
int min_model_iteration_count = 1;
};
// These values are persisted to logs. Entries should not be renumbered and
......@@ -143,7 +147,10 @@ class Adapter : public AlsReader::Observer,
kMinimalAlsChange = 7,
// Adapter should only use personal curves but none is available.
kMissingPersonalCurve = 8,
kMaxValue = kMissingPersonalCurve
// Adapter should only use a personal curve that has been trained for a min
// number of iterations.
kWaitingForTrainedPersonalCurve = 9,
kMaxValue = kWaitingForTrainedPersonalCurve
};
struct AdapterDecision {
......@@ -359,6 +366,8 @@ class Adapter : public AlsReader::Observer,
base::Optional<AdapterDecision>
decision_at_first_recent_user_brightness_request_;
int model_iteration_count_at_user_brightness_change_ = 0;
// The thresholds are calculated from the |average_log_ambient_lux_|.
// They are only updated when brightness is changed (either by user or model).
base::Optional<double> brightening_threshold_;
......
......@@ -922,9 +922,77 @@ TEST_F(AdapterTest, UsePersonalCurve) {
adapter_->GetCurrentAvgLogAlsForTesting().value()));
}
TEST_F(AdapterTest, UsePersonalCurveAfter3) {
std::map<std::string, std::string> params = default_params_;
params["model_curve"] = "1";
params["min_model_iteration_count"] = "3";
// Init modeller with only a global curve.
Init(AlsReader::AlsInitStatus::kSuccess, BrightnessMonitor::Status::kSuccess,
Model(global_curve_, base::nullopt, 0), GetTestModelConfig(), params);
EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kSuccess);
// Sufficient ALS data has come in but no brightness change is triggered
// because there is no personal curve.
ForwardTimeAndReportAls({1, 2, 3, 4, 5, 6, 7, 8});
EXPECT_EQ(test_observer_.num_changes(), 0);
EXPECT_EQ(adapter_->GetCurrentAvgLogAlsForTesting(), base::nullopt);
// Personal curve is received, it does not lead to any immediate brightness
// change.
thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
fake_modeller_.ReportModelTrained(*personal_curve_);
EXPECT_EQ(test_observer_.num_changes(), 0);
EXPECT_EQ(adapter_->GetCurrentAvgLogAlsForTesting(), base::nullopt);
// Another ALS comes in, which does not trigger a brightness change.
ReportAls(20);
EXPECT_EQ(test_observer_.num_changes(), 0);
EXPECT_EQ(adapter_->GetCurrentAvgLogAlsForTesting(), base::nullopt);
// Another training is done.
thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
fake_modeller_.ReportModelTrained(*personal_curve_);
EXPECT_EQ(test_observer_.num_changes(), 0);
EXPECT_EQ(adapter_->GetCurrentAvgLogAlsForTesting(), base::nullopt);
// Another ALS comes in, which does not trigger a brightness change.
ReportAls(30);
EXPECT_EQ(test_observer_.num_changes(), 0);
EXPECT_EQ(adapter_->GetCurrentAvgLogAlsForTesting(), base::nullopt);
// Another training is done.
const base::Optional<MonotoneCubicSpline> personal_curve_2 =
MonotoneCubicSpline::CreateMonotoneCubicSpline({-4, 12, 20},
{30, 60, 100});
DCHECK(personal_curve_2);
thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
fake_modeller_.ReportModelTrained(*personal_curve_2);
EXPECT_EQ(test_observer_.num_changes(), 0);
EXPECT_EQ(adapter_->GetCurrentAvgLogAlsForTesting(), base::nullopt);
// Another ALS comes in, which triggers a brightness change.
ReportAls(40);
EXPECT_EQ(test_observer_.num_changes(), 1);
EXPECT_EQ(test_observer_.GetCause(),
power_manager::BacklightBrightnessChange_Cause_MODEL);
CheckAvgLog({7, 8, 20, 30, 40},
adapter_->GetCurrentAvgLogAlsForTesting().value());
// Brightness is changed according to the personal curve.
EXPECT_DOUBLE_EQ(test_observer_.GetBrightnessPercent(),
personal_curve_2->Interpolate(
adapter_->GetCurrentAvgLogAlsForTesting().value()));
}
TEST_F(AdapterTest, UseGlobalCurve) {
std::map<std::string, std::string> params = default_params_;
params["model_curve"] = "0";
// This param has no effect.
params["min_model_iteration_count"] = "3";
Init(AlsReader::AlsInitStatus::kSuccess, BrightnessMonitor::Status::kSuccess,
Model(global_curve_, personal_curve_, 0), GetTestModelConfig(), params);
......
......@@ -4238,6 +4238,7 @@ Unknown properties are collapsed to zero. -->
<int value="6" label="FluctuatingAlsDecrease"/>
<int value="7" label="MinimalAlsChange"/>
<int value="8" label="MissingPersonalCurve"/>
<int value="9" label="WaitingForTrainedPersonalCurve"/>
</enum>
<enum name="AutoScreenBrightnessParameterError">
......@@ -10604,6 +10604,19 @@ uploading your change for review.
</summary>
</histogram>
<histogram base="true"
name="AutoScreenBrightness.AdapterDecisionAtUserChange.ModelIteration"
units="count" expires_after="2019-12-31">
<!-- Name completed by histogram_suffixes name="AdapterDecision" -->
<owner>jiameng@chromium.org</owner>
<summary>
When user changes brightness manually, we will ask the model whether it also
thinks brightness should be changed. We also log the number of model
iterations if we've set to use personal curve only. Chrome OS only.
</summary>
</histogram>
<histogram
name="AutoScreenBrightness.AdapterDecisionAtUserChange.NoBrightnessChange.Cause"
enum="AutoScreenBrightnessNoBrightnessChangeCause"
......@@ -10638,6 +10651,12 @@ uploading your change for review.
</summary>
</histogram>
<histogram name="AutoScreenBrightness.BrightnessChange.Cause"
enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2019-12-31">
<owner>jiameng@chromium.org</owner>
<summary>Reason for the model to change brightness. Chrome OS only.</summary>
</histogram>
<histogram name="AutoScreenBrightness.BrightnessChange.ElapsedTime" units="ms"
expires_after="2019-12-31">
<owner>jiameng@chromium.org</owner>
......@@ -10646,6 +10665,15 @@ uploading your change for review.
</summary>
</histogram>
<histogram name="AutoScreenBrightness.BrightnessChange.ModelIteration"
units="count" expires_after="2019-12-31">
<owner>jiameng@chromium.org</owner>
<summary>
Number of model iterations when brightness is changed by a personal curve.
Chrome OS only.
</summary>
</histogram>
<histogram name="AutoScreenBrightness.BrightnessMonitorStatus"
enum="AutoScreenBrightnessBrightnessMonitorStatus"
expires_after="2019-12-31">
......@@ -145912,6 +145940,8 @@ should be kept until we use this API. -->
name="AutoScreenBrightness.AdapterDecisionAtUserChange.Darken.AlsDelta"/>
<affected-histogram
name="AutoScreenBrightness.AdapterDecisionAtUserChange.Darken.AlsStd"/>
<affected-histogram
name="AutoScreenBrightness.AdapterDecisionAtUserChange.ModelIteration"/>
<affected-histogram
name="AutoScreenBrightness.AdapterDecisionAtUserChange.Unknown.AlsStd"/>
</histogram_suffixes>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment