diff --git a/interfaces/innerkits/ability_manager/include/ability_manager_interface.h b/interfaces/innerkits/ability_manager/include/ability_manager_interface.h index 6e57722b2e60f72a2753a2b431c1034151d831dc..475a737bad841f80e06b9b61d9804017a5cd396f 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 3f9a59de06d0b5193ea1cb7913dd463ac851f804..2fbe21326e599ecc79dd8a6286a7b6f1b351f774 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 2d3bd5854bdfad0680fa01803e3712a4be24fe54..378b3e0b506c373ea6703eaa9afc909344188533 100644 --- a/services/abilitymgr/BUILD.gn +++ b/services/abilitymgr/BUILD.gn @@ -93,6 +93,7 @@ ohos_shared_library("abilityms") { "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", "//utils/native/base:utils", + "//third_party/libpng:libpng", ] external_deps = [ diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index f6c2176e8201055b639d0a01c21375befc90eb39..8ec36d621597e102e39b6d8ef46884e3ed492226 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 ebced052d7beb228fa431da3941aa581c2d06fbf..f7e234267bf0cbfe2a8ee85ae7a907123e1ab473 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 b41b2af41170c2e6f42b3816c42eeb2165d9110b..79b7d4c4e125782185f900f290e65de1e1a8903a 100644 --- a/services/abilitymgr/include/mission_info_mgr.h +++ b/services/abilitymgr/include/mission_info_mgr.h @@ -22,6 +22,7 @@ #include "inner_mission_info.h" #include "mission_listener_controller.h" +#include "mission_snapshot.h"" #include "task_data_persistence_mgr.h" namespace OHOS { @@ -120,6 +121,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 +158,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 fe7b0590606ce2f3328f5ca148f4125ab6f4ac79..d855de483d9634d8a8fdb7f4ec48acfcd8a5f7b3 100644 --- a/services/abilitymgr/include/mission_list_manager.h +++ b/services/abilitymgr/include/mission_list_manager.h @@ -23,6 +23,7 @@ #include "mission_list.h" #include "mission_listener_controller.h" #include "mission_info.h" +#include "mission_snapshot.h" #include "want.h" namespace OHOS { @@ -249,6 +250,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 db3c2e1e004b6f359ca5e6208e2b54088ba74863..3e8aae52068fa7ea67cd144aee45efaebba3faba 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 fc3a387d67efe68b9bc7755cfc4a11b68d41654a..f393ffe8b1684326c310e73065d71620c5ad39e8 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 b4837a790348f793d37f1e298d88e099486f5efe..734aee4b3109973967c21d655f2d520d1ad6ce8f 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 b94cf6b91ae2e39a3bfdf0b6ab463621966317a3..659db8c0efdce9cf5bd05b81926564e404130e48 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 99a0e658b38db9f69cef19aedc9ba57e156c961d..c4977bd4c9384e44d6656352ccd56288bcfd2df5 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 e3282cc3ac2a107277d442b1078ac868e4939feb..8faacfe115d86983d29a330ad395e7e4c04a8e9d 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 c934493732e873220a6fd281aee0fd0d352fba87..abf8dd730676c5e6cebe8dbd0d965ad35a79d14d 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 47fac5416c4ac4ceef4bd1984274ba5e4f08e828..382259f0a90e9c96def42d125ad58f545ba570f9 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