diff --git a/bundle.json b/bundle.json new file mode 100644 index 0000000000000000000000000000000000000000..291168b70f68d95078a827e1375dfa852b1c7d7d --- /dev/null +++ b/bundle.json @@ -0,0 +1,40 @@ +{ + "name": "@openharmony/memmgr", + "version": "3.1.0", + "description": "memory management", + "publishAs": "source", + "scripts": {}, + "author": {}, + "repository": "", + "license": "Apache License 2.0", + "component": { + "name": "plugins/memmgr", + "subsystem": "resourceschedule", + "adapted_system_type": [ "standard" ], + "deps": { + "components": [ + "libhilog", + "ipc_core", + "softbus_client", + "system_ability_fwk", + "samgr_proxy", + "utils_base", + "libhisysevent", + "libaccountkits", + "cesfwk_core", + "cesfwk_innerkits", + "want" + ], + "third_party": [] + }, + "build": { + "sub_component": [ + "//foundation/resourceschedule/plugins/memmgr/sa_profile:memmgr_sa_profile", + "//foundation/resourceschedule/plugins/memmgr/services/memmgrservice:memmgrservice", + "//foundation/resourceschedule/plugins/memmgr/services/memmgrservice:memmgrservice_init" + ], + "inner_kits": [], + "test": [], + } + } + } diff --git a/common/include/kernel_interface.h b/common/include/kernel_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..3cd345c7127331ad39bd23ee904dcf11449f1ee1 --- /dev/null +++ b/common/include/kernel_interface.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_KERNEL_INTERFACE_H +#define OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_KERNEL_INTERFACE_H + +#include "single_instance.h" +#include + +namespace OHOS { +namespace Memory { +class KernelInterface { + DECLARE_SINGLE_INSTANCE(KernelInterface); + +public: + bool EchoToPath(const char* path, const char* content); +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_KERNEL_INTERFACE_H diff --git a/common/include/memmgr_log.h b/common/include/memmgr_log.h new file mode 100644 index 0000000000000000000000000000000000000000..2bc8de23440b1ccc92bea44925f0d80f18c775d5 --- /dev/null +++ b/common/include/memmgr_log.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_MEM_MGR_LOG_H +#define OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_MEM_MGR_LOG_H + +#include "hilog/log.h" + +namespace OHOS { +namespace Memory { +static constexpr OHOS::HiviewDFX::HiLogLabel DP_LOG_LABEL = { + LOG_CORE, + 0x7001100, + "MemMgr" +}; + +#ifdef HILOGF +#undef HILOGF +#endif +#ifdef HILOGE +#undef HILOGE +#endif +#ifdef HILOGW +#undef HILOGW +#endif +#ifdef HILOGI +#undef HILOGI +#endif +#ifdef HILOGD +#undef HILOGD +#endif + +#define DP_LOG(level, fmt, ...) \ + HiviewDFX::HiLog::level(DP_LOG_LABEL, "%{public}s::%{public}s " fmt, TAG.c_str(), __FUNCTION__, ##__VA_ARGS__) + +#define HILOGF(fmt, ...) DP_LOG(Fatal, fmt, ##__VA_ARGS__) +#define HILOGE(fmt, ...) DP_LOG(Error, fmt, ##__VA_ARGS__) +#define HILOGW(fmt, ...) DP_LOG(Warn, fmt, ##__VA_ARGS__) +#define HILOGI(fmt, ...) DP_LOG(Info, fmt, ##__VA_ARGS__) +#define HILOGD(fmt, ...) DP_LOG(Debug, fmt, ##__VA_ARGS__) +} // namespace MemMgr +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_MEM_MGR_LOG_H diff --git a/common/include/single_instance.h b/common/include/single_instance.h new file mode 100644 index 0000000000000000000000000000000000000000..c0395d1ce34abb06d874f48c76e7f210618276d3 --- /dev/null +++ b/common/include/single_instance.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_SINGLE_INSTANCE_H +#define OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_SINGLE_INSTANCE_H + +namespace OHOS { +namespace MemMgr { +#define DECLARE_SINGLE_INSTANCE_BASE(className) \ +public: \ + static className& GetInstance(); \ +private: \ + className(const className&) = delete; \ + className& operator= (const className&) = delete; \ + className(className&&) = delete; \ + className& operator= (className&&) = delete; \ + +#define DECLARE_SINGLE_INSTANCE(className) \ + DECLARE_SINGLE_INSTANCE_BASE(className) \ +private: \ + className() = default; \ + ~className() = default; \ + +#define IMPLEMENT_SINGLE_INSTANCE(className) \ +className& className::GetInstance() \ +{ \ + static auto instance = new className(); \ + return *instance; \ +} +} // namespace MemMgr +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_COMMON_INCLUDE_SINGLE_INSTANCE_H diff --git a/common/src/kernel_interface.cpp b/common/src/kernel_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a0e34320dee3f8bf3cc367d151c1fe6a562f7619 --- /dev/null +++ b/common/src/kernel_interface.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel_interface.h" +#include "memmgr_log.h" + +#include +#include +#include +#include + + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "KernelInterface"; +} + +IMPLEMENT_SINGLE_INSTANCE(KernelInterface); + +bool KernelInterface::EchoToPath(const char* path, const char* content) +{ + uint32_t fd = open(path, O_RDWR, 0666); + if (fd == -1) { + HILOGE("echo %{public}s > %{public}s failed: file is not open", content, path); + return false; + } + if (write(fd, content, strlen(content)) < 0) { + HILOGE("echo %{public}s > %{public}s failed: write failed", content, path); + close(fd); + return false; + } + close(fd); + HILOGI("echo %{public}s > %{public}s", content, path); + return true; +} +} // namespace Memory +} // namespace OHOS diff --git a/memmgr.gni b/memmgr.gni new file mode 100644 index 0000000000000000000000000000000000000000..0687741cdadd1a22c3270ed770196d702040ed61 --- /dev/null +++ b/memmgr.gni @@ -0,0 +1,22 @@ +# Copyright (C) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +memmgr_subsystem_name = "resourceschedule" + +memmgr_part_name = "plugins/memmgr" + +memmgr_root_path = "//foundation/resourceschedule/${memmgr_part_name}" + +memmgr_common_path = "${memmgr_root_path}/common" + +memmgr_service_path = "${memmgr_root_path}/services/memmgrservice" \ No newline at end of file diff --git a/sa_profile/1909.xml b/sa_profile/1909.xml new file mode 100644 index 0000000000000000000000000000000000000000..4609242a5a16101dc15df3bdc7ec9101fa942af8 --- /dev/null +++ b/sa_profile/1909.xml @@ -0,0 +1,27 @@ + + + + memmgrservice + + /system/lib/libmemmgrservice.z.so + + + 1909 + /system/lib/libmemmgrservice.z.so + true + false + 1 + + diff --git a/sa_profile/BUILD.gn b/sa_profile/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4b011c8bd1539a7c9eea517c8180cfdc6dbfe697 --- /dev/null +++ b/sa_profile/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos/sa_profile/sa_profile.gni") +import("//foundation/resourceschedule/plugins/memmgr/memmgr.gni") + +ohos_sa_profile("memmgr_sa_profile") { + sources = [ "1909.xml" ] + part_name = "${memmgr_part_name}" +} diff --git a/services/memmgrservice/BUILD.gn b/services/memmgrservice/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d857c30bc5516a926a9010d5040caf29c7994133 --- /dev/null +++ b/services/memmgrservice/BUILD.gn @@ -0,0 +1,106 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/ohos_var.gni") + +import("//foundation/resourceschedule/plugins/memmgr/memmgr.gni") + +## Install memmgrservice.rc to /system/etc/init/memmgrservice.rc {{{ +ohos_prebuilt_etc("memmgrservice_init") { + if (use_musl) { + source = "memmgrservice.cfg" + } else { + source = "memmgrservice.rc" + } + relative_install_dir = "init" + part_name = "${memmgr_part_name}" + subsystem_name = "${memmgr_subsystem_name}" +} +## Install memmgrservice.rc to /system/etc/init/memmgrservice.rc }}} + +config("memory_memmgr_config") { + visibility = [ ":*" ] + include_dirs = [ + "include", + "${memmgr_root_path}/common/include", + "include/event/", + "include/reclaim_priority_manager/", + "include/kill_strategy_manager/", + "include/reclaim_strategy_manager/", + "include/config/", + "//base/notification/ces_standard/frameworks/core/include/", + "//base/notification/ces_standard/interfaces/innerkits/native/include", + "//base/account/os_account/interfaces/innerkits/osaccount/native/include", + "//base/account/os_account/frameworks/common/database/include", + "//base/account/os_account/frameworks/common/log/include", + "//base/account/os_account/frameworks/common/account_error/include" + ] + + defines = [ + "ACCOUNT_LOG_TAG = \"AppAccountFwk\"", + ] +} + +ohos_shared_library("memmgrservice") { + install_enable = true + sources = [ + "src/mem_mgr_service.cpp", + "src/event/mem_mgr_event_center.cpp", + "src/event/app_state_callback_mem_host.cpp", + "src/event/mem_mgr_event_subscriber.cpp", + "src/event/mem_mgr_event_observer.cpp", + "src/event/account_observer.cpp", + "src/event/account_subscriber.cpp", + "src/reclaim_priority_manager/reclaim_priority_manager.cpp", + "src/reclaim_priority_manager/process_priority_info.cpp", + "src/reclaim_priority_manager/bundle_priority_info.cpp", + "src/reclaim_priority_manager/os_account_priority_info.cpp", + "${memmgr_common_path}/src/kernel_interface.cpp", + ] + + configs = [ ":memory_memmgr_config" ] + + deps = [ + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base:appexecfwk_base", + "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_core:appexecfwk_core", + "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", + "//foundation/distributedschedule/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy", + "//utils/native/base:utils", + "//base/account/os_account/frameworks/common:libaccount_common", + "//base/account/os_account/frameworks/osaccount/native:os_account_innerkits", + ] + + external_deps = [ + "dsoftbus_standard:softbus_client", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "aafwk_standard:want", + "ces_standard:cesfwk_core", + "ces_standard:cesfwk_innerkits", + "hisysevent_native:libhisysevent", + "os_account_standard:libaccountkits", + ] + + part_name = "${memmgr_part_name}" + subsystem_name = "${memmgr_subsystem_name}" +} + +group("unittest") { + testonly = true + deps = [ "test:unittest" ] +} diff --git a/services/memmgrservice/include/event/account_observer.h b/services/memmgrservice/include/event/account_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..defaa00e5d4440245cd34c61aef197bb2140454d --- /dev/null +++ b/services/memmgrservice/include/event/account_observer.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_ACCOUNT_OBSERVER_H +#define OHOS_MEMORY_MEMMGR_ACCOUNT_OBSERVER_H + +#include "account_subscriber.h" + +namespace OHOS { +namespace Memory { +struct AccountCallback { + std::function OnOsAccountsChanged; +}; + +class AccountObserver { +public: + AccountObserver(const AccountCallback &callback); + ~AccountObserver(); + void OnAccountsChanged(const int &id); +protected: +private: + std::shared_ptr subscriber_; + AccountCallback callback_; +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_ACCOUNT_OBSERVER_H diff --git a/services/memmgrservice/include/event/account_subscriber.h b/services/memmgrservice/include/event/account_subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..3376bc93c89e196871d115c17322d92cbc42a63f --- /dev/null +++ b/services/memmgrservice/include/event/account_subscriber.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_ACCOUNT_SUBSCRIBER_H +#define OHOS_MEMORY_MEMMGR_ACCOUNT_SUBSCRIBER_H + +#include "os_account_subscriber.h" +#include "os_account_subscribe_info.h" + +namespace OHOS { +namespace Memory { +class AccountSubscriber : public AccountSA::OsAccountSubscriber { +public: + AccountSubscriber(const AccountSA::OsAccountSubscribeInfo &subscriberInfo, + const std::function &callback); + ~AccountSubscriber(); + virtual void OnAccountsChanged(const int &id) override; +protected: +private: + std::function callback_; +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_ACCOUNT_SUBSCRIBER_H diff --git a/services/memmgrservice/include/event/app_state_callback_mem_host.h b/services/memmgrservice/include/event/app_state_callback_mem_host.h new file mode 100644 index 0000000000000000000000000000000000000000..793f5a27bee67823b0a425a9570cecd55d7fdee8 --- /dev/null +++ b/services/memmgrservice/include/event/app_state_callback_mem_host.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_EVENT_MEM_HOST_H +#define OHOS_MEMORY_MEMMGR_EVENT_MEM_HOST_H + +#include "single_instance.h" +#include "memmgr_log.h" +#include + +#include "app_state_callback_host.h" +#include "app_process_data.h" +#include "app_mgr_client.h" + +namespace OHOS { +namespace Memory { +class AppStateCallbackMemHost : public AppExecFwk::AppStateCallbackHost { +public: + AppStateCallbackMemHost(); + ~AppStateCallbackMemHost(); + bool ConnectAppMgrService(); + bool Register(); +protected: + virtual void OnAppStateChanged(const AppExecFwk::AppProcessData &) override; +private: + std::unique_ptr appMgrClient_; +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_EVENT_MEM_HOST_H diff --git a/services/memmgrservice/include/event/mem_mgr_event_center.h b/services/memmgrservice/include/event/mem_mgr_event_center.h new file mode 100644 index 0000000000000000000000000000000000000000..0ba8316803fc4986a4c83a1d25d30b58205cf628 --- /dev/null +++ b/services/memmgrservice/include/event/mem_mgr_event_center.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_EVENT_CENTER_H +#define OHOS_MEMORY_MEMMGR_EVENT_CENTER_H + +#include "single_instance.h" +#include "event_handler.h" +#include "app_state_callback_mem_host.h" +#include "mem_mgr_event_observer.h" +#include "account_observer.h" + +namespace OHOS { +namespace Memory { +class MemMgrEventCenter { + DECLARE_SINGLE_INSTANCE_BASE(MemMgrEventCenter); + +public: + bool Init(); + ~MemMgrEventCenter(); + +protected: + /** + * @brief System common event receiver. + * @param eventData Common event data. + */ + void OnReceiveCaredEvent(const EventFwk::CommonEventData &eventData); + + void OnOsAccountsChanged(const int &id); + + void OnMemPsiUploaded(const int &level); +private: + MemMgrEventCenter(); + bool GetEventHandler(); + bool RegisterEventListener(); + void RegisterAppStateCallback(); + void RegisterSystemEventObserver(); + void RegisterAccountObserver(); + void RegisterMemPsiMonitor(); + + std::unique_ptr appStateCallback_; + std::unique_ptr sysEvtOberserver_; + std::unique_ptr accountOberserver_; + std::unique_ptr handler_; +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_EVENT_CENTER_H diff --git a/services/memmgrservice/include/event/mem_mgr_event_observer.h b/services/memmgrservice/include/event/mem_mgr_event_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..cbd35bcc8e6dfd26b60ecc77aab9cc5a9f4b4579 --- /dev/null +++ b/services/memmgrservice/include/event/mem_mgr_event_observer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_EVENT_OBSERVER_H +#define OHOS_MEMORY_MEMMGR_EVENT_OBSERVER_H + +#include "common_event_subscriber.h" +#include "common_event_subscribe_info.h" +#include "mem_mgr_event_subscriber.h" + +namespace OHOS { +namespace Memory { +struct MemMgrCaredEventCallback { + std::function OnReceiveCaredEvent; +}; + +class MemMgrEventObserver { +public: + MemMgrEventObserver(const MemMgrCaredEventCallback &callback); + ~MemMgrEventObserver(); + /** + * @brief System common event recei ver. + * @param eventData Common event data. + */ + void OnReceiveEvent(const EventFwk::CommonEventData &eventData); +protected: +private: + std::shared_ptr subscriber_; + MemMgrCaredEventCallback callback_; +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_EVENT_OBSERVER_H diff --git a/services/memmgrservice/include/event/mem_mgr_event_subscriber.h b/services/memmgrservice/include/event/mem_mgr_event_subscriber.h new file mode 100644 index 0000000000000000000000000000000000000000..1889680d4cce28a5c5107899d279ba869be84c67 --- /dev/null +++ b/services/memmgrservice/include/event/mem_mgr_event_subscriber.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_EVENT_SUBSCRIBER_H +#define OHOS_MEMORY_MEMMGR_EVENT_SUBSCRIBER_H + +#include "common_event_subscriber.h" +#include "common_event_subscribe_info.h" + +namespace OHOS { +namespace Memory { +class MemMgrEventSubscriber : public EventFwk::CommonEventSubscriber { +public: + MemMgrEventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo, + const std::function &callback); + ~MemMgrEventSubscriber(); + /** + * @brief System common event receiver. + * @param eventData Common event data. + */ + virtual void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; +protected: +private: + std::function callback_; +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_EVENT_SUBSCRIBER_H diff --git a/services/memmgrservice/include/mem_mgr_service.h b/services/memmgrservice/include/mem_mgr_service.h new file mode 100644 index 0000000000000000000000000000000000000000..107fdc39173f4e8b61c874d84e00aef4774e9811 --- /dev/null +++ b/services/memmgrservice/include/mem_mgr_service.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_SERVICE_H +#define OHOS_MEMORY_MEMMGR_SERVICE_H + +#include "single_instance.h" +#include "system_ability.h" + +namespace OHOS { +namespace Memory { +class MemMgrService : public SystemAbility { + DECLARE_SYSTEM_ABILITY(MemMgrService); + DECLARE_SINGLE_INSTANCE_BASE(MemMgrService); + +public: + MemMgrService(); + ~MemMgrService() = default; + +protected: + void OnStart() override; + void OnStop() override; + +private: + bool Init(); +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_SERVICE_H diff --git a/services/memmgrservice/include/reclaim_priority_manager/bundle_priority_info.h b/services/memmgrservice/include/reclaim_priority_manager/bundle_priority_info.h new file mode 100644 index 0000000000000000000000000000000000000000..5c62b459d6499ea309354f8eb4fc205af8470bef --- /dev/null +++ b/services/memmgrservice/include/reclaim_priority_manager/bundle_priority_info.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_BUNDLE_PRIORITY_INFO_H +#define OHOS_MEMORY_MEMMGR_BUNDLE_PRIORITY_INFO_H + +#include "reclaim_priority_constants.h" +#include "process_priority_info.h" +#include +#include +#include + +namespace OHOS { +namespace Memory { +class BundlePriorityInfo { +public: + using ProcessesInfoMap = std::map; + explicit BundlePriorityInfo(std::string name, int bundleUid); + explicit BundlePriorityInfo(std::string name, int bundleUid, int priority); + ~BundlePriorityInfo(); + inline bool operator<(const BundlePriorityInfo &tmp) const + { + return priority_ < tmp.priority_; + } + std::string name_; + int uid_; + ProcessesInfoMap processes_; + int priority_; + + bool ProcessExistInBundle(pid_t pid); + void AddProcess(ProcessPriorityInfo &newProcess); + void RemoveProcessById(pid_t pid); + ProcessPriorityInfo& FindProcessInfoById(pid_t pid); + int GetProcessCount(); + int GetMinProcessPriority(); + void SetPriority(int targetPriority); + void UpdatePriority(); +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_BUNDLE_PRIORITY_INFO_H diff --git a/services/memmgrservice/include/reclaim_priority_manager/os_account_priority_info.h b/services/memmgrservice/include/reclaim_priority_manager/os_account_priority_info.h new file mode 100644 index 0000000000000000000000000000000000000000..b7727f2baf6d2a823d13c5965ebef6cd22285cec --- /dev/null +++ b/services/memmgrservice/include/reclaim_priority_manager/os_account_priority_info.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_OS_ACCOUNT_PRIORITY_INFO_H +#define OHOS_MEMORY_MEMMGR_OS_ACCOUNT_PRIORITY_INFO_H + +#include "reclaim_priority_constants.h" +#include "bundle_priority_info.h" + +#include +#include +#include + +namespace OHOS { +namespace Memory { +class OsAccountPriorityInfo { +public: + int id_; + bool isCurOsAccount_; + bool isPreOsAccount_; + int priorityShift_; + + explicit OsAccountPriorityInfo(int accountId, bool isCurrent); + bool BundleExist(int bundleId); + BundlePriorityInfo* FindBundleInfoById(int bundleId); + void AddBundleToUser(BundlePriorityInfo* bundle); + void RemoveBundleById(int bundleUid); + int BundleCount(); + void setProcessPriority(int targetPriority); + void PromoteAllBundlePriority(int shift); + void ReduceAllBundlePriority(int shift); +private: + // map + using BundlePrioMap = std::map; + BundlePrioMap bundleIdInfoMapping_; + + void AdjustAllBundlePriority(int shift); +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_OS_ACCOUNT_PRIORITY_INFO_H diff --git a/services/memmgrservice/include/reclaim_priority_manager/process_priority_info.h b/services/memmgrservice/include/reclaim_priority_manager/process_priority_info.h new file mode 100644 index 0000000000000000000000000000000000000000..e9d72eb01de72d1d9b1985729f24d4e35b11dcab --- /dev/null +++ b/services/memmgrservice/include/reclaim_priority_manager/process_priority_info.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_PROCESS_PRIORITY_INFO_H +#define OHOS_MEMORY_MEMMGR_PROCESS_PRIORITY_INFO_H + +#include "reclaim_priority_constants.h" +#include +#include + +namespace OHOS { +namespace Memory { +class ProcessPriorityInfo { +public: + explicit ProcessPriorityInfo(pid_t pid, int bundleUid, int priority); + int uid_; + pid_t pid_; + int priority_; + bool isBackgroundRunning; + bool isSuspendDelay; + bool isEventStart; + bool isDataAbilityStart; + void SetPriority(int targetPriority); +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_PROCESS_PRIORITY_INFO_H diff --git a/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h new file mode 100644 index 0000000000000000000000000000000000000000..505c488a2ff4c71b7db7d7b833263e0198d71044 --- /dev/null +++ b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_CONSTANTS_H +#define OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_CONSTANTS_H + +#include +#include +#include + +namespace OHOS { +namespace Memory { +// system app +constexpr int RECLAIM_PRIORITY_SYSTEM = -1000; +// foreground process priority +constexpr int RECLAIM_PRIORITY_FOREGROUND = 0; +// perceived suspend delay case +constexpr int RECLAIM_PRIORITY_BG_SUSPEND_DELAY = 100; +// perceived background process priority +constexpr int RECLAIM_PRIORITY_BG_PERCEIVED = 200; +// backgroud priority +constexpr int RECLAIM_PRIORITY_BACKGROUND = 400; +// suspend process priority +constexpr int RECLAIM_PRIORITY_SUSPEND = 800; +// visible process priority +constexpr int RECLAIM_PRIORITY_VISIBLE = 1; +// frozen process priority +constexpr int RECLAIM_PRIORITY_FROZEN = 600; +// empty process priority +constexpr int RECLAIM_PRIORITY_EMPTY = 900; +// unknown process priority +constexpr int RECLAIM_PRIORITY_UNKNOWN = 1000; + +constexpr std::string_view SYSTEM_UI_BUNDLE_NAME = "com.ohos.systemui"; +constexpr std::string_view LAUNCHER_BUNDLE_NAME = "com.ohos.launcher"; + +const int USER_ID_SHIFT = 100000; + +enum class AppStateUpdateReason { + CREATE_PROCESS = 0, + PROCESS_READY, + FOREGROUND, + BACKGROUND, + SUSPEND_DELAY_START, + SUSPEND_DELAY_END, + BACKGROUND_RUNNING_START, + BACKGROUND_RUNNING_END, + EVENT_START, + EVENT_END, + DATA_ABILITY_START, + DATA_ABILITY_END, + PROCESS_SUSPEND, + PROCESS_TERMINATED, + OS_ACCOUNT_HOT_SWITCH, +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_CONSTANTS_H diff --git a/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..f470bac46d1400a3b373ad2f6eff94fc24a584dc --- /dev/null +++ b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H +#define OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H + +#include "single_instance.h" +#include "event_handler.h" +#include "reclaim_priority_constants.h" +#include "process_priority_info.h" +#include "bundle_priority_info.h" +#include "os_account_priority_info.h" + +#include +#include +#include + +namespace OHOS { +namespace Memory { +class ReclaimPriorityManager { + DECLARE_SINGLE_INSTANCE_BASE(ReclaimPriorityManager); + +public: + struct BundleInfoPtrCmp { + bool operator()(const BundlePriorityInfo* p1, const BundlePriorityInfo* p2) + { + if (p1->priority_ <= p2->priority_) { + return true; + } else { + return false; + } + } + }; + + using BundlePrioSet = std::set; + // map + using BundlePrioMap = std::map; + bool Init(); + bool UpdateReclaimPriority(pid_t pid, int bundleUid, std::string bundleName, AppStateUpdateReason priorityReason); + bool UpdateAllReclaimPriority(AppStateUpdateReason priorityReason); + bool CurrentOsAccountChanged(int curAccountId); + + // two methods below used to manage totalBundlePrioSet_ by BundlePriorityInfo + void AddBundleInfoToSet(BundlePriorityInfo* bundleInfo); + void UpdateBundlePriority(BundlePriorityInfo* bundleInfo); + void DeleteBundleInfoFromSet(BundlePriorityInfo* bundleInfo); + + inline bool Initailized() + { + return initialized_; + }; + +protected: + // for lmkd and memory reclaim + const BundlePrioSet GetBundlePrioSet(); + +private: + bool initialized_ = false; + int preOsAccountId_ = 0; + int curOsAccountId_ = 0; + + // map + std::map osAccountsInfoMap_; + // total system prioritySet + // when new a BundlePriorityInfo, it will be added into this set + // when delete a BundlePriorityInfo, it will be removed from this set + // when change the priority of BundlePriorityInfo, it will be removed and added from this set to re-sort it + BundlePrioSet totalBundlePrioSet_; + + std::shared_ptr handler_; + ReclaimPriorityManager(); + bool GetEventHandler(); + bool UpdateReclaimPriorityInner(pid_t pid, int bundleUid, std::string bundleName, + AppStateUpdateReason priorityReason); + bool CurrentOsAccountChangedInner(int curAccountId); + bool ApplyReclaimPriority(BundlePriorityInfo *bundleInfo, ProcessPriorityInfo &processInfo); + bool IsProcessExist(pid_t pid, int bundleUid, int accountId); + bool IsUserExist(int accountId); + bool HandleCreateProcess(int pid, int bundleUid, std::string bundleName, int accountId); + void HandleTerminateProcess(ProcessPriorityInfo &processInfo, BundlePriorityInfo *bundleInfo, + OsAccountPriorityInfo *osAccountInfo); + int GetBundleMinPriority(BundlePriorityInfo *bInfo); + OsAccountPriorityInfo* FindUserInfoById(int accountId); + void RemoveUserInfoById(int accountId); + void AddOsAccountInfo(OsAccountPriorityInfo account); + bool IsSystemApp(BundlePriorityInfo &bundleInfo); + + static inline int GetOsAccountLocalIdFromUid(int bundleUid) + { + return bundleUid / USER_ID_SHIFT; + } +}; +} // namespace Memory +} // namespace OHOS +#endif // OHOS_MEMORY_MEMMGR_RECALIM_PRIORITY_MANAGER_H diff --git a/services/memmgrservice/memmgrservice.cfg b/services/memmgrservice/memmgrservice.cfg new file mode 100644 index 0000000000000000000000000000000000000000..3c45ae10eb14b90a46fdc7cbb204261a86fac9f1 --- /dev/null +++ b/services/memmgrservice/memmgrservice.cfg @@ -0,0 +1,16 @@ +{ + "jobs" : [{ + "name" : "post-fs-data", + "cmds" : [ + "start memmgrservice" + ] + } + ], + "services" : [{ + "name" : "memmgrservice", + "path" : ["/system/bin/sa_main", "/system/profile/memmgrservice.xml"], + "uid" : "root", + "gid" : ["system", "shell", "uhid", "root"] + } + ] +} diff --git a/services/memmgrservice/memmgrservice.rc b/services/memmgrservice/memmgrservice.rc new file mode 100644 index 0000000000000000000000000000000000000000..eafd376530229ce360d888304a8a2738b388be43 --- /dev/null +++ b/services/memmgrservice/memmgrservice.rc @@ -0,0 +1,21 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +on post-fs-data + start memmgrservice + +service memmgrservice /system/bin/sa_main /system/profile/memmgrservice.xml + class z_core + user root + group root shell + seclabel u:r:softbus_server:s0 diff --git a/services/memmgrservice/src/event/account_observer.cpp b/services/memmgrservice/src/event/account_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a64f3e6da7ab214168a0081e7c2fb490429a602f --- /dev/null +++ b/services/memmgrservice/src/event/account_observer.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_observer.h" +#include "memmgr_log.h" + +#include "os_account_manager.h" +#include "os_account_info.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "AccountObserver"; +} + +AccountObserver::AccountObserver(const AccountCallback &callback) : callback_(callback) +{ + HILOGI("called"); + + AccountSA::OsAccountInfo osAccountInfo; + AccountSA::OsAccountManager::QueryCurrentOsAccount(osAccountInfo); + HILOGI("curOsAccount: id=%{public}d, name=%{public}s", osAccountInfo.GetLocalId(), osAccountInfo.GetLocalName().c_str()); + // the account has been changed before + OnAccountsChanged(osAccountInfo.GetLocalId()); + + AccountSA::OsAccountSubscribeInfo osAccountSubscribeInfo; + osAccountSubscribeInfo.SetOsAccountSubscribeType(AccountSA::OS_ACCOUNT_SUBSCRIBE_TYPE::ACTIVED); + osAccountSubscribeInfo.SetName("MemMgrAccountActivedSubscriber"); + + subscriber_ = std::make_shared(osAccountSubscribeInfo, + std::bind(&AccountObserver::OnAccountsChanged, this, std::placeholders::_1)); + ErrCode errCode = AccountSA::OsAccountManager::SubscribeOsAccount(subscriber_); + HILOGI("SubscribeOsAccount errCode=%{public}d", errCode); +} + +AccountObserver::~AccountObserver() +{ + if (subscriber_) { + AccountSA::OsAccountManager::UnsubscribeOsAccount(subscriber_); + } +} + +void AccountObserver::OnAccountsChanged(const int &id) +{ + HILOGI("called"); + if (callback_.OnOsAccountsChanged != nullptr) { + callback_.OnOsAccountsChanged(id); + } +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/event/account_subscriber.cpp b/services/memmgrservice/src/event/account_subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7412af0be6b7ed7d61698bb7c1eacf9af0f1a7e0 --- /dev/null +++ b/services/memmgrservice/src/event/account_subscriber.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_subscriber.h" +#include "memmgr_log.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "AccountSubscriber"; +} + +AccountSubscriber::AccountSubscriber(const AccountSA::OsAccountSubscribeInfo &subscriberInfo, + const std::function &callback) + : AccountSA::OsAccountSubscriber(subscriberInfo), callback_(callback) +{ +} + +AccountSubscriber::~AccountSubscriber() +{ + callback_ = nullptr; +} + +void AccountSubscriber::OnAccountsChanged(const int &id) +{ + HILOGI("called"); + if (callback_ != nullptr) { + callback_(id); + } +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/event/app_state_callback_mem_host.cpp b/services/memmgrservice/src/event/app_state_callback_mem_host.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b4f825e2162753f4e3d563258158646daed39a1 --- /dev/null +++ b/services/memmgrservice/src/event/app_state_callback_mem_host.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_state_callback_mem_host.h" +#include "memmgr_log.h" +#include "reclaim_priority_manager.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "AppStateCallbackMemHost"; +} + +AppStateCallbackMemHost::AppStateCallbackMemHost() : appMgrClient_(std::make_unique()) +{ +} + +AppStateCallbackMemHost::~AppStateCallbackMemHost() +{ +} + +bool AppStateCallbackMemHost::ConnectAppMgrService() +{ + if (appMgrClient_ == nullptr) { + return false; + } + int result = static_cast(appMgrClient_->ConnectAppMgrService()); + return result == ERR_OK; +} + +bool AppStateCallbackMemHost::Register() +{ + int result = static_cast(appMgrClient_->RegisterAppStateCallback(sptr(this))); + return result == ERR_OK; +} + +void AppStateCallbackMemHost::OnAppStateChanged(const AppExecFwk::AppProcessData &appData) +{ + std::string appName = appData.appName; + HILOGI("called appName=<%{public}s>", appName.c_str()); + switch (appData.appState) { + case AppExecFwk::ApplicationState::APP_STATE_CREATE: + ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(appData.pid, appData.uid, + appData.appName, AppStateUpdateReason::CREATE_PROCESS); + break; + case AppExecFwk::ApplicationState::APP_STATE_READY: + ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(appData.pid, appData.uid, + appData.appName, AppStateUpdateReason::PROCESS_READY); + break; + case AppExecFwk::ApplicationState::APP_STATE_FOREGROUND: + ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(appData.pid, appData.uid, + appData.appName, AppStateUpdateReason::FOREGROUND); + break; + case AppExecFwk::ApplicationState::APP_STATE_BACKGROUND: + ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(appData.pid, appData.uid, + appData.appName, AppStateUpdateReason::BACKGROUND); + break; + case AppExecFwk::ApplicationState::APP_STATE_SUSPENDED: + ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(appData.pid, appData.uid, + appData.appName, AppStateUpdateReason::PROCESS_SUSPEND); + break; + case AppExecFwk::ApplicationState::APP_STATE_TERMINATED: + ReclaimPriorityManager::GetInstance().UpdateReclaimPriority(appData.pid, appData.uid, + appData.appName, AppStateUpdateReason::PROCESS_TERMINATED); + break; + default: + break; + } + // notify kill stratagy manager + + // notify reclaim stratagy manager +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/event/mem_mgr_event_center.cpp b/services/memmgrservice/src/event/mem_mgr_event_center.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d83d88ed31854aa8bc5cad217dfc3a79df54db2 --- /dev/null +++ b/services/memmgrservice/src/event/mem_mgr_event_center.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "mem_mgr_event_center.h" +#include "memmgr_log.h" + +#include "mem_mgr_event_observer.h" +#include "reclaim_priority_manager.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "MemMgrEventCenter"; +} + +IMPLEMENT_SINGLE_INSTANCE(MemMgrEventCenter); + +MemMgrEventCenter::MemMgrEventCenter() : appStateCallback_(std::make_unique()) +{ +} + +MemMgrEventCenter::~MemMgrEventCenter() +{ + appStateCallback_ = nullptr; +} + +bool MemMgrEventCenter::Init() +{ + HILOGI("called"); + if (GetEventHandler()) { + return RegisterEventListener(); + } + return false; +} + +bool MemMgrEventCenter::GetEventHandler() +{ + if (!handler_) { + handler_ = std::make_unique(AppExecFwk::EventRunner::Create()); + if (handler_ == nullptr) { + HILOGI("failed to create event handler"); + return false; + } + } + return true; +} + +bool MemMgrEventCenter::RegisterEventListener() +{ + HILOGI("called"); + //RegisterAppStateCallback(); + + //RegisterSystemEventObserver(); + + //RegisterAccountObserver(); + + //RegisterMemPsiMonitor(); + + return true; +} + +void MemMgrEventCenter::RegisterAppStateCallback() +{ + HILOGI("called"); + if (!appStateCallback_->ConnectAppMgrService()) { + HILOGE("failed to ConnectAppMgrService, try again after 1s!"); + std::function RegisterEventListenerFunc = std::bind( + &MemMgrEventCenter::RegisterAppStateCallback, this); + handler_->PostTask(RegisterEventListenerFunc, 1000, AppExecFwk::EventQueue::Priority::LOW); // 1000 means 1s + return; + } + HILOGI("success to ConnectAppMgrService"); + + if (!appStateCallback_->Register()) { + HILOGE("failed to RegisterAppStateCallback"); + return; + } + HILOGI("success to RegisterAppStateCallback"); +} + +void MemMgrEventCenter::RegisterSystemEventObserver() +{ + MemMgrCaredEventCallback callback = { + std::bind(&MemMgrEventCenter::OnReceiveCaredEvent, this, std::placeholders::_1), + }; + sysEvtOberserver_ = std::make_unique(callback); + HILOGI("success to register cared event callback"); +} + +void MemMgrEventCenter::RegisterAccountObserver() +{ + AccountCallback callback = { + std::bind(&MemMgrEventCenter::OnOsAccountsChanged, this, std::placeholders::_1), + }; + accountOberserver_ = std::make_unique(callback); + HILOGI("success to register account callback"); +} + +void MemMgrEventCenter::RegisterMemPsiMonitor() +{ + HILOGI("success to register psi callback"); +} + +// callback list below + +void MemMgrEventCenter::OnReceiveCaredEvent(const EventFwk::CommonEventData &eventData) +{ + auto want = eventData.GetWant(); + std::string action = want.GetAction(); + HILOGI("action=<%{public}s>", action.c_str()); +} + +void MemMgrEventCenter::OnOsAccountsChanged(const int &id) +{ + HILOGI("account changed=<%{public}d>", id); + // notify reclaim priority manager + ReclaimPriorityManager::GetInstance().CurrentOsAccountChanged(id); +} + +void MemMgrEventCenter::OnMemPsiUploaded(const int &level) +{ + HILOGI("memory psi level=<%{public}d>", level); + // notify kill strategy manager +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/event/mem_mgr_event_observer.cpp b/services/memmgrservice/src/event/mem_mgr_event_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15eb7ebbd95998d2d0a273af882153bd401b5226 --- /dev/null +++ b/services/memmgrservice/src/event/mem_mgr_event_observer.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mem_mgr_event_observer.h" +#include "memmgr_log.h" + +#include "common_event.h" +#include "common_event_manager.h" +#include "common_event_support.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "MemMgrEventObserver"; +} + +MemMgrEventObserver::MemMgrEventObserver(const MemMgrCaredEventCallback &callback) : callback_(callback) +{ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_POWER_CONNECTED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_POWER_DISCONNECTED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_TICK); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_STARTED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_BACKGROUND); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_FOREGROUND); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_STARTING); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_STOPPING); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_STOPPED); + EventFwk::CommonEventSubscribeInfo commonEventSubscribeInfo(matchingSkills); + + subscriber_ = std::make_shared(commonEventSubscribeInfo, + std::bind(&MemMgrEventObserver::OnReceiveEvent, this, std::placeholders::_1)); + EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber_); +} + +MemMgrEventObserver::~MemMgrEventObserver() +{ + if (subscriber_) { + EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber_); + } +} + +void MemMgrEventObserver::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + HILOGI("called"); + if (callback_.OnReceiveCaredEvent != nullptr) { + callback_.OnReceiveCaredEvent(eventData); + } +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/event/mem_mgr_event_subscriber.cpp b/services/memmgrservice/src/event/mem_mgr_event_subscriber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34569666739268bf361a0d697a6fde05d499db1d --- /dev/null +++ b/services/memmgrservice/src/event/mem_mgr_event_subscriber.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mem_mgr_event_subscriber.h" +#include "memmgr_log.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "MemMgrEventSubscriber"; +} + +MemMgrEventSubscriber::MemMgrEventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo, + const std::function &callback) + : EventFwk::CommonEventSubscriber(subscriberInfo), callback_(callback) +{ +} + +MemMgrEventSubscriber::~MemMgrEventSubscriber() +{ + callback_ = nullptr; +} + +void MemMgrEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + HILOGI("called"); + if (callback_ != nullptr) { + callback_(eventData); + } +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/mem_mgr_service.cpp b/services/memmgrservice/src/mem_mgr_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a363f3a757844f33dcab9d974d7425dcf152ff55 --- /dev/null +++ b/services/memmgrservice/src/mem_mgr_service.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mem_mgr_service.h" +#include "memmgr_log.h" +#include "system_ability_definition.h" +#include "mem_mgr_event_center.h" +#include "reclaim_priority_manager.h" + +#include + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "MemMgrService"; +} + +IMPLEMENT_SINGLE_INSTANCE(MemMgrService); +const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&MemMgrService::GetInstance()); + +MemMgrService::MemMgrService() : SystemAbility(MEMORY_MANAGER_SA_ID, true) +{ +} + +bool MemMgrService::Init() +{ + // init reclaim priority manager + if (!ReclaimPriorityManager::GetInstance().Init()) { + HILOGE("ReclaimPriorityManager init failed"); + return false; + } + + // init kill strategy manager + + // init reclaim strategy manager + + // init event center, then managers above can work by event trigger + if (!MemMgrEventCenter::GetInstance().Init()) { + HILOGE("MemMgrEventCenter init failed"); + return false; + } + HILOGI("init successed"); + return true; +} + +void MemMgrService::OnStart() +{ + HILOGI("called"); + if (!Init()) { + HILOGE("init failed"); + return; + } +} + +void MemMgrService::OnStop() +{ + HILOGI("called"); +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/reclaim_priority_manager/bundle_priority_info.cpp b/services/memmgrservice/src/reclaim_priority_manager/bundle_priority_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..743aae1a5298a2d62527b2b2ab4e53671a04f13d --- /dev/null +++ b/services/memmgrservice/src/reclaim_priority_manager/bundle_priority_info.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this->file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bundle_priority_info.h" +#include "memmgr_log.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "BundlePriorityInfo"; +} // namespace + +BundlePriorityInfo::BundlePriorityInfo(std::string name, int bundleUid):name_(name), uid_(bundleUid) +{ + this->priority_ = RECLAIM_PRIORITY_UNKNOWN; +} + +BundlePriorityInfo::BundlePriorityInfo(std::string name, int bundleUid, int priority):name_(name), + uid_(bundleUid), priority_(priority) +{ +} + +BundlePriorityInfo::~BundlePriorityInfo() +{ + delete this; +} + +bool BundlePriorityInfo::ProcessExistInBundle(pid_t pid) +{ + if (processes_.count(pid) == 0) { + return false; + } + return true; +} + +void BundlePriorityInfo::AddProcess(ProcessPriorityInfo &newProcess) +{ + processes_.insert(std::make_pair(newProcess.pid_, newProcess)); +} + +void BundlePriorityInfo::RemoveProcessById(pid_t pid) +{ + processes_.erase(pid); +} + +int BundlePriorityInfo::GetProcessCount() +{ + return processes_.size(); +} + +ProcessPriorityInfo& BundlePriorityInfo::FindProcessInfoById(pid_t pid) +{ + return processes_.at(pid); +} + +int BundlePriorityInfo::GetMinProcessPriority() +{ + int min_priority = RECLAIM_PRIORITY_UNKNOWN; + for (auto i = processes_.begin(); i != processes_.end(); ++i) { + if (i->second.priority_ < min_priority) { + min_priority = i->second.priority_; + } + } + return min_priority; +} + +void BundlePriorityInfo::SetPriority(int targetPriority) +{ + priority_ = targetPriority; +} + +void BundlePriorityInfo::UpdatePriority() +{ + int targetPriority = GetMinProcessPriority(); + SetPriority(targetPriority); + HILOGI("bundleName=%{public}s, priority=%{public}d", name_.c_str(), priority_); +} + + +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/reclaim_priority_manager/os_account_priority_info.cpp b/services/memmgrservice/src/reclaim_priority_manager/os_account_priority_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b3d89bf20185ddb4c82448dd4fa692caae84d05 --- /dev/null +++ b/services/memmgrservice/src/reclaim_priority_manager/os_account_priority_info.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this->file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "os_account_priority_info.h" +#include "memmgr_log.h" + + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "OsAccountPriorityInfo"; +const int OS_ACCOUNT_PRIORITY_SHIFT_DEFAULT = 50; +} // namespace + +OsAccountPriorityInfo::OsAccountPriorityInfo(int accountId, bool isCurrent):id_(accountId), isCurOsAccount_(isCurrent) +{ + isPreOsAccount_ = false; + priorityShift_ = OS_ACCOUNT_PRIORITY_SHIFT_DEFAULT; +} + +bool OsAccountPriorityInfo::BundleExist(int bundleUId) +{ + if (bundleIdInfoMapping_.count(bundleUId) == 0) { + return false; + } + return true; +} + +BundlePriorityInfo* OsAccountPriorityInfo::FindBundleInfoById(int bundleUId) +{ + return bundleIdInfoMapping_.at(bundleUId); +} + +void OsAccountPriorityInfo::AddBundleToUser(BundlePriorityInfo* bundle) +{ + bundleIdInfoMapping_.insert(std::make_pair(bundle->uid_, bundle)); +} + +void OsAccountPriorityInfo::RemoveBundleById(int bundleUid) +{ + bundleIdInfoMapping_.erase(bundleUid); +} + +int OsAccountPriorityInfo::BundleCount() +{ + return bundleIdInfoMapping_.size(); +} + +void OsAccountPriorityInfo::PromoteAllBundlePriority(int shift) +{ + AdjustAllBundlePriority(-shift); +} + +void OsAccountPriorityInfo::ReduceAllBundlePriority(int shift) +{ + AdjustAllBundlePriority(shift); +} + +void OsAccountPriorityInfo::AdjustAllBundlePriority(int shift) +{ + for (auto i = bundleIdInfoMapping_.begin(); i != bundleIdInfoMapping_.end(); ++i) { + BundlePriorityInfo *bundleInfo = i->second; + int targetPriority = bundleInfo->priority_ + shift; + bundleInfo->SetPriority(targetPriority); + + } +} + + + +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/reclaim_priority_manager/process_priority_info.cpp b/services/memmgrservice/src/reclaim_priority_manager/process_priority_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..350a4130291454cbe01a7d801802ab4301c2eb0e --- /dev/null +++ b/services/memmgrservice/src/reclaim_priority_manager/process_priority_info.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "process_priority_info.h" +#include "memmgr_log.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "ProcessPriorityInfo"; + +} // namespace + +ProcessPriorityInfo::ProcessPriorityInfo(pid_t pid, int bundleUid, int priority) +{ + HILOGI("ProcessPriorityInfo constructed with priority"); + this->uid_ = bundleUid; + this->pid_ = pid; + this->priority_ = priority; + this->isBackgroundRunning = false; + this->isSuspendDelay = false; + this->isEventStart = false; + this->isDataAbilityStart = false; +} + +void ProcessPriorityInfo::SetPriority(int targetPriority) +{ + priority_ = targetPriority; +} +} // namespace Memory +} // namespace OHOS diff --git a/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp b/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..82b243069f60196a62335f053b6456f20e7b488b --- /dev/null +++ b/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "reclaim_priority_manager.h" +#include "memmgr_log.h" +#include "kernel_interface.h" + +namespace OHOS { +namespace Memory { +namespace { +const std::string TAG = "ReclaimPriorityManager"; +} +IMPLEMENT_SINGLE_INSTANCE(ReclaimPriorityManager); + +bool WriteOomScoreAdjToKernel(const BundlePriorityInfo *bInfo) +{ + if (bInfo == nullptr) { + return false; + } + int pathSize = 30; + int contentSize = 10; + char path[pathSize]; + char content[contentSize]; + for (auto i = bInfo->processes_.begin(); i != bInfo->processes_.end(); ++i) { + int priority = i->second.priority_; + int pid = i->second.pid_; + snprintf(path, pathSize, "/proc/%d/oom_score_adj", pid); + snprintf(content, contentSize, "%d", priority); + KernelInterface::GetInstance().EchoToPath(path, content); + } + return true; +} + +ReclaimPriorityManager::ReclaimPriorityManager() +{ +} + +bool ReclaimPriorityManager::Init() +{ + initialized_ = GetEventHandler(); + if (initialized_) { + HILOGI("init successed"); + } else { + HILOGE("init failed"); + } + return initialized_; +} + +bool ReclaimPriorityManager::GetEventHandler() +{ + if (!handler_) { + handler_ = std::make_shared(AppExecFwk::EventRunner::Create()); + if (handler_ == nullptr) { + HILOGE("handler init failed"); + return false; + } + } + return true; +} + +bool ReclaimPriorityManager::IsUserExist(int accountId) +{ + if (osAccountsInfoMap_.find(accountId) == osAccountsInfoMap_.end()) { + HILOGE("accountId not exist"); + return false; + } + return true; +} + +void ReclaimPriorityManager::AddBundleInfoToSet(BundlePriorityInfo* bundleInfo) +{ + totalBundlePrioSet_.insert(bundleInfo); +} + +void ReclaimPriorityManager::DeleteBundleInfoFromSet(BundlePriorityInfo* bundleInfo) +{ + totalBundlePrioSet_.erase(bundleInfo); +} + +OsAccountPriorityInfo* ReclaimPriorityManager::FindUserInfoById(int accountId) +{ + return &(osAccountsInfoMap_.at(accountId)); +} + +void ReclaimPriorityManager::RemoveUserInfoById(int accountId) +{ + // erase the accountId data + osAccountsInfoMap_.erase(accountId); +} + +void ReclaimPriorityManager::AddOsAccountInfo(OsAccountPriorityInfo account) +{ + osAccountsInfoMap_.insert(std::make_pair(account.id_, account)); +} + +bool ReclaimPriorityManager::IsProcessExist(pid_t pid, int bundleUid, int accountId) +{ + if (!IsUserExist(accountId)) { + return false; + } + OsAccountPriorityInfo *osAccountInfo = FindUserInfoById(accountId); + if (!osAccountInfo->BundleExist(bundleUid)) { + HILOGE("bundle name not exist"); + return false; + } + BundlePriorityInfo* bundleInfo = osAccountInfo->FindBundleInfoById(bundleUid); + if (!bundleInfo->ProcessExistInBundle(pid)) { + HILOGE("pid not exist"); + return false; + } + return true; +} + +bool ReclaimPriorityManager::UpdateReclaimPriority(pid_t pid, int bundleUid, + std::string name, AppStateUpdateReason reason) +{ + if (!initialized_) { + HILOGE("has not been initialized_, skiped!"); + return false; + } + std::function updateReclaimPriorityInnerFunc = + std::bind(&ReclaimPriorityManager::UpdateReclaimPriorityInner, this, pid, bundleUid, name, reason); + return handler_->PostImmediateTask(updateReclaimPriorityInnerFunc); +} + +bool ReclaimPriorityManager::IsSystemApp(BundlePriorityInfo &bundleInfo) +{ + // special case: launcher and system ui bundle + if (bundleInfo.name_ == LAUNCHER_BUNDLE_NAME || bundleInfo.name_ == SYSTEM_UI_BUNDLE_NAME) { + return true; + } + return false; +} + +void ReclaimPriorityManager::UpdateBundlePriority(BundlePriorityInfo *bundleInfo) +{ + DeleteBundleInfoFromSet(bundleInfo); + bundleInfo->UpdatePriority(); + AddBundleInfoToSet(bundleInfo); +} + +bool ReclaimPriorityManager::HandleCreateProcess(int pid, int bundleUid, std::string bundleName, int accountId) +{ + if (!IsUserExist(accountId)) { + OsAccountPriorityInfo newAccount(accountId, true); + AddOsAccountInfo(newAccount); + } + OsAccountPriorityInfo* osAccountInfo = FindUserInfoById(accountId); + BundlePriorityInfo *bundleInfo; + if (osAccountInfo->BundleExist(bundleUid)) { + // insert new ProcessInfo and update new priority + bundleInfo = osAccountInfo->FindBundleInfoById(bundleUid); + } else { + // need to new BundleInfo ,add to list and map + bundleInfo = new BundlePriorityInfo(bundleName, bundleUid, RECLAIM_PRIORITY_FOREGROUND); + AddBundleInfoToSet(bundleInfo); + } + ProcessPriorityInfo *processInfo; + if (IsSystemApp(*bundleInfo)) { + processInfo = new ProcessPriorityInfo(pid, bundleUid, RECLAIM_PRIORITY_SYSTEM); + } else { + processInfo = new ProcessPriorityInfo(pid, bundleUid, RECLAIM_PRIORITY_FOREGROUND); + } + bundleInfo->AddProcess(*processInfo); + UpdateBundlePriority(bundleInfo); + osAccountInfo->AddBundleToUser(bundleInfo); + bool ret = ApplyReclaimPriority(bundleInfo, *processInfo); + HILOGI("create: bundleName=%{public}s, prio=%{public}d", bundleName.c_str(), bundleInfo->priority_); + return ret; +} + +void ReclaimPriorityManager::HandleTerminateProcess(ProcessPriorityInfo &processInfo, + BundlePriorityInfo *bundleInfo, OsAccountPriorityInfo *osAccountInfo) +{ + // clear processInfo and bundleInfo if needed, delete the object + HILOGI("terminated: bundleName=%{public}s, pid=%{public}d", bundleInfo->name_.c_str(), processInfo.pid_); + int removedProcessPrio = processInfo.priority_; + bundleInfo->RemoveProcessById(processInfo.pid_); + + if (bundleInfo->GetProcessCount() == 0) { + osAccountInfo->RemoveBundleById(bundleInfo->uid_); + DeleteBundleInfoFromSet(bundleInfo); + delete bundleInfo; + bundleInfo = nullptr; + } else { + if (removedProcessPrio <= bundleInfo->priority_) { + UpdateBundlePriority(bundleInfo); + } + } + if (osAccountInfo->BundleCount() == 0) { + RemoveUserInfoById(osAccountInfo->id_); + } +} + +bool ReclaimPriorityManager::UpdateReclaimPriorityInner(pid_t pid, int bundleUid, + std::string bundleName, AppStateUpdateReason reason) +{ + int accountId = GetOsAccountLocalIdFromUid(bundleUid); + + if (reason == AppStateUpdateReason::CREATE_PROCESS) { + bool ret = HandleCreateProcess(pid, bundleUid, bundleName, accountId); + return ret; + } + + if (!IsProcessExist(pid, bundleUid, accountId)) { + HILOGE("process not exist and not to create it!!"); + return false; + } + + OsAccountPriorityInfo* osAccountInfo = FindUserInfoById(accountId); + BundlePriorityInfo *bundleInfo = osAccountInfo->FindBundleInfoById(bundleUid); + if (bundleInfo->priority_ == RECLAIM_PRIORITY_SYSTEM) { + HILOGI("%{public}s is system app, skip!", bundleName.c_str()); + return true; + } + + ProcessPriorityInfo &processInfo = bundleInfo->FindProcessInfoById(pid); + + bool ret = true; + switch (reason) { + case AppStateUpdateReason::CREATE_PROCESS: { + HILOGE("not supposed to reach here!"); + return false; + } + case AppStateUpdateReason::PROCESS_TERMINATED: { + HandleTerminateProcess(processInfo, bundleInfo, osAccountInfo); + break; + } + case AppStateUpdateReason::FOREGROUND: { + processInfo.SetPriority(RECLAIM_PRIORITY_FOREGROUND); + UpdateBundlePriority(bundleInfo); + break; + } + case AppStateUpdateReason::BACKGROUND: { + processInfo.SetPriority(RECLAIM_PRIORITY_BACKGROUND); + UpdateBundlePriority(bundleInfo); + break; + } + case AppStateUpdateReason::PROCESS_SUSPEND: { + processInfo.SetPriority(RECLAIM_PRIORITY_SUSPEND); + UpdateBundlePriority(bundleInfo); + break; + } + case AppStateUpdateReason::SUSPEND_DELAY_START: + processInfo.isSuspendDelay = true; + if (bundleInfo->priority_ > RECLAIM_PRIORITY_BG_SUSPEND_DELAY) { + processInfo.SetPriority(RECLAIM_PRIORITY_BG_SUSPEND_DELAY); + UpdateBundlePriority(bundleInfo); + } + break; + case AppStateUpdateReason::SUSPEND_DELAY_END: + processInfo.isSuspendDelay = false; + if (bundleInfo->priority_ == RECLAIM_PRIORITY_BG_SUSPEND_DELAY) { + processInfo.SetPriority(RECLAIM_PRIORITY_BACKGROUND); + UpdateBundlePriority(bundleInfo); + } + break; + case AppStateUpdateReason::BACKGROUND_RUNNING_START: + processInfo.isBackgroundRunning = true; + break; + case AppStateUpdateReason::BACKGROUND_RUNNING_END: + processInfo.isBackgroundRunning = false; + break; + case AppStateUpdateReason::EVENT_START: + processInfo.isEventStart = true; + break; + case AppStateUpdateReason::EVENT_END: + processInfo.isEventStart = false; + break; + case AppStateUpdateReason::DATA_ABILITY_START: + processInfo.isDataAbilityStart = true; + break; + case AppStateUpdateReason::DATA_ABILITY_END: + processInfo.isDataAbilityStart = false; + break; + default: + break; + } + // if priority of the process or the bundle is smaller than RECLAIM_PRIORITY_BACKGROUND, it need not to update + if (processInfo.isBackgroundRunning || processInfo.isEventStart || processInfo.isDataAbilityStart) { + if (bundleInfo->priority_ > RECLAIM_PRIORITY_BG_PERCEIVED) { + processInfo.SetPriority(RECLAIM_PRIORITY_BG_PERCEIVED); + UpdateBundlePriority(bundleInfo); + } + } else if (bundleInfo->priority_ == RECLAIM_PRIORITY_BG_PERCEIVED) { + processInfo.SetPriority(RECLAIM_PRIORITY_BACKGROUND); + UpdateBundlePriority(bundleInfo); + } + ret = ApplyReclaimPriority(bundleInfo, processInfo); + return ret; +} + +bool ReclaimPriorityManager::ApplyReclaimPriority(BundlePriorityInfo *bundleInfo, ProcessPriorityInfo &processInfo) +{ + return WriteOomScoreAdjToKernel(bundleInfo); +} + +bool ReclaimPriorityManager::CurrentOsAccountChanged(int curAccountId) +{ + if (!initialized_) { + HILOGE("has not been initialized_, skiped!"); + return false; + } + std::function currentOsAccountChangedInnerFunc = + std::bind(&ReclaimPriorityManager::CurrentOsAccountChangedInner, this, curAccountId); + return handler_->PostImmediateTask(currentOsAccountChangedInnerFunc); +} + +bool ReclaimPriorityManager::CurrentOsAccountChangedInner(int curAccountId) +{ + preOsAccountId_ = curOsAccountId_; + curOsAccountId_ = curAccountId; + for (auto i = osAccountsInfoMap_.begin(); i != osAccountsInfoMap_.end(); ++i) { + i->second.isCurOsAccount_ = (i->first == curOsAccountId_) ? true : false; + i->second.isPreOsAccount_ = (i->first == preOsAccountId_) ? true : false; + } + return UpdateAllReclaimPriority(AppStateUpdateReason::OS_ACCOUNT_HOT_SWITCH); +} + +bool ReclaimPriorityManager::UpdateAllReclaimPriority(AppStateUpdateReason reason) +{ + if (!initialized_) { + HILOGE("has not been initialized_, skiped!"); + return false; + } + switch (reason) { + case AppStateUpdateReason::OS_ACCOUNT_HOT_SWITCH: { + if (curOsAccountId_ == preOsAccountId_) { // now there is only one user + HILOGI("now there is only one user<%{public}d>, do nothing", curOsAccountId_); + } else { + OsAccountPriorityInfo* curUser = FindUserInfoById(curOsAccountId_); + curUser->PromoteAllBundlePriority(curUser->priorityShift_); + OsAccountPriorityInfo* preUser = FindUserInfoById(preOsAccountId_); + preUser->ReduceAllBundlePriority(curUser->priorityShift_); + } + break; + } + default: + break; + } + HILOGI("UpdateReclaimPriority for all apps"); + return true; +} +} // namespace Memory +} // namespace OHOS