blob: 75deac5d099027d882be754ebe5d9bac01234619 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_MANAGER_H_
#define CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_MANAGER_H_
#include <string>
#include "ash/components/arc/mojom/app.mojom.h"
#include "ash/components/arc/session/connection_holder.h"
#include "ash/components/arc/session/connection_observer.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "chrome/browser/ash/arc/vmm/arc_system_state_observation.h"
#include "chrome/browser/ash/arc/vmm/arc_vmm_swap_scheduler.h"
#include "chrome/browser/ash/arc/vmm/arcvm_working_set_trim_executor.h"
#include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/browser_context.h"
namespace arc {
class ArcBridgeService;
enum class SwapState {
ENABLE,
FORCE_ENABLE,
DISABLE,
};
// ARCVM vmm features manager.
class ArcVmmManager : public KeyedService,
public arc::ConnectionObserver<arc::mojom::AppInstance>,
public ash::ConciergeClient::VmObserver {
public:
class Observer : public base::CheckedObserver {
public:
virtual void OnArcVmSwappingOut() {}
virtual void OnArcVmSwappingIn() {}
protected:
~Observer() override = default;
};
// Returns singleton instance for the given BrowserContext, or nullptr if
// the browser |context| is not allowed to use ARC.
static ArcVmmManager* GetForBrowserContext(content::BrowserContext* context);
static ArcVmmManager* GetForBrowserContextForTesting(
content::BrowserContext* context);
ArcVmmManager(content::BrowserContext* context, ArcBridgeService* bridge);
ArcVmmManager(const ArcVmmManager&) = delete;
ArcVmmManager& operator=(const ArcVmmManager&) = delete;
~ArcVmmManager() override;
// SetSwapState change the ARCVM vmm swap state in crosvm. When swap enabled,
// the crosvm process will be STOP and guest memory will be moved to the
// staging memory.
void SetSwapState(SwapState state);
// Is the ARCVM on "swapped" state. If it's true, the ARC app launch maybe
// slower than usual.
bool IsSwapped() const;
void set_user_id_hash(const std::string& user_id_hash) {
user_id_hash_ = user_id_hash;
}
static void EnsureFactoryBuilt();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// arc::ConnectionObserver:
void OnConnectionReady() override;
void OnConnectionClosed() override;
// ash::ConciergeClient::VmObserver override:
void OnVmSwapping(
const vm_tools::concierge::VmSwappingSignal& signal) override;
private:
friend class ArcVmmManagerTest;
friend class ArcVmmManagerBrowserTest;
// Accelerator target for experimental usage. Ctrl + Alt + Shift + O / P for
// enable or disable vmm swap.
class AcceleratorTarget;
void SendSwapRequest(vm_tools::concierge::SwapOperation operation,
base::OnceClosure success_callback);
// Wrapped function of `SendSwapRequest`. Verify if the latest operation still
// match the calling operation. If so, pass the params to SendSwapRequest, or
// do nothing.
// Prefer use it in the chain of callbacks. Before enable vmm swap, the memory
// shrink may need take several minutes. During this time, if the "disable"
// request come, we need make sure not send the "enable" request after finish
// memory shrink.
void VerifyThenSendSwapRequest(vm_tools::concierge::SwapOperation operation,
base::OnceClosure success_callback);
void SendAggressiveBalloonRequest(bool enable,
base::OnceClosure success_callback);
// Wrapped function of `SendAggressiveBalloonRequest`. Verify if the latest
// operation still match the calling operation. If so, pass the params to
// SendAggressiveBalloonRequest, or do nothing.
// Prefer use it in the chain of callbacks, as the same with
// `VerifyThenSendSwapRequest`.
void VerifyThenSendAggressiveBalloonRequest(
bool enable,
base::OnceClosure success_callback);
void PostWithSwapDelay(base::OnceClosure callback);
// Called by `SendSwapRequest` and should not be called by other caller.
// Enable aggressive balloon and reclaim ARCVM guest memory.
// Shrink memory before enable swap. The function send enable swap request
// after shrink success.
void ShrinkArcVmMemoryAndEnableSwap(
vm_tools::concierge::SwapOperation requested_operation);
// Called by callback from `ShrinkArcVmMemoryAndEnableSwap` and should not be
// called by other caller. Update shrink result.
void SetShrinkResult(bool success);
SwapState latest_swap_state_ = SwapState::DISABLE;
// List of observers.
base::ObserverList<Observer> observer_list_;
// Log the time stamp and result of last shrink memory request.
std::optional<base::Time> last_shrink_timestamp_;
std::optional<bool> last_shrink_result_;
// Repeat timer for checking and trimming ARCVM memory regularly. According
// current design in concierge, if the vmm swap status is enabled, the vmm
// manager needs to go through the "enable" process (i.e. trim memory, set
// aggressive balloon, send enable vmm swap dbus request) once an hour.
base::OneShotTimer enabled_state_heartbeat_timer_;
// The default delay from swap enabled and swap out. Basically it's used for
// keyboard swap. In finch, it will be replaced by the flag parameter.
base::TimeDelta swap_out_delay_ = base::Seconds(3);
// Accelerator for experimental usage. Always behind the feature flag.
std::unique_ptr<AcceleratorTarget> accelerator_;
// Swap request scheduler for experimental usage. Always behind the feature
// flag and parameters.
std::unique_ptr<ArcVmmSwapScheduler> scheduler_;
bool arc_connected_ = false;
std::string user_id_hash_;
base::RepeatingCallback<
void(ArcVmWorkingSetTrimExecutor::ResultCallback, ArcVmReclaimType, int)>
trim_call_;
raw_ptr<content::BrowserContext> context_ = nullptr;
raw_ptr<ArcBridgeService> bridge_service_ = nullptr;
base::ScopedObservation<
ConnectionHolder<mojom::AppInstance, mojom::AppHost>,
ConnectionHolder<mojom::AppInstance, mojom::AppHost>::Observer>
app_instance_observation_{this};
base::ScopedObservation<ash::ConciergeClient,
ash::ConciergeClient::VmObserver>
concierge_observation_{this};
base::WeakPtrFactory<ArcVmmManager> weak_ptr_factory_{this};
};
} // namespace arc
#endif // CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_MANAGER_H_