1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "freeze_manager.h"
17 
18 #include "ability_manager_client.h"
19 #include "global.h"
20 #include "res_sched_client.h"
21 #include "res_type.h"
22 #include "system_ability_definition.h"
23 
24 namespace OHOS {
25 namespace MiscServices {
26 const std::string INPUT_METHOD_SERVICE_SA_NAME = "inputmethod_service";
27 constexpr const char *STOP_TASK_NAME = "ReportStop";
28 constexpr std::int32_t DELAY_TIME = 3000L;
29 std::shared_ptr<AppExecFwk::EventHandler> FreezeManager::eventHandler_ = nullptr;
IsIpcNeeded(RequestType type)30 bool FreezeManager::IsIpcNeeded(RequestType type)
31 {
32     // If ime is in use, no need to request hide.
33     std::lock_guard<std::mutex> lock(mutex_);
34     return !(type == RequestType::REQUEST_HIDE && !isImeInUse_);
35 }
36 
BeforeIpc(RequestType type)37 void FreezeManager::BeforeIpc(RequestType type)
38 {
39     {
40         std::lock_guard<std::mutex> lock(mutex_);
41         if (type == RequestType::START_INPUT || type == RequestType::REQUEST_SHOW) {
42             isImeInUse_ = true;
43         }
44         if (!isFrozen_) {
45             IMSA_HILOGD("not frozen already.");
46             return;
47         }
48         isFrozen_ = false;
49     }
50     ControlIme(false);
51 }
52 
AfterIpc(RequestType type,bool isSuccess)53 void FreezeManager::AfterIpc(RequestType type, bool isSuccess)
54 {
55     bool shouldFreeze = false;
56     {
57         std::lock_guard<std::mutex> lock(mutex_);
58         if (type == RequestType::START_INPUT || type == RequestType::REQUEST_SHOW) {
59             isImeInUse_ = isSuccess;
60         }
61         if (type == RequestType::REQUEST_HIDE && isImeInUse_) {
62             isImeInUse_ = !isSuccess;
63         }
64         if (type == RequestType::STOP_INPUT) {
65             isImeInUse_ = false;
66         }
67         if (isFrozen_ == !isImeInUse_) {
68             IMSA_HILOGD("frozen state already: %{public}d.", isFrozen_);
69             return;
70         }
71         isFrozen_ = !isImeInUse_;
72         shouldFreeze = isFrozen_;
73     }
74     ControlIme(shouldFreeze);
75 }
76 
ControlIme(bool shouldFreeze)77 void FreezeManager::ControlIme(bool shouldFreeze)
78 {
79     if (eventHandler_ == nullptr) {
80         IMSA_HILOGW("eventHandler_ is nullptr.");
81         ReportRss(shouldFreeze, pid_);
82         return;
83     }
84     if (shouldFreeze) {
85         // Delay the FREEZE report by 3s.
86         eventHandler_->PostTask(
87             [shouldFreeze, pid = pid_]() { ReportRss(shouldFreeze, pid); }, STOP_TASK_NAME, DELAY_TIME);
88     } else {
89         // Cancel the unexecuted FREEZE task.
90         eventHandler_->RemoveTask(STOP_TASK_NAME);
91         ReportRss(shouldFreeze, pid_);
92     }
93 }
94 
ReportRss(bool shouldFreeze,pid_t pid)95 void FreezeManager::ReportRss(bool shouldFreeze, pid_t pid)
96 {
97     auto type = ResourceSchedule::ResType::RES_TYPE_SA_CONTROL_APP_EVENT;
98     auto status = shouldFreeze ? ResourceSchedule::ResType::SaControlAppStatus::SA_STOP_APP
99                                : ResourceSchedule::ResType::SaControlAppStatus::SA_START_APP;
100     std::unordered_map<std::string, std::string> payload = {
101         { "saId", std::to_string(INPUT_METHOD_SYSTEM_ABILITY_ID) },
102         { "saName", INPUT_METHOD_SERVICE_SA_NAME },
103         { "extensionType", std::to_string(static_cast<int32_t>(AppExecFwk::ExtensionAbilityType::INPUTMETHOD)) },
104         { "pid", std::to_string(pid) } };
105     IMSA_HILOGD("report RSS should freeze: %{public}d.", shouldFreeze);
106     ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, status, payload);
107 }
108 
SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> & eventHandler)109 void FreezeManager::SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &eventHandler)
110 {
111     eventHandler_ = eventHandler;
112 }
113 } // namespace MiscServices
114 } // namespace OHOS