From b7788833f6c4260dcfe76f1d4286385fab784ffa Mon Sep 17 00:00:00 2001 From: raul <3293272615@qq.com> Date: Sat, 15 Jan 2022 21:18:07 +0800 Subject: [PATCH] fix snapshot bug Signed-off-by: laoyitong Change-Id: I946a21123a89d017e2bab5e3740ba3fa2ae80ea3 --- .../include/ability_manager_interface.h | 1 + .../aafwk/mission_manager/mission_manager.cpp | 4 +- services/abilitymgr/BUILD.gn | 1 + .../include/ability_manager_service.h | 1 - .../abilitymgr/include/mission_data_storage.h | 10 ++ .../abilitymgr/include/mission_info_mgr.h | 29 ++++++ .../abilitymgr/include/mission_list_manager.h | 17 ++++ .../include/task_data_persistence_mgr.h | 18 ++++ .../abilitymgr/src/ability_manager_proxy.cpp | 2 +- .../src/ability_manager_service.cpp | 20 ++-- .../abilitymgr/src/ability_manager_stub.cpp | 1 + .../abilitymgr/src/mission_data_storage.cpp | 97 +++++++++++++++++++ services/abilitymgr/src/mission_info_mgr.cpp | 47 +++++++++ .../abilitymgr/src/mission_list_manager.cpp | 22 +++++ .../src/task_data_persistence_mgr.cpp | 20 ++++ 15 files changed, 278 insertions(+), 12 deletions(-) diff --git a/interfaces/innerkits/ability_manager/include/ability_manager_interface.h b/interfaces/innerkits/ability_manager/include/ability_manager_interface.h index 6e57722b2e6..475a737bad8 100755 --- a/interfaces/innerkits/ability_manager/include/ability_manager_interface.h +++ b/interfaces/innerkits/ability_manager/include/ability_manager_interface.h @@ -817,6 +817,7 @@ public: START_SYNC_MISSIONS = 1112, STOP_SYNC_MISSIONS = 1113, REGISTER_SNAPSHOT_HANDLER = 1114, + GET_MISSION_SNAPSHOT_INFO = 1115, // ipc id 2001-3000 for tools // ipc id for dumping state (2001) diff --git a/interfaces/kits/napi/aafwk/mission_manager/mission_manager.cpp b/interfaces/kits/napi/aafwk/mission_manager/mission_manager.cpp index 3f9a59de06d..2fbe21326e5 100644 --- a/interfaces/kits/napi/aafwk/mission_manager/mission_manager.cpp +++ b/interfaces/kits/napi/aafwk/mission_manager/mission_manager.cpp @@ -33,7 +33,7 @@ using namespace OHOS::AppExecFwk; using AbilityManagerClient = AAFwk::AbilityManagerClient; namespace { constexpr int32_t ARG_COUNT_TWO = 1; - constexpr int32_t ARG_COUNT_THREE = 1; + constexpr int32_t ARG_COUNT_THREE = 3; } class JsMissionManager { public: @@ -256,7 +256,7 @@ private: return engine.CreateUndefined(); } int32_t missionId = -1; - if (!ConvertFromJsValue(engine, info.argv[0], missionId)) { + if (!ConvertFromJsValue(engine, info.argv[1], missionId)) { HILOG_ERROR("missionSnapshot: Parse missionId failed"); return engine.CreateUndefined(); } diff --git a/services/abilitymgr/BUILD.gn b/services/abilitymgr/BUILD.gn index 2d3bd5854bd..b30fa110e49 100644 --- a/services/abilitymgr/BUILD.gn +++ b/services/abilitymgr/BUILD.gn @@ -92,6 +92,7 @@ ohos_shared_library("abilityms") { "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", + "//third_party/libpng:libpng", "//utils/native/base:utils", ] diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index f6c2176e820..8ec36d62159 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -933,7 +933,6 @@ private: std::unordered_map> missionListManagers_; std::shared_ptr currentMissionListManager_; std::shared_ptr kernalAbilityManager_; - sptr snapshotHandler_; std::shared_ptr userController_; sptr abilityController_ = nullptr; bool controllerIsAStabilityTest_ = false; diff --git a/services/abilitymgr/include/mission_data_storage.h b/services/abilitymgr/include/mission_data_storage.h index ebced052d7b..f7e234267bf 100644 --- a/services/abilitymgr/include/mission_data_storage.h +++ b/services/abilitymgr/include/mission_data_storage.h @@ -22,6 +22,7 @@ #include "event_handler.h" #include "inner_mission_info.h" +#include "mission_snapshot.h" namespace OHOS { namespace AAFwk { @@ -29,6 +30,7 @@ const std::string TASK_DATA_FILE_BASE_PATH = "/data/service/el1/public/AbilityMa const std::string MISSION_DATA_FILE_PATH = "MissionInfo"; const std::string MISSION_JSON_FILE_PREFIX = "mission"; const std::string JSON_FILE_SUFFIX = ".json"; +const std::string PNG_FILE_SUFFIX = ".png"; class MissionDataStorage : public std::enable_shared_from_this { public: @@ -56,11 +58,19 @@ public: */ void DeleteMissionInfo(int missionId); + void SaveMissionSnapshot(int missionId, const MissionSnapshot& missionSnapshot); + + bool GetMissionSnapshot(int missionId, MissionSnapshot& missionSnapshot); + + bool WriteToPng(const char* fileName, uint32_t width, uint32_t height, const uint8_t* data); + private: std::string GetMissionDataDirPath(); std::string GetMissionDataFilePath(int missionId); + std::string GetMissionSnapshotPath(int missionId); + bool CheckFileNameValid(const std::string &fileName); private: diff --git a/services/abilitymgr/include/mission_info_mgr.h b/services/abilitymgr/include/mission_info_mgr.h index b41b2af4117..790e05fad56 100644 --- a/services/abilitymgr/include/mission_info_mgr.h +++ b/services/abilitymgr/include/mission_info_mgr.h @@ -22,6 +22,8 @@ #include "inner_mission_info.h" #include "mission_listener_controller.h" +#include "mission_snapshot.h" +#include "snapshot.h" #include "task_data_persistence_mgr.h" namespace OHOS { @@ -120,6 +122,32 @@ public: * @param info dump result. */ void Dump(std::vector &info); + + /** + * @brief update mission snapshot + * @param missionId mission id + * @param abilityToken abilityToken to get current mission snapshot + * @param missionSnapshot result of snapshot + * @return return true if update mission snapshot success, else false + */ + bool UpdateMissionSnapshot(int32_t missionId, const sptr& abilityToken, + MissionSnapshot& missionSnapshot) const; + + /** + * @brief get the mission snapshot object + * @param missionId mission id + * @param abilityToken abilityToken to get current mission snapshot + * @param missionSnapshot result of snapshot + * @return true return true if get mission snapshot success, else false + */ + bool GetMissionSnapshot(int32_t missionId, const sptr& abilityToken, + MissionSnapshot& missionSnapshot) const; + + /** + * @brief register snapshotHandler + * @param handler the snapshotHandler + */ + void RegisterSnapshotHandler(const sptr& handler); private: /** * @brief Boot query mission info. @@ -131,6 +159,7 @@ private: std::unordered_map missionIdMap_; // key:distributed misisonid, vaule: has been saved std::list missionInfoList_; std::shared_ptr taskDataPersistenceMgr_; + sptr snapshotHandler_; }; } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/include/mission_list_manager.h b/services/abilitymgr/include/mission_list_manager.h index fe7b0590606..deafae1fb94 100644 --- a/services/abilitymgr/include/mission_list_manager.h +++ b/services/abilitymgr/include/mission_list_manager.h @@ -23,6 +23,8 @@ #include "mission_list.h" #include "mission_listener_controller.h" #include "mission_info.h" +#include "mission_snapshot.h" +#include "snapshot.h" #include "want.h" namespace OHOS { @@ -249,6 +251,21 @@ public: * @param info dump result. */ void DumpMissionInfos(std::vector &info); + + /** + * @brief register snapshotHandler + * @param handler the snapshotHandler + */ + void RegisterSnapshotHandler(const sptr& handler); + + /** + * @brief Get the Mission Snapshot object + * @param missionId mission id + * @param abilityToken abilityToken to get current mission snapshot + * @param missionSnapshot result of snapshot + */ + void GetMissionSnapshot(int32_t missionId, const sptr& abilityToken, + MissionSnapshot& missionSnapshot); private: int StartAbilityLocked(const std::shared_ptr ¤tTopAbility, const std::shared_ptr &callerAbility, const AbilityRequest &abilityRequest); diff --git a/services/abilitymgr/include/task_data_persistence_mgr.h b/services/abilitymgr/include/task_data_persistence_mgr.h index db3c2e1e004..3e8aae52068 100644 --- a/services/abilitymgr/include/task_data_persistence_mgr.h +++ b/services/abilitymgr/include/task_data_persistence_mgr.h @@ -28,6 +28,8 @@ namespace AAFwk { const std::string THREAD_NAME = "TaskDataStorage"; const std::string SAVE_MISSION_INFO = "SaveMissionInfo"; const std::string DELETE_MISSION_INFO = "DeleteMissionInfo"; +const std::string SAVE_MISSION_SNAPSHOT = "SaveMissionSnapshot"; +const std::string GET_MISSION_SNAPSHOT = "GetMissionSnapshot"; class TaskDataPersistenceMgr : public std::enable_shared_from_this { DECLARE_DELAYED_SINGLETON(TaskDataPersistenceMgr) @@ -66,6 +68,22 @@ public: */ bool RemoveUserDir(int32_t userId); + /** + * @brief save mission snapshot + * @param missionId id of mission + * @param snapshot result of snapshot + * @return return true if update mission snapshot success, else false + */ + bool SaveMissionSnapshot(int missionId, const MissionSnapshot& snapshot); + + /** + * @brief get the mission snapshot object + * @param missionId id of mission + * @param missionSnapshot + * @return return true if update mission snapshot success, else false + */ + bool GetMissionSnapshot(int missionId, MissionSnapshot& missionSnapshot); + private: std::unordered_map> missionDataStorageMgr_; std::shared_ptr currentMissionDataStorage_; diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index fc3a387d67e..f393ffe8b16 100755 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -684,7 +684,7 @@ int AbilityManagerProxy::GetMissionSnapshot(const std::string& deviceId, int32_t HILOG_ERROR("missionId write failed."); return ERR_INVALID_VALUE; } - error = Remote()->SendRequest(IAbilityManager::GET_MISSION_SNAPSHOT, data, reply, option); + error = Remote()->SendRequest(IAbilityManager::GET_MISSION_SNAPSHOT_INFO, data, reply, option); if (error != NO_ERROR) { HILOG_ERROR("Send request error: %{public}d", error); return error; diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index b4837a79034..734aee4b310 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -40,6 +40,7 @@ #include "softbus_bus_center.h" #include "string_ex.h" #include "system_ability_definition.h" +#include "png.h" using OHOS::AppExecFwk::ElementName; @@ -2810,8 +2811,12 @@ void AbilityManagerService::ClearUserData(int32_t userId) int AbilityManagerService::RegisterSnapshotHandler(const sptr& handler) { + if (!currentMissionListManager_) { + HILOG_ERROR("snapshot: currentMissionListManager_ is nullptr."); + return 0; + } + currentMissionListManager_->RegisterSnapshotHandler(handler); HILOG_INFO("snapshot: AbilityManagerService register snapshot handler success."); - snapshotHandler_ = handler; return 0; } @@ -2822,15 +2827,14 @@ int32_t AbilityManagerService::GetMissionSnapshot(const std::string& deviceId, i HILOG_INFO("get remote mission snapshot."); return GetRemoteMissionSnapshotInfo(deviceId, missionId, missionSnapshot); } - HILOG_INFO("get local mission snapshot."); - if (!snapshotHandler_) { - return 0; + if (!currentMissionListManager_) { + HILOG_ERROR("snapshot: currentMissionListManager_ is nullptr."); + return -1; } - Snapshot snapshot; - int32_t result = snapshotHandler_->GetSnapshot(GetAbilityTokenByMissionId(missionId), snapshot); - missionSnapshot.snapshot = snapshot.GetPixelMap(); - return result; + auto token = GetAbilityTokenByMissionId(missionId); + currentMissionListManager_->GetMissionSnapshot(missionId, token, missionSnapshot); + return 0; } int32_t AbilityManagerService::GetRemoteMissionSnapshotInfo(const std::string& deviceId, int32_t missionId, diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index b94cf6b91ae..659db8c0efd 100755 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -127,6 +127,7 @@ void AbilityManagerStub::SecondStepInit() requestFuncMap_[STOP_USER] = &AbilityManagerStub::StopUserInner; requestFuncMap_[SET_ABILITY_CONTROLLER] = &AbilityManagerStub::SetAbilityControllerInner; requestFuncMap_[IS_USER_A_STABILITY_TEST] = &AbilityManagerStub::IsUserAStabilityTestInner; + requestFuncMap_[GET_MISSION_SNAPSHOT_INFO] = &AbilityManagerStub::GetMissionSnapshotInfoInner; } int AbilityManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) diff --git a/services/abilitymgr/src/mission_data_storage.cpp b/services/abilitymgr/src/mission_data_storage.cpp index 99a0e658b38..c4977bd4c93 100644 --- a/services/abilitymgr/src/mission_data_storage.cpp +++ b/services/abilitymgr/src/mission_data_storage.cpp @@ -19,6 +19,9 @@ #include "file_util.h" #include "hilog_wrapper.h" +#include "image_source.h" +#include "media_errors.h" +#include "png.h" namespace OHOS { namespace AAFwk { @@ -125,5 +128,99 @@ bool MissionDataStorage::CheckFileNameValid(const std::string &fileName) return true; } + +void MissionDataStorage::SaveMissionSnapshot(int32_t missionId, const MissionSnapshot& missionSnapshot) +{ + std::string filePath = GetMissionSnapshotPath(missionId); + std::string dirPath = OHOS::HiviewDFX::FileUtil::ExtractFilePath(filePath); + if (!OHOS::HiviewDFX::FileUtil::FileExists(dirPath)) { + bool createDir = OHOS::HiviewDFX::FileUtil::ForceCreateDirectory(dirPath); + if (!createDir) { + HILOG_ERROR("snapshot: create dir %{public}s failed.", dirPath.c_str()); + return; + } + } + const uint8_t* data = missionSnapshot.snapshot->GetPixels(); + bool saveMissionFile = WriteToPng(filePath.c_str(), missionSnapshot.snapshot->GetWidth(), + missionSnapshot.snapshot->GetHeight(), data); + if (!saveMissionFile) { + HILOG_ERROR("snapshot: save mission snapshot failed, path = %{public}s.", filePath.c_str()); + } +} + +bool MissionDataStorage::GetMissionSnapshot(int missionId, MissionSnapshot& missionSnapshot) +{ + std::string filePath = GetMissionSnapshotPath(missionId); + if (!OHOS::HiviewDFX::FileUtil::FileExists(filePath)) { + HILOG_INFO("snapshot: storage snapshot not exists, missionId = %{public}d", missionId); + return false; + } + uint32_t errCode = 0; + Media::SourceOptions sourceOptions; + auto imageSource = Media::ImageSource::CreateImageSource(filePath, sourceOptions, errCode); + if (errCode != OHOS::Media::SUCCESS) { + HILOG_ERROR("snapshot: CreateImageSource failed, errCode = %{public}d", errCode); + return false; + } + Media::DecodeOptions decodeOptions; + auto pixelMap = imageSource->CreatePixelMap(decodeOptions, errCode); + if (errCode != OHOS::Media::SUCCESS) { + HILOG_ERROR("snapshot: CreatePixelMap failed, errCode = %{public}d", errCode); + return false; + } + missionSnapshot.snapshot = std::move(pixelMap); + return true; +} + +std::string MissionDataStorage::GetMissionSnapshotPath(int missionId) +{ + return GetMissionDataDirPath() + "/" + + MISSION_JSON_FILE_PREFIX + "_" + std::to_string(missionId) + PNG_FILE_SUFFIX; +} + +bool MissionDataStorage::WriteToPng(const char* fileName, uint32_t width, uint32_t height, const uint8_t* data) +{ + const int BITMAP_DEPTH = 8; // color depth + const int BPP = 4; // bytes per pixel + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (png_ptr == nullptr) { + HILOG_ERROR("snapshot: png_create_write_struct error, nullptr!\n"); + return false; + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (png_ptr == nullptr) { + HILOG_ERROR("snapshot: png_create_info_struct error, nullptr!\n"); + png_destroy_write_struct(&png_ptr, nullptr); + return false; + } + FILE *fp = fopen(fileName, "wb"); + if (fp == nullptr) { + HILOG_ERROR("snapshot: open file [%s] error, nullptr!\n", fileName); + png_destroy_write_struct(&png_ptr, &info_ptr); + return false; + } + png_init_io(png_ptr, fp); + + // set png header + png_set_IHDR(png_ptr, info_ptr, + width, height, + BITMAP_DEPTH, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + png_set_packing(png_ptr); + png_write_info(png_ptr, info_ptr); + + for (uint32_t i = 0; i < height; i++) { + png_write_row(png_ptr, data + (i * width * BPP)); + } + png_write_end(png_ptr, info_ptr); + + // free memory + png_destroy_write_struct(&png_ptr, &info_ptr); + (void)fclose(fp); + return true; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/mission_info_mgr.cpp b/services/abilitymgr/src/mission_info_mgr.cpp index e3282cc3ac2..8faacfe115d 100644 --- a/services/abilitymgr/src/mission_info_mgr.cpp +++ b/services/abilitymgr/src/mission_info_mgr.cpp @@ -305,5 +305,52 @@ void MissionInfoMgr::Dump(std::vector &info) innerMissionInfo.Dump(info); } } + +void MissionInfoMgr::RegisterSnapshotHandler(const sptr& handler) +{ + snapshotHandler_ = handler; +} + +bool MissionInfoMgr::UpdateMissionSnapshot(int32_t missionId, const sptr& abilityToken, + MissionSnapshot& missionSnapshot) +{ + auto it = find_if(missionInfoList_.begin(), missionInfoList_.end(), [missionId](const InnerMissionInfo &info) { + return missionId == info.missionInfo.id; + }); + if (it == missionInfoList_.end()) { + HILOG_ERROR("snapshot: get mission failed, missionId %{public}d not exists", missionId); + return false; + } + Snapshot snapshot; + int32_t result = snapshotHandler_->GetSnapshot(abilityToken, snapshot); + if (result != 0) { + HILOG_ERROR("snapshot: get WMS snapshot failed, result = %{public}d", result); + return false; + } + if (!taskDataPersistenceMgr_) { + HILOG_ERROR("snapshot: taskDataPersistenceMgr_ is nullptr"); + return false; + } + missionSnapshot.snapshot = snapshot.GetPixelMap(); + if (!taskDataPersistenceMgr_->SaveMissionSnapshot(missionId, missionSnapshot)) { + HILOG_ERROR("snapshot: save mission snapshot failed"); + return false; + } + return true; +} + +bool MissionInfoMgr::GetMissionSnapshot(int32_t missionId, const sptr& abilityToken, + MissionSnapshot& missionSnapshot) +{ + if (!taskDataPersistenceMgr_) { + HILOG_ERROR("snapshot: taskDataPersistenceMgr_ is nullptr"); + return false; + } + if (taskDataPersistenceMgr_->GetMissionSnapshot(missionId, missionSnapshot)) { + return true; + } + HILOG_INFO("snapshot: storage mission snapshot not exists, create new snapshot"); + return UpdateMissionSnapshot(missionId, abilityToken, missionSnapshot); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/mission_list_manager.cpp b/services/abilitymgr/src/mission_list_manager.cpp index c934493732e..abf8dd73067 100644 --- a/services/abilitymgr/src/mission_list_manager.cpp +++ b/services/abilitymgr/src/mission_list_manager.cpp @@ -751,6 +751,17 @@ void MissionListManager::CompleteBackground(const std::shared_ptr terminateAbility->Terminate(timeoutTask); } } + auto mission = abilityRecord->GetMission(); + if (!mission) { + HILOG_ERROR("snapshot: GetMission failed"); + return; + } + MissionSnapshot snapshot; + DelayedSingleton::GetInstance()->UpdateMissionSnapshot(mission->GetMissionId(), + abilityRecord->GetToken(), snapshot); + if (listenerController_) { + listenerController_->NotifyMissionSnapshotChanged(mission->GetMissionId()); + } } int MissionListManager::TerminateAbility(const std::shared_ptr &abilityRecord, @@ -1494,5 +1505,16 @@ void MissionListManager::DumpMission(int missionId, std::vector &in } innerMissionInfo.Dump(info); } + +void MissionListManager::RegisterSnapshotHandler(const sptr& handler) +{ + DelayedSingleton::GetInstance()->RegisterSnapshotHandler(handler); +} + +void MissionListManager::GetMissionSnapshot(int32_t missionId, const sptr& abilityToken, + MissionSnapshot& missionSnapshot) +{ + DelayedSingleton::GetInstance()->GetMissionSnapshot(missionId, abilityToken, missionSnapshot); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/task_data_persistence_mgr.cpp b/services/abilitymgr/src/task_data_persistence_mgr.cpp index 47fac5416c4..382259f0a90 100644 --- a/services/abilitymgr/src/task_data_persistence_mgr.cpp +++ b/services/abilitymgr/src/task_data_persistence_mgr.cpp @@ -105,5 +105,25 @@ bool TaskDataPersistenceMgr::RemoveUserDir(int32_t userId) } return true; } + +bool TaskDataPersistenceMgr::SaveMissionSnapshot(int missionId, const MissionSnapshot& snapshot) +{ + if (!handler_ || !currentMissionDataStorage_) { + HILOG_ERROR("snapshot: handler_ or currentMissionDataStorage_ is nullptr"); + return false; + } + std::function SaveMissionSnapshotFunc = std::bind(&MissionDataStorage::SaveMissionSnapshot, + currentMissionDataStorage_, missionId, snapshot); + return handler_->PostTask(SaveMissionSnapshotFunc, SAVE_MISSION_SNAPSHOT); +} + +bool TaskDataPersistenceMgr::GetMissionSnapshot(int missionId, MissionSnapshot& snapshot) +{ + if (!currentMissionDataStorage_) { + HILOG_ERROR("snapshot: currentMissionDataStorage_ is nullptr"); + return false; + } + return currentMissionDataStorage_->GetMissionSnapshot(missionId, snapshot); +} } // namespace AAFwk } // namespace OHOS -- Gitee