blob: 3dfa2495a3ab5ccd253b5d7621b35200363253f4 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_METRICS_LOGIN_UNLOCK_THROUGHPUT_RECORDER_H_
#define ASH_METRICS_LOGIN_UNLOCK_THROUGHPUT_RECORDER_H_
#include <optional>
#include <string>
#include "ash/ash_export.h"
#include "ash/metrics/ui_metrics_recorder.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/public/cpp/shelf_types.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/deferred_sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "cc/metrics/frame_sequence_metrics.h"
#include "chromeos/ash/components/login/login_state/login_state.h"
#include "ui/compositor/total_animation_throughput_reporter.h"
namespace ui {
class Compositor;
}
namespace ash {
class ShelfModel;
class ASH_EXPORT LoginUnlockThroughputRecorder : public SessionObserver,
public LoginState::Observer {
public:
enum RestoreWindowType {
kBrowser,
kArc,
};
LoginUnlockThroughputRecorder();
LoginUnlockThroughputRecorder(const LoginUnlockThroughputRecorder&) = delete;
LoginUnlockThroughputRecorder& operator=(
const LoginUnlockThroughputRecorder&) = delete;
~LoginUnlockThroughputRecorder() override;
// ShellObserver:
void OnLockStateChanged(bool locked) override;
// LoginState::Observer:
void LoggedInStateChanged() override;
// Adds "restore_window_id" to the list of potentially restored windows.
// See
// https://source.chromium.org/chromium/chromium/src/+/main:ui/views/widget/widget.h;l=404-415.
void AddScheduledRestoreWindow(int restore_window_id,
const std::string& app_id,
RestoreWindowType window_type);
// This is called when restored window was created.
void OnRestoredWindowCreated(int restore_window_id);
// This is called before window is shown to request presentation feedback.
void OnBeforeRestoredWindowShown(int restore_window_id,
ui::Compositor* compositor);
// This is called when restored window was presented.
void OnRestoredWindowPresented(int restore_window_id);
// This is called when the list of shelf icons is initialized.
void InitShelfIconList(const ShelfModel* model);
// This is called when the list of shelf icons is updated.
void UpdateShelfIconList(const ShelfModel* model);
// This is called when ARC++ becomes enabled.
void OnArcOptedIn();
// This is called when list of ARC++ apps is updated.
void OnArcAppListReady();
// This is called when cryptohome was successfully created/unlocked.
void OnAuthSuccess();
// This is true if we need to report Ash.ArcAppInitialAppsInstallDuration
// histogram in this session but it has not been reported yet.
bool NeedReportArcAppListReady() const;
void ResetScopedThroughputReporterBlockerForTesting();
const ui::TotalAnimationThroughputReporter*
login_animation_throughput_reporter() const {
return login_animation_throughput_reporter_.get();
}
// Add a time marker for login animations events. A timeline will be sent to
// tracing after login is done.
void AddLoginTimeMarker(const std::string& marker_name);
// This flag signals that all expected browser windows are already scheduled.
void BrowserSessionRestoreDataLoaded();
// This flag signals that Full Session restore has reported all the expected
// windows to be created.
void FullSessionRestoreDataLoaded();
// Records that ARC has finished booting.
void ArcUiAvailableAfterLogin();
base::SequencedTaskRunner* post_login_deferred_task_runner() const {
return post_login_deferred_task_runner_.get();
}
void SetLoginFinishedReportedForTesting();
private:
class TimeMarker {
public:
explicit TimeMarker(const std::string& name);
TimeMarker(const TimeMarker& other) = default;
~TimeMarker() = default;
const std::string& name() const { return name_; }
base::TimeTicks time() const { return time_; }
// Comparator for sorting.
bool operator<(const TimeMarker& other) const {
return time_ < other.time_;
}
private:
friend class std::vector<TimeMarker>;
const std::string name_;
const base::TimeTicks time_ = base::TimeTicks::Now();
};
void OnLoginAnimationFinish(
base::TimeTicks start,
const cc::FrameSequenceMetrics::CustomReportData& data);
void ScheduleWaitForShelfAnimationEndIfNeeded();
void OnAllExpectedShelfIconsLoaded();
void MaybeReportLoginFinished();
void OnLoginAnimationFinishedTimerFired();
void MaybeRestoreDataLoaded();
// We only want to initialize the slice name on certain expected events.
// If we miss these, it will ne names "Unordered" and we will know that
// we missed the expected event.
void EnsureTracingSliceNamed();
UiMetricsRecorder ui_recorder_;
// Set of window IDs ("restore_window_id") that could be restored but
// for which windows have not been created yet.
base::flat_set<int> windows_to_restore_;
// Set of window IDs ("restore_window_id") that were created as a part of the
// session restore but not yet shown.
base::flat_set<int> restore_windows_not_shown_;
// Set of window IDs ("restore_window_id") that were shown and presentation
// time was requested.
base::flat_set<int> restore_windows_presentation_time_requested_;
// Set of window IDs ("restore_window_id") for which presentation time
// was received.
base::flat_set<int> restore_windows_presented_;
base::TimeTicks primary_user_logged_in_;
bool shelf_initialized_ = false;
// Session restore data comes from chrome::SessionRestore and ash::FullRestore
// independently.
// This flag is true after SessionRestore has finished loading its data.
bool browser_session_restore_data_loaded_ = false;
// This flag is true after FullRestore has finished loading its data.
bool full_session_restore_data_loaded_ = false;
// All restored windows are known. If the list is empty we know that windows
// will not be restored at this point.
bool restore_data_loaded_ = false;
// |has_pending_icon_| is true when last shelf icons update had an item
// pending icon load.
bool has_pending_icon_ = false;
// |shelf_icons_loaded_| is true when shelf icons are considered loaded,
// i.e. |has_pending_icon_| is true and first resored browser window was
// created.
bool shelf_icons_loaded_ = false;
bool user_logged_in_ = false;
bool arc_app_list_ready_reported_ = false;
bool all_restored_windows_presented_ = false;
bool shelf_animation_end_scheduled_ = false;
bool shelf_animation_finished_ = false;
bool login_animation_throughput_received_ = false;
bool login_finished_reported_ = false;
// |browser_windows_will_not_be_restored_| is true when session restore
// window list is empty.
bool browser_windows_will_not_be_restored_ = false;
// This is a signal that current list of expected windows to be restored is
// final.
bool first_restored_window_created_ = false;
std::optional<base::TimeTicks> arc_opt_in_time_;
base::WeakPtr<ui::TotalAnimationThroughputReporter>
login_animation_throughput_reporter_;
std::unique_ptr<
ui::TotalAnimationThroughputReporter::ScopedThroughputReporterBlocker>
scoped_throughput_reporter_blocker_;
std::vector<TimeMarker> login_time_markers_;
// Timer that sets the limit to wait for the login animation to finish
// before scheduling post-login tasks.
base::OneShotTimer login_animation_finished_timer_;
// Deferred task runner for the post-login tasks.
scoped_refptr<base::DeferredSequencedTaskRunner>
post_login_deferred_task_runner_;
base::WeakPtrFactory<LoginUnlockThroughputRecorder> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_METRICS_LOGIN_UNLOCK_THROUGHPUT_RECORDER_H_