// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/camera/autozoom_controller_impl.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/public/cpp/system/anchored_nudge_manager.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
namespace ash {
AutozoomControllerImpl::AutozoomControllerImpl()
: nudge_controller_(std::make_unique<AutozoomNudgeController>(this)) {
auto* camera_hal_dispatcher = media::CameraHalDispatcherImpl::GetInstance();
if (camera_hal_dispatcher) {
camera_hal_dispatcher->GetAutoFramingSupported(
base::BindOnce(&AutozoomControllerImpl::SetAutozoomSupported,
weak_ptr_factory_.GetWeakPtr()));
camera_hal_dispatcher->AddActiveClientObserver(this);
}
Shell::Get()->session_controller()->AddObserver(this);
}
AutozoomControllerImpl::~AutozoomControllerImpl() {
Shell::Get()->session_controller()->RemoveObserver(this);
auto* camera_hal_dispatcher = media::CameraHalDispatcherImpl::GetInstance();
if (camera_hal_dispatcher) {
camera_hal_dispatcher->RemoveActiveClientObserver(this);
}
}
bool AutozoomControllerImpl::IsAutozoomControlEnabled() {
if (autozoom_supported_for_test_) {
return true;
}
// TODO(b/264472916): Add simon vs. non-simon logic here.
return autozoom_supported_ && active_camera_client_count_ > 0;
}
cros::mojom::CameraAutoFramingState AutozoomControllerImpl::GetState() {
return state_;
}
void AutozoomControllerImpl::SetState(
cros::mojom::CameraAutoFramingState state) {
if (active_user_pref_service_) {
active_user_pref_service_->SetInteger(prefs::kAutozoomState,
static_cast<int32_t>(state));
}
}
void AutozoomControllerImpl::SetAutozoomSupported(bool autozoom_supported) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool orig_control_enabled = IsAutozoomControlEnabled();
autozoom_supported_ = autozoom_supported;
bool control_enabled = IsAutozoomControlEnabled();
if (control_enabled != orig_control_enabled) {
for (auto& observer : observers_)
observer.OnAutozoomControlEnabledChanged(control_enabled);
}
}
void AutozoomControllerImpl::Toggle() {
SetState(state_ == cros::mojom::CameraAutoFramingState::OFF
? cros::mojom::CameraAutoFramingState::ON_SINGLE
: cros::mojom::CameraAutoFramingState::OFF);
AnchoredNudgeManager::Get()->MaybeRecordNudgeAction(
NudgeCatalogName::kAutozoom);
}
void AutozoomControllerImpl::AddObserver(AutozoomObserver* observer) {
observers_.AddObserver(observer);
}
void AutozoomControllerImpl::RemoveObserver(AutozoomObserver* observer) {
observers_.RemoveObserver(observer);
}
void AutozoomControllerImpl::OnActiveUserPrefServiceChanged(
PrefService* pref_service) {
if (pref_service == active_user_pref_service_)
return;
// Initial login and user switching in multi profiles.
active_user_pref_service_ = pref_service;
InitFromUserPrefs();
}
void AutozoomControllerImpl::OnStatePrefChanged() {
Refresh();
}
void AutozoomControllerImpl::Refresh() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (active_user_pref_service_) {
state_ = static_cast<cros::mojom::CameraAutoFramingState>(
active_user_pref_service_->GetInteger(prefs::kAutozoomState));
} else {
state_ = cros::mojom::CameraAutoFramingState::OFF;
}
auto* camera_hal_dispatcher = media::CameraHalDispatcherImpl::GetInstance();
if (camera_hal_dispatcher) {
camera_hal_dispatcher->SetAutoFramingState(state_);
}
for (auto& observer : observers_)
observer.OnAutozoomStateChanged(state_);
}
void AutozoomControllerImpl::StartWatchingPrefsChanges() {
DCHECK(active_user_pref_service_);
pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
pref_change_registrar_->Init(active_user_pref_service_);
pref_change_registrar_->Add(
prefs::kAutozoomState,
base::BindRepeating(&AutozoomControllerImpl::OnStatePrefChanged,
base::Unretained(this)));
}
void AutozoomControllerImpl::InitFromUserPrefs() {
StartWatchingPrefsChanges();
Refresh();
}
void AutozoomControllerImpl::OnActiveClientChange(
cros::mojom::CameraClientType type,
bool is_new_active_client,
const base::flat_set<std::string>& active_device_ids) {
bool orig_control_enabled = IsAutozoomControlEnabled();
if (is_new_active_client) {
active_camera_client_count_++;
} else if (active_device_ids.empty()) {
DCHECK(active_camera_client_count_ > 0);
active_camera_client_count_--;
}
bool control_enabled = IsAutozoomControlEnabled();
if (control_enabled != orig_control_enabled) {
for (auto& observer : observers_)
observer.OnAutozoomControlEnabledChanged(control_enabled);
}
}
// static
void AutozoomControllerImpl::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(
prefs::kAutozoomState,
static_cast<int32_t>(cros::mojom::CameraAutoFramingState::OFF));
}
} // namespace ash