• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "shutdown_dialog.h"
17 
18 #include <atomic>
19 #include <fstream>
20 #include <memory>
21 #include <set>
22 #include <string_ex.h>
23 
24 #include <ability_manager_client.h>
25 #ifdef HAS_MULTIMODALINPUT_INPUT_PART
26 #include <input_manager.h>
27 #include <key_event.h>
28 #include <key_option.h>
29 #endif
30 #include <message_parcel.h>
31 
32 #include "config_policy_utils.h"
33 #include "json/reader.h"
34 #include "json/value.h"
35 #include "power_log.h"
36 #include "power_mgr_service.h"
37 #include "power_vibrator.h"
38 
39 using namespace OHOS::MMI;
40 using namespace OHOS::AAFwk;
41 
42 namespace OHOS {
43 namespace PowerMgr {
44 namespace {
45 static constexpr int32_t LONG_PRESS_DELAY_MS = 3000;
46 static constexpr int32_t INVALID_USERID = -1;
47 static constexpr int32_t MESSAGE_PARCEL_KEY_SIZE = 3;
48 static constexpr int32_t INIT_LONG_PRESS_RETRY = 3;
49 static constexpr uint32_t RETRY_TIME = 1000;
50 std::atomic_bool g_isDialogShow = false;
51 std::atomic_bool g_longPressShow = false;
52 int32_t g_retryCount = 1;
53 sptr<IRemoteObject> g_remoteObject = nullptr;
54 const std::string DIALOG_CONFIG_PATH = "etc/systemui/poweroff_config.json";
55 } // namespace
56 
57 std::string ShutdownDialog::bundleName_ = "com.ohos.powerdialog";
58 std::string ShutdownDialog::abilityName_ = "PowerUiExtensionAbility";
59 std::string ShutdownDialog::uiExtensionType_ = "sysDialog/power";
60 
ShutdownDialog()61 ShutdownDialog::ShutdownDialog() : dialogConnectionCallback_(new DialogAbilityConnection()) {}
62 
~ShutdownDialog()63 ShutdownDialog::~ShutdownDialog()
64 {
65     dialogConnectionCallback_ = nullptr;
66 }
67 
KeyMonitorInit()68 void ShutdownDialog::KeyMonitorInit()
69 {
70 #ifdef HAS_MULTIMODALINPUT_INPUT_PART
71     POWER_HILOGD(FEATURE_SHUTDOWN, "Initialize the long press powerkey");
72     std::shared_ptr<KeyOption> keyOption = std::make_shared<KeyOption>();
73     std::set<int32_t> preKeys;
74 
75     keyOption->SetPreKeys(preKeys);
76     keyOption->SetFinalKey(KeyEvent::KEYCODE_POWER);
77     keyOption->SetFinalKeyDown(true);
78     keyOption->SetFinalKeyDownDuration(LONG_PRESS_DELAY_MS);
79     longPressId_ =
80         InputManager::GetInstance()->SubscribeKeyEvent(keyOption, [this](std::shared_ptr<KeyEvent> keyEvent) {
81             POWER_HILOGI(FEATURE_SHUTDOWN, "Receive long press powerkey");
82             ConnectSystemUi();
83             StartVibrator();
84         });
85     if (longPressId_ < ERR_OK) {
86         if (g_retryCount <= INIT_LONG_PRESS_RETRY) {
87             POWER_HILOGI(FEATURE_SHUTDOWN, "SubscribeKey long press failed errcode = %{public}d, Try again in 1 second",
88                 longPressId_);
89             FFRTTask task = [this] {
90                 KeyMonitorInit();
91             };
92             FFRTUtils::SubmitDelayTask(task, RETRY_TIME, queue_);
93             g_retryCount++;
94         }
95         return;
96     }
97     POWER_HILOGI(FEATURE_SHUTDOWN, "SubscribeKey long press success");
98 #endif
99 }
100 
KeyMonitorCancel()101 void ShutdownDialog::KeyMonitorCancel()
102 {
103 #ifdef HAS_MULTIMODALINPUT_INPUT_PART
104     InputManager* inputManager = InputManager::GetInstance();
105     if (inputManager == nullptr) {
106         POWER_HILOGW(FEATURE_SHUTDOWN, "InputManager is null");
107         return;
108     }
109     if (longPressId_ >= ERR_OK) {
110         inputManager->UnsubscribeKeyEvent(longPressId_);
111     }
112     longPressId_ = 0;
113 #endif
114 }
115 
ConnectSystemUi()116 bool ShutdownDialog::ConnectSystemUi()
117 {
118     if (g_isDialogShow) {
119         AppExecFwk::ElementName element;
120         dialogConnectionCallback_->OnAbilityConnectDone(element, g_remoteObject, INVALID_USERID);
121         POWER_HILOGW(FEATURE_SHUTDOWN, "power dialog has been show");
122         return true;
123     }
124     auto ams = AbilityManagerClient::GetInstance();
125     if (ams == nullptr) {
126         POWER_HILOGW(FEATURE_SHUTDOWN, "AbilityManagerClient is nullptr");
127         return false;
128     }
129 
130     Want want;
131     want.SetElementName("com.ohos.systemui", "com.ohos.systemui.dialog");
132     ErrCode result = ams->ConnectAbility(want, dialogConnectionCallback_, INVALID_USERID);
133     if (result != ERR_OK) {
134         POWER_HILOGW(FEATURE_SHUTDOWN, "ConnectAbility systemui dialog failed, result = %{public}d", result);
135         return false;
136     }
137     POWER_HILOGI(FEATURE_SHUTDOWN, "ConnectAbility systemui dialog success.");
138     return true;
139 }
140 
IsLongPress() const141 bool ShutdownDialog::IsLongPress() const
142 {
143     return g_longPressShow;
144 }
145 
ResetLongPressFlag()146 void ShutdownDialog::ResetLongPressFlag()
147 {
148     g_longPressShow = false;
149 }
150 
LoadDialogConfig()151 void ShutdownDialog::LoadDialogConfig()
152 {
153     char buf[MAX_PATH_LEN];
154     char* configPath = GetOneCfgFile(DIALOG_CONFIG_PATH.c_str(), buf, MAX_PATH_LEN);
155     if (configPath == nullptr || *configPath == '\0') {
156         POWER_HILOGI(COMP_UTILS, "do not find shutdown off json");
157         return;
158     }
159     std::ifstream inputStream(configPath, std::ios::in | std::ios::binary);
160     std::string contentStr(std::istreambuf_iterator<char> {inputStream}, std::istreambuf_iterator<char> {});
161     Json::Reader reader;
162     Json::Value root;
163     if (!reader.parse(contentStr.data(), contentStr.data() + contentStr.size(), root)) {
164         POWER_HILOGE(COMP_UTILS, "json parse error");
165         return;
166     }
167 
168     if (!root["bundleName"].isString() ||
169         !root["abilityName"].isString() || !root["uiExtensionType"].isString()) {
170             return;
171     }
172 
173     bundleName_ = root["bundleName"].asString();
174     abilityName_ = root["abilityName"].asString();
175     uiExtensionType_ = root["uiExtensionType"].asString();
176 }
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)177 void ShutdownDialog::DialogAbilityConnection::OnAbilityConnectDone(
178     const AppExecFwk::ElementName& element, const sptr<IRemoteObject>& remoteObject, int resultCode)
179 {
180     POWER_HILOGI(FEATURE_SHUTDOWN, "OnAbilityConnectDone");
181     std::lock_guard lock(mutex_);
182     if (remoteObject == nullptr) {
183         POWER_HILOGW(FEATURE_SHUTDOWN, "remoteObject is nullptr");
184         return;
185     }
186     if (g_remoteObject == nullptr) {
187         g_remoteObject = remoteObject;
188     }
189     FFRTUtils::SubmitTask([remoteObject] {
190         MessageParcel data;
191         MessageParcel reply;
192         MessageOption option;
193         data.WriteInt32(MESSAGE_PARCEL_KEY_SIZE);
194         data.WriteString16(u"bundleName");
195         data.WriteString16(Str8ToStr16(ShutdownDialog::GetBundleName()));
196         data.WriteString16(u"abilityName");
197         data.WriteString16(Str8ToStr16(ShutdownDialog::GetAbilityName()));
198         data.WriteString16(u"parameters");
199         std::string midStr = "\"";
200         // sysDialogZOrder = 2 displayed on the lock screen
201         std::string paramStr = "{\"ability.want.params.uiExtensionType\":"+ midStr +
202             ShutdownDialog::GetUiExtensionType() + midStr + ",\"sysDialogZOrder\":2}";
203         data.WriteString16(Str8ToStr16(paramStr));
204         POWER_HILOGI(FEATURE_SHUTDOWN, "show power dialog is begin");
205         const uint32_t cmdCode = 1;
206         int32_t ret = remoteObject->SendRequest(cmdCode, data, reply, option);
207         if (ret != ERR_OK) {
208             POWER_HILOGW(FEATURE_SHUTDOWN, "show power dialog is failed: %{public}d", ret);
209             return;
210         }
211         g_isDialogShow = true;
212         g_longPressShow = true;
213         POWER_HILOGI(FEATURE_SHUTDOWN, "show power dialog is success");
214         auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
215         if (pms == nullptr) {
216             return;
217         }
218         pms->RefreshActivity(
219             static_cast<int64_t>(time(nullptr)), UserActivityType::USER_ACTIVITY_TYPE_ATTENTION, false);
220     });
221 }
222 
StartVibrator()223 void ShutdownDialog::StartVibrator()
224 {
225     std::shared_ptr<PowerVibrator> vibrator = PowerVibrator::GetInstance();
226     std::string scene = "shutdown_diag";
227     vibrator->StartVibrator(scene);
228 }
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)229 void ShutdownDialog::DialogAbilityConnection::OnAbilityDisconnectDone(
230     const AppExecFwk::ElementName& element, int resultCode)
231 {
232     POWER_HILOGD(FEATURE_SHUTDOWN, "OnAbilityDisconnectDone");
233     std::lock_guard lock(mutex_);
234     g_isDialogShow = false;
235     g_longPressShow = false;
236     g_remoteObject = nullptr;
237 }
238 } // namespace PowerMgr
239 } // namespace OHOS
240