diff --git a/window_scene/session/host/include/session.h b/window_scene/session/host/include/session.h index 773d025aa90f562d39bea3759f62d1bb6b7d9954..5f7e8f3819ff0c5e02c5fcc559215a168ade3efb 100644 --- a/window_scene/session/host/include/session.h +++ b/window_scene/session/host/include/session.h @@ -229,11 +229,29 @@ public: std::shared_ptr GetSurfaceNode() const; void SetLeashWinSurfaceNode(std::shared_ptr leashWinSurfaceNode); std::shared_ptr GetLeashWinSurfaceNode() const; + + /* + * Window Scene Snapshot + */ std::shared_ptr GetSnapshot() const; std::shared_ptr Snapshot( bool runInFfrt = false, float scaleParam = 0.0f, bool useCurWindow = false) const; void ResetSnapshot(); void SaveSnapshot(bool useFfrt, bool needPersist = true); + void SetSaveSnapshotCallback(Task&& task) + { + if (task) { + saveSnapshotCallback_ = std::move(task); + } + }; + + void SetRemoveSnapshotCallback(Task&& task) + { + if (task) { + removeSnapshotCallback_ = std::move(task); + } + }; + SessionState GetSessionState() const; virtual void SetSessionState(SessionState state); void SetSessionInfoAncoSceneState(int32_t ancoSceneState); @@ -920,7 +938,7 @@ private: bool enableRemoveStartingWindow_ { false }; bool appBufferReady_ { false }; bool useStartingWindowAboveLocked_ { false }; - + /* * Window Layout */ @@ -932,6 +950,12 @@ private: * Screen Lock */ bool isScreenLockWindow_ { false }; + + /* + * Window Scene Snapshot + */ + Task saveSnapshotCallback_ = []() {}; + Task removeSnapshotCallback_ = []() {}; }; } // namespace OHOS::Rosen diff --git a/window_scene/session/host/src/session.cpp b/window_scene/session/host/src/session.cpp index f360b385cb001eddc93c08a13104c9408a55753d..e89fdb9a3d952d1cadf0285f48321022b72ce187 100644 --- a/window_scene/session/host/src/session.cpp +++ b/window_scene/session/host/src/session.cpp @@ -2406,10 +2406,15 @@ void Session::SaveSnapshot(bool useFfrt, bool needPersist) std::lock_guard lock(session->snapshotMutex_); session->snapshot_ = pixelMap; } + session->saveSnapshotCallback_(); if (!requirePersist) { return; } - session->scenePersistence_->SaveSnapshot(pixelMap); + if (!session->scenePersistence_) { + TLOGNE(WmsLogTag::WMS_PATTERN, "scenePersistence_ is null"); + return; + } + session->scenePersistence_->SaveSnapshot(pixelMap, session->removeSnapshotCallback_); }; if (!useFfrt) { task(); diff --git a/window_scene/session_manager/include/scene_session_manager.h b/window_scene/session_manager/include/scene_session_manager.h index 72c546d73a879f49a95ebf89c927775b5a153fde..df718ec7f62bef689e62698811f2c695871e446e 100644 --- a/window_scene/session_manager/include/scene_session_manager.h +++ b/window_scene/session_manager/include/scene_session_manager.h @@ -621,8 +621,10 @@ public: /* * Window Pattern */ + void InitSnapshotCache(); void VisitSnapshotFromCache(int32_t persistentId); void PutSnapshotToCache(int32_t persistentId); + void RemoveSnapshotFromCache(int32_t persistentId); protected: SceneSessionManager(); @@ -1310,6 +1312,7 @@ private: * Window Pattern */ std::unique_ptr snapshotLRUCache_; + std::size_t snapCapacity_ = 0; }; } // namespace OHOS::Rosen diff --git a/window_scene/session_manager/include/window_manager_lru.h b/window_scene/session_manager/include/window_manager_lru.h index 22d42850b5a5fe97213b97ac8c3fad71516c3fc0..ce6d497a837c63cbcf3210d0fada33adf32972b7 100644 --- a/window_scene/session_manager/include/window_manager_lru.h +++ b/window_scene/session_manager/include/window_manager_lru.h @@ -18,6 +18,7 @@ #include #include +#include namespace OHOS::Rosen { namespace { @@ -29,11 +30,13 @@ public: bool Visit(int32_t key); int32_t Put(int32_t key); + void Remove(int32_t key); private: const std::size_t capacity_; std::list cacheList_; std::unordered_map::iterator> cacheMap_; + mutable std::mutex LRUCacheMutex_; }; } // namespace OHOS::Rosen #endif // OHOS_ROSEN_LRUCACHE_H \ No newline at end of file diff --git a/window_scene/session_manager/src/scene_session_manager.cpp b/window_scene/session_manager/src/scene_session_manager.cpp index 2f432bd4ba9d5e89f3e2d18413c38b3aa46aed50..48dac5bdff5449f8b12f0bc7778d165b98ade225 100644 --- a/window_scene/session_manager/src/scene_session_manager.cpp +++ b/window_scene/session_manager/src/scene_session_manager.cpp @@ -335,20 +335,6 @@ SceneSessionManager::SceneSessionManager() : rsInterface_(RSInterfaces::GetInsta scbDumpSubscriber_ = ScbDumpSubscriber::Subscribe(); - const static std::unordered_map SNAPSHOT_CACHE_CAPACITY_MAP = { - {WindowUIType::PC_WINDOW, MAX_SNAPSHOT_IN_RECENT_PC}, - {WindowUIType::PAD_WINDOW, MAX_SNAPSHOT_IN_RECENT_PAD}, - {WindowUIType::PHONE_WINDOW, MAX_SNAPSHOT_IN_RECENT_PHONE}, - {WindowUIType::INVALID_WINDOW, MAX_SNAPSHOT_IN_RECENT_PHONE}, - }; - std::size_t snapCapacity = SNAPSHOT_CACHE_CAPACITY_MAP.at(WindowUIType::INVALID_WINDOW); - if (SNAPSHOT_CACHE_CAPACITY_MAP.find(systemConfig_.windowUIType_) != SNAPSHOT_CACHE_CAPACITY_MAP.end()) { - snapCapacity = SNAPSHOT_CACHE_CAPACITY_MAP.at(systemConfig_.windowUIType_); - } else { - TLOGI(WmsLogTag::WMS_PATTERN, "invalid type: %{public}hhu", systemConfig_.windowUIType_); - } - snapshotLRUCache_ = std::make_unique(snapCapacity); - listenerController_ = std::make_shared(); windowFocusController_ = sptr::MakeSptr(); } @@ -425,6 +411,8 @@ void SceneSessionManager::Init() std::bind(&SceneSessionManager::UpdateSessionCrossAxisState, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); PcFoldScreenManager::GetInstance().RegisterFoldScreenStatusChangeCallback(0, callback); + + InitSnapshotCache(); } void SceneSessionManager::RegisterFlushWindowInfoCallback() @@ -2512,6 +2500,24 @@ bool SceneSessionManager::IsPcSceneSessionLifecycle(const sptr& sc return (systemConfig_.backgroundswitch && !isAppSupportPhoneInPc) || isPcAppInPad; } +void SceneSessionManager::InitSnapshotCache() +{ + const static std::unordered_map SNAPSHOT_CACHE_CAPACITY_MAP = { + {WindowUIType::PC_WINDOW, MAX_SNAPSHOT_IN_RECENT_PC}, + {WindowUIType::PAD_WINDOW, MAX_SNAPSHOT_IN_RECENT_PAD}, + {WindowUIType::PHONE_WINDOW, MAX_SNAPSHOT_IN_RECENT_PHONE}, + {WindowUIType::INVALID_WINDOW, MAX_SNAPSHOT_IN_RECENT_PHONE}, + }; + + auto uiType = systemConfig_.windowUIType_; + snapCapacity_ = SNAPSHOT_CACHE_CAPACITY_MAP.at(WindowUIType::INVALID_WINDOW); + if (SNAPSHOT_CACHE_CAPACITY_MAP.find(uiType) != SNAPSHOT_CACHE_CAPACITY_MAP.end()) { + snapCapacity_ = SNAPSHOT_CACHE_CAPACITY_MAP.at(uiType); + } + TLOGI(WmsLogTag::WMS_PATTERN, "type: %{public}hhu, capacity: %{public}u", uiType, snapCapacity_); + snapshotLRUCache_ = std::make_unique(snapCapacity_); +} + void SceneSessionManager::PutSnapshotToCache(int32_t persistentId) { TLOGD(WmsLogTag::WMS_PATTERN, "session:%{public}d", persistentId); @@ -2528,13 +2534,19 @@ void SceneSessionManager::PutSnapshotToCache(int32_t persistentId) void SceneSessionManager::VisitSnapshotFromCache(int32_t persistentId) { TLOGD(WmsLogTag::WMS_PATTERN, "session:%{public}d", persistentId); - taskScheduler_->PostAsyncTask([this, persistentId](){ - if (!snapshotLRUCache_->Visit(persistentId)) { - TLOGND(WmsLogTag::WMS_PATTERN, "session:%{public}d not in cache", persistentId); - } - }, __func__); + if (!snapshotLRUCache_->Visit(persistentId)) { + TLOGD(WmsLogTag::WMS_PATTERN, "session:%{public}d not in cache", persistentId); + } } +void SceneSessionManager::RemoveSnapshotFromCache(int32_t persistentId) +{ + TLOGD(WmsLogTag::WMS_PATTERN, "session:%{public}d", persistentId); + snapshotLRUCache_->Remove(persistentId); + if (auto sceneSession = GetSceneSession(persistentId)) { + sceneSession->ResetSnapshot(); + } +} WSError SceneSessionManager::RequestSceneSessionBackground(const sptr& sceneSession, const bool isDelegator, const bool isToDesktop, const bool isSaveSnapshot) @@ -2557,10 +2569,9 @@ WSError SceneSessionManager::RequestSceneSessionBackground(const sptrEditSessionInfo().callingTokenId_ = 0; } - if (SessionHelper::IsMainWindow(sceneSession->GetWindowType())) { - PutSnapshotToCache(persistentId); - } - + sceneSession->SetSaveSnapshotCallback([this, persistentId]() { + this->PutSnapshotToCache(persistentId); + }); sceneSession->BackgroundTask(isSaveSnapshot); if (!GetSceneSession(persistentId)) { TLOGNE(WmsLogTag::WMS_MAIN, "Request background session invalid by %{public}d", persistentId); @@ -2797,6 +2808,9 @@ WSError SceneSessionManager::RequestSceneSessionDestruction(const sptrGetSessionInfo(), ActionType::SINGLE_CLOSE); + sceneSession->SetRemoveSnapshotCallback([this, persistentId]() { + this->RemoveSnapshotFromCache(persistentId); + }); sceneSession->DisconnectTask(false, isSaveSnapshot); if (!GetSceneSession(persistentId)) { TLOGNE(WmsLogTag::WMS_MAIN, "Destruct session invalid by %{public}d", persistentId); diff --git a/window_scene/session_manager/src/window_manager_lru.cpp b/window_scene/session_manager/src/window_manager_lru.cpp index bb12c03b4fd607b990371535ddd24856dbbaf93a..d8f3edb0aec7e91f585e9978ace9959e6ded2c6e 100644 --- a/window_scene/session_manager/src/window_manager_lru.cpp +++ b/window_scene/session_manager/src/window_manager_lru.cpp @@ -18,6 +18,7 @@ namespace OHOS::Rosen { bool LRUCache::Visit(int32_t key) { + std::lock_guard lock(LRUCacheMutex_); if (auto it = cacheMap_.find(key); it != cacheMap_.end()) { cacheList_.splice(cacheList_.begin(), cacheList_, it->second); return true; @@ -29,6 +30,7 @@ int32_t LRUCache::Put(int32_t key) { int32_t lastRemovedKey = UNDEFINED_REMOVED_KEY; if (!Visit(key)) { + std::lock_guard lock(LRUCacheMutex_); if (cacheList_.size() >= capacity_) { lastRemovedKey = cacheList_.back(); cacheList_.pop_back(); @@ -39,4 +41,13 @@ int32_t LRUCache::Put(int32_t key) } return lastRemovedKey; } + +void LRUCache::Remove(int32_t key) +{ + std::lock_guard lock(LRUCacheMutex_); + if (auto it = cacheMap_.find(key); it != cacheMap_.end()) { + cacheList_.erase(it->second); + cacheMap_.erase(it); + } +} } // namespace OHOS::Rosen diff --git a/window_scene/test/unittest/scene_session_manager_test5.cpp b/window_scene/test/unittest/scene_session_manager_test5.cpp index ca182247cd0908d4cf3a88636b8f8600a729e0c4..2fa20ec1429d5f40051834e70c93bb4055d069d3 100644 --- a/window_scene/test/unittest/scene_session_manager_test5.cpp +++ b/window_scene/test/unittest/scene_session_manager_test5.cpp @@ -1159,6 +1159,24 @@ HWTEST_F(SceneSessionManagerTest5, CheckSessionPropertyOnRecovery, Function | Sm ASSERT_EQ(result, WSError::WS_ERROR_INVALID_PARAM); } +/** + * @tc.name: InitSnapshotCache + * @tc.desc: InitSnapshotCache + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionManagerTest5, InitSnapshotCache, Function | SmallTest | Level3) +{ + ASSERT_NE(ssm_, nullptr); + ssm_->InitSnapshotCache(); + if (ssm_->systemConfig_.windowUIType_ == WindowUIType::PC_WINDOW) { + ASSERT_EQ(ssm_->snapCapacity_, 24); + } else if (ssm_->systemConfig_.windowUIType_ == WindowUIType::PAD_WINDOW) { + ASSERT_EQ(ssm_->snapCapacity_, 8); + } else { + ASSERT_EQ(ssm_->snapCapacity_, 3); + } +} + /** * @tc.name: PutSnapshotToCache * @tc.desc: PutSnapshotToCache @@ -1178,7 +1196,7 @@ HWTEST_F(SceneSessionManagerTest5, PutSnapshotToCache, Function | SmallTest | Le sceneSession->scenePersistence_ = sptr::MakeSptr(bundleName, persistentId); sceneSession->snapshot_ = std::make_shared(); ssm_->sceneSessionMap_.insert({30, sceneSession}); - for (int32_t id = 30; id <= 33; ++id) { + for (int32_t id = 30; id <= 30 + ssm_->snapCapacity_; ++id) { ssm_->PutSnapshotToCache(id); } ASSERT_EQ(sceneSession->snapshot_, nullptr); @@ -1203,12 +1221,38 @@ HWTEST_F(SceneSessionManagerTest5, VisitSnapshotFromCache, Function | SmallTest sceneSession->scenePersistence_ = sptr::MakeSptr(bundleName, persistentId); ssm_->sceneSessionMap_.insert({30, sceneSession}); sceneSession->snapshot_ = std::make_shared(); - for (int32_t id = 30; id < 33; ++id) { + for (int32_t id = 30; id < 30 + ssm_->snapCapacity_; ++id) { ssm_->PutSnapshotToCache(id); } ssm_->VisitSnapshotFromCache(30); - usleep(WAIT_SYNC_IN_NS); - ssm_->PutSnapshotToCache(33); + ssm_->PutSnapshotToCache(30 + ssm_->snapCapacity_); + ASSERT_NE(sceneSession->snapshot_, nullptr); +} + +/** + * @tc.name: RemoveSnapshotFromCache + * @tc.desc: RemoveSnapshotFromCache + * @tc.type: FUNC + */ +HWTEST_F(SceneSessionManagerTest5, RemoveSnapshotFromCache, Function | SmallTest | Level3) +{ + ASSERT_NE(ssm_, nullptr); + ssm_->sceneSessionMap_.clear(); + SessionInfo info; + info.abilityName_ = "test1"; + info.bundleName_ = "test2"; + info.persistentId_ = 30; + sptr sceneSession = sptr::MakeSptr(info, nullptr); + std::string bundleName = "testBundleName"; + int32_t persistentId = 30; + sceneSession->scenePersistence_ = sptr::MakeSptr(bundleName, persistentId); + ssm_->sceneSessionMap_.insert({30, sceneSession}); + sceneSession->snapshot_ = std::make_shared(); + for (int32_t id = 30; id < 30 + ssm_->snapCapacity_; ++id) { + ssm_->PutSnapshotToCache(id); + } + ssm_->RemoveSnapshotFromCache(31); + ssm_->PutSnapshotToCache(30 + ssm_->snapCapacity_); ASSERT_NE(sceneSession->snapshot_, nullptr); } diff --git a/window_scene/test/unittest/window_manager_lru_test.cpp b/window_scene/test/unittest/window_manager_lru_test.cpp index 0b677eff45edae9b0f5c730316e364b056da5d01..1a32d9e8c8f42a4136f6a776f000d27859ba1202 100644 --- a/window_scene/test/unittest/window_manager_lru_test.cpp +++ b/window_scene/test/unittest/window_manager_lru_test.cpp @@ -81,5 +81,23 @@ HWTEST_F(LRUCacheTest, Put, Function | SmallTest | Level2) res = testLRUCache_->Put(33); ASSERT_EQ(res, 30); } + +/** + * @tc.name: Remove + * @tc.desc: test function Remove + * @tc.type: FUNC + */ +HWTEST_F(LRUCacheTest, Remove, Function | SmallTest | Level2) +{ + testLRUCache_ = std::make_unique(TEST_CACHE_CAPACITY); + int32_t res = testLRUCache_->Put(30); + ASSERT_EQ(res, -1); + + testLRUCache_->Put(31); + testLRUCache_->Put(32); + testLRUCache_->Remove(32); + res = testLRUCache_->Put(33); + ASSERT_EQ(res, -1); +} } } \ No newline at end of file