Commit 73f259d2 authored by Polina Bondarenko's avatar Polina Bondarenko Committed by Commit Bot

arc: data_snapshotd: LoadSnapshot impl

Before starting ARC container or VM try to load a snapshot if available.
ARC data snapshots are loaded only for MGS. If there is no snapshot or
the process fails, start ARC session as usual.

BUG=b:161221001
TEST=components_unittests
TEST=unit_tests

Change-Id: I7e222f9abd11b0471a40a475c73931886582bf55
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2498488
Auto-Submit: Polina Bondarenko <pbond@chromium.org>
Commit-Queue: Polina Bondarenko <pbond@chromium.org>
Reviewed-by: default avatarOleksandr Peletskyi <peletskyi@chromium.org>
Reviewed-by: default avatarYusuke Sato <yusukes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829117}
parent d246c5d4
...@@ -261,6 +261,7 @@ static_library("arc_base") { ...@@ -261,6 +261,7 @@ static_library("arc_base") {
"//chromeos/memory:memory", "//chromeos/memory:memory",
"//chromeos/system:system", "//chromeos/system:system",
"//components/account_id", "//components/account_id",
"//components/arc/enterprise",
"//components/keyed_service/content", "//components/keyed_service/content",
"//components/prefs", "//components/prefs",
"//components/user_manager", "//components/user_manager",
......
...@@ -128,5 +128,19 @@ void ArcDataSnapshotdBridge::TakeSnapshot( ...@@ -128,5 +128,19 @@ void ArcDataSnapshotdBridge::TakeSnapshot(
std::move(callback).Run(true /* success */); std::move(callback).Run(true /* success */);
} }
void ArcDataSnapshotdBridge::LoadSnapshot(
const std::string& account_id,
base::OnceCallback<void(bool, bool)> callback) {
if (!is_available_) {
LOG(ERROR) << "LoadSnapshot call when D-Bus service is not available.";
std::move(callback).Run(false /* success */, false /* last */);
return;
}
VLOG(1) << "LoadSnapshot via D-Bus";
NOTIMPLEMENTED();
std::move(callback).Run(true /* success */, true /* last */);
}
} // namespace data_snapshotd } // namespace data_snapshotd
} // namespace arc } // namespace arc
...@@ -31,6 +31,8 @@ class ArcDataSnapshotdBridge { ...@@ -31,6 +31,8 @@ class ArcDataSnapshotdBridge {
void ClearSnapshot(bool last, base::OnceCallback<void(bool)> callback); void ClearSnapshot(bool last, base::OnceCallback<void(bool)> callback);
void TakeSnapshot(const std::string& account_id, void TakeSnapshot(const std::string& account_id,
base::OnceCallback<void(bool)> callback); base::OnceCallback<void(bool)> callback);
void LoadSnapshot(const std::string& account_id,
base::OnceCallback<void(bool, bool)> callback);
bool is_available_for_testing() { return is_available_; } bool is_available_for_testing() { return is_available_; }
......
...@@ -320,6 +320,23 @@ void ArcDataSnapshotdManager::EnsureDaemonStopped(base::OnceClosure callback) { ...@@ -320,6 +320,23 @@ void ArcDataSnapshotdManager::EnsureDaemonStopped(base::OnceClosure callback) {
StopDaemon(std::move(callback)); StopDaemon(std::move(callback));
} }
void ArcDataSnapshotdManager::StartLoadingSnapshot(base::OnceClosure callback) {
// Do not load a snapshot if it's not a normal MGS setup.
if (state_ != State::kNone) {
std::move(callback).Run();
return;
}
std::string account_id = GetCryptohomeAccountId();
if (!account_id.empty() && IsSnapshotEnabled() &&
(snapshot_.last() || snapshot_.previous())) {
EnsureDaemonStarted(base::BindOnce(
&ArcDataSnapshotdManager::LoadSnapshot, weak_ptr_factory_.GetWeakPtr(),
std::move(account_id), std::move(callback)));
return;
}
std::move(callback).Run();
}
bool ArcDataSnapshotdManager::IsAutoLoginConfigured() { bool ArcDataSnapshotdManager::IsAutoLoginConfigured() {
switch (state_) { switch (state_) {
case ArcDataSnapshotdManager::State::kBlockedUi: case ArcDataSnapshotdManager::State::kBlockedUi:
...@@ -328,6 +345,7 @@ bool ArcDataSnapshotdManager::IsAutoLoginConfigured() { ...@@ -328,6 +345,7 @@ bool ArcDataSnapshotdManager::IsAutoLoginConfigured() {
return true; return true;
case ArcDataSnapshotdManager::State::kNone: case ArcDataSnapshotdManager::State::kNone:
case ArcDataSnapshotdManager::State::kRestored: case ArcDataSnapshotdManager::State::kRestored:
case ArcDataSnapshotdManager::State::kRunning:
return false; return false;
} }
} }
...@@ -338,6 +356,7 @@ bool ArcDataSnapshotdManager::IsAutoLoginAllowed() { ...@@ -338,6 +356,7 @@ bool ArcDataSnapshotdManager::IsAutoLoginAllowed() {
return false; return false;
case ArcDataSnapshotdManager::State::kNone: case ArcDataSnapshotdManager::State::kNone:
case ArcDataSnapshotdManager::State::kRestored: case ArcDataSnapshotdManager::State::kRestored:
case ArcDataSnapshotdManager::State::kRunning:
case ArcDataSnapshotdManager::State::kMgsLaunched: case ArcDataSnapshotdManager::State::kMgsLaunched:
case ArcDataSnapshotdManager::State::kMgsToLaunch: case ArcDataSnapshotdManager::State::kMgsToLaunch:
return true; return true;
...@@ -365,9 +384,17 @@ void ArcDataSnapshotdManager::OnSessionStateChanged() { ...@@ -365,9 +384,17 @@ void ArcDataSnapshotdManager::OnSessionStateChanged() {
return; return;
} }
break; break;
case ArcDataSnapshotdManager::State::kBlockedUi: case State::kRunning:
case ArcDataSnapshotdManager::State::kNone: if (user_manager::UserManager::Get() &&
case ArcDataSnapshotdManager::State::kRestored: user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()) {
return;
}
// It is a correct state. Exit MGS withg loaded snapshot.
state_ = State::kNone;
return;
case State::kBlockedUi:
case State::kNone:
case State::kRestored:
break; break;
} }
} }
...@@ -438,6 +465,19 @@ void ArcDataSnapshotdManager::TakeSnapshot(const std::string& account_id) { ...@@ -438,6 +465,19 @@ void ArcDataSnapshotdManager::TakeSnapshot(const std::string& account_id) {
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} }
void ArcDataSnapshotdManager::LoadSnapshot(const std::string& account_id,
base::OnceClosure callback) {
if (!bridge_) {
OnSnapshotLoaded(std::move(callback), false /* success */,
false /* last */);
return;
}
bridge_->LoadSnapshot(
account_id,
base::BindOnce(&ArcDataSnapshotdManager::OnSnapshotLoaded,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ArcDataSnapshotdManager::OnSnapshotsCleared(bool success) { void ArcDataSnapshotdManager::OnSnapshotsCleared(bool success) {
switch (state_) { switch (state_) {
case State::kBlockedUi: case State::kBlockedUi:
...@@ -451,6 +491,7 @@ void ArcDataSnapshotdManager::OnSnapshotsCleared(bool success) { ...@@ -451,6 +491,7 @@ void ArcDataSnapshotdManager::OnSnapshotsCleared(bool success) {
return; return;
case State::kMgsToLaunch: case State::kMgsToLaunch:
case State::kMgsLaunched: case State::kMgsLaunched:
case State::kRunning:
LOG(WARNING) << "Snapshots are cleared while in incorrect state"; LOG(WARNING) << "Snapshots are cleared while in incorrect state";
return; return;
} }
...@@ -532,17 +573,8 @@ void ArcDataSnapshotdManager::OnArcInstanceStopped(bool success) { ...@@ -532,17 +573,8 @@ void ArcDataSnapshotdManager::OnArcInstanceStopped(bool success) {
OnSnapshotTaken(false /* success */); OnSnapshotTaken(false /* success */);
return; return;
} }
std::string account_id = ""; std::string account_id = GetCryptohomeAccountId();
// Take snapshots only for MGSs. if (account_id.empty() || state_ != State::kMgsLaunched) {
if (user_manager::UserManager::Get() &&
user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() &&
state_ == State::kMgsLaunched &&
user_manager::UserManager::Get()->GetActiveUser()) {
cryptohome::Identification id(
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId());
account_id = id.id();
}
if (account_id.empty()) {
LOG(ERROR) << "Cryptohome account ID is empty."; LOG(ERROR) << "Cryptohome account ID is empty.";
OnSnapshotTaken(false /* success */); OnSnapshotTaken(false /* success */);
return; return;
...@@ -565,5 +597,36 @@ void ArcDataSnapshotdManager::OnSnapshotTaken(bool success) { ...@@ -565,5 +597,36 @@ void ArcDataSnapshotdManager::OnSnapshotTaken(bool success) {
EnsureDaemonStopped(std::move(attempt_user_exit_callback_)); EnsureDaemonStopped(std::move(attempt_user_exit_callback_));
} }
void ArcDataSnapshotdManager::OnSnapshotLoaded(base::OnceClosure callback,
bool success,
bool last) {
if (!success) {
LOG(ERROR) << "Failed to load ARC data directory snapshot.";
std::move(callback).Run();
return;
}
VLOG(1) << "Successfully loaded " << (last ? "last" : "previous")
<< " snapshot";
state_ = State::kRunning;
// Clear last snapshot if the previous one was loaded.
if (!last && snapshot_.last())
snapshot_.ClearSnapshot(true /* last */);
EnsureDaemonStopped(base::DoNothing());
std::move(callback).Run();
}
std::string ArcDataSnapshotdManager::GetCryptohomeAccountId() {
// Take snapshots only for MGSs.
if (user_manager::UserManager::Get() &&
user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() &&
user_manager::UserManager::Get()->GetActiveUser()) {
return cryptohome::Identification(user_manager::UserManager::Get()
->GetActiveUser()
->GetAccountId())
.id();
}
return "";
}
} // namespace data_snapshotd } // namespace data_snapshotd
} // namespace arc } // namespace arc
...@@ -36,6 +36,8 @@ class ArcDataSnapshotdManager final ...@@ -36,6 +36,8 @@ class ArcDataSnapshotdManager final
kNone, kNone,
// Blocked UI mode is ON. // Blocked UI mode is ON.
kBlockedUi, kBlockedUi,
// Running with a snapshot.
kRunning,
// In blocked UI mode, MGS can be launched. // In blocked UI mode, MGS can be launched.
kMgsToLaunch, kMgsToLaunch,
// MGS is launched to create a snapshot. // MGS is launched to create a snapshot.
...@@ -187,6 +189,10 @@ class ArcDataSnapshotdManager final ...@@ -187,6 +189,10 @@ class ArcDataSnapshotdManager final
// Stops arc-data-snapshotd. // Stops arc-data-snapshotd.
void EnsureDaemonStopped(base::OnceClosure callback); void EnsureDaemonStopped(base::OnceClosure callback);
// Starts loading a snapshot to android-data directory.
// |callback| is called once the process is over.
void StartLoadingSnapshot(base::OnceClosure callback);
// Returns true if autologin to public account should be performed. // Returns true if autologin to public account should be performed.
bool IsAutoLoginConfigured(); bool IsAutoLoginConfigured();
// Returns true if autologin is allowed to be performed and manager is not // Returns true if autologin is allowed to be performed and manager is not
...@@ -231,6 +237,7 @@ class ArcDataSnapshotdManager final ...@@ -231,6 +237,7 @@ class ArcDataSnapshotdManager final
void GenerateKeyPair(); void GenerateKeyPair();
void ClearSnapshot(bool last, base::OnceCallback<void(bool)> callback); void ClearSnapshot(bool last, base::OnceCallback<void(bool)> callback);
void TakeSnapshot(const std::string& account_id); void TakeSnapshot(const std::string& account_id);
void LoadSnapshot(const std::string& account_id, base::OnceClosure callback);
// Called once the outdated snapshots were removed or ensured that there are // Called once the outdated snapshots were removed or ensured that there are
// no outdated snapshots. // no outdated snapshots.
...@@ -254,6 +261,13 @@ class ArcDataSnapshotdManager final ...@@ -254,6 +261,13 @@ class ArcDataSnapshotdManager final
// Called once a snapshot is taken. // Called once a snapshot is taken.
void OnSnapshotTaken(bool success); void OnSnapshotTaken(bool success);
// Called once a snapshot is taken.
void OnSnapshotLoaded(base::OnceClosure callback, bool success, bool last);
// Returns non-empty account ID string if a MGS is active.
// Otherwise returns an empty string.
std::string GetCryptohomeAccountId();
static bool is_snapshot_enabled_for_testing_; static bool is_snapshot_enabled_for_testing_;
State state_ = State::kNone; State state_ = State::kNone;
Snapshot snapshot_; Snapshot snapshot_;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "chromeos/system/scheduler_configuration_manager_base.h" #include "chromeos/system/scheduler_configuration_manager_base.h"
#include "components/arc/arc_features.h" #include "components/arc/arc_features.h"
#include "components/arc/arc_util.h" #include "components/arc/arc_util.h"
#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
#include "components/arc/session/arc_bridge_host_impl.h" #include "components/arc/session/arc_bridge_host_impl.h"
#include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager.h"
#include "components/version_info/channel.h" #include "components/version_info/channel.h"
...@@ -531,7 +532,23 @@ void ArcSessionImpl::OnSocketCreated(base::ScopedFD socket_fd) { ...@@ -531,7 +532,23 @@ void ArcSessionImpl::OnSocketCreated(base::ScopedFD socket_fd) {
return; return;
} }
VLOG(2) << "Socket is created. Starting ARC container"; VLOG(2) << "Socket is created. Start loading ARC data snapshot";
StartLoadingDataSnapshot(base::BindOnce(&ArcSessionImpl::OnDataSnapshotLoaded,
weak_factory_.GetWeakPtr(),
std::move(socket_fd)));
}
void ArcSessionImpl::StartLoadingDataSnapshot(base::OnceClosure callback) {
auto* arc_data_snapshotd_manager =
arc::data_snapshotd::ArcDataSnapshotdManager::Get();
if (arc_data_snapshotd_manager)
arc_data_snapshotd_manager->StartLoadingSnapshot(std::move(callback));
else
std::move(callback).Run();
}
void ArcSessionImpl::OnDataSnapshotLoaded(base::ScopedFD socket_fd) {
VLOG(2) << "Starting ARC container";
client_->UpgradeArc( client_->UpgradeArc(
std::move(upgrade_params_), std::move(upgrade_params_),
base::BindOnce(&ArcSessionImpl::OnUpgraded, weak_factory_.GetWeakPtr(), base::BindOnce(&ArcSessionImpl::OnUpgraded, weak_factory_.GetWeakPtr(),
......
...@@ -217,6 +217,15 @@ class ArcSessionImpl ...@@ -217,6 +217,15 @@ class ArcSessionImpl
// Called when arcbridge socket is created. // Called when arcbridge socket is created.
void OnSocketCreated(base::ScopedFD fd); void OnSocketCreated(base::ScopedFD fd);
// Loads ARC data/ snapshot if necessary.
// |callback| is called once the load process is finished.
void StartLoadingDataSnapshot(base::OnceClosure callback);
// Called when ARC data/ snapshot step is done: either snapshot is loaded or
// skipped.
// |socket_fd| should be a socket to be passed to OnUpgraded.
void OnDataSnapshotLoaded(base::ScopedFD scoped_fd);
// D-Bus callback for UpgradeArcContainer(). |socket_fd| should be a socket // D-Bus callback for UpgradeArcContainer(). |socket_fd| should be a socket
// which should be accept(2)ed to connect ArcBridgeService Mojo channel. // which should be accept(2)ed to connect ArcBridgeService Mojo channel.
void OnUpgraded(base::ScopedFD socket_fd, bool result); void OnUpgraded(base::ScopedFD socket_fd, bool result);
......
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