1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
// 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 "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 "chromeos/ash/experiences/arc/mojom/app.mojom.h"
#include "chromeos/ash/experiences/arc/session/connection_holder.h"
#include "chromeos/ash/experiences/arc/session/connection_observer.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_
|