• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "starting_window.h"
17 #include <ability_manager_client.h>
18 #include <common/rs_common_def.h>
19 #include <display_manager_service_inner.h>
20 #include <hitrace_meter.h>
21 #include <transaction/rs_transaction.h>
22 
23 #include "display_group_info.h"
24 #include "remote_animation.h"
25 #include "window_helper.h"
26 #include "window_inner_manager.h"
27 #include "window_manager_hilog.h"
28 #include "window_manager_service.h"
29 #include "window_manager_service_utils.h"
30 #include "window_system_effect.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 namespace {
35     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "StartingWindow"};
36 }
37 
38 const std::map<OHOS::AppExecFwk::DisplayOrientation, Orientation> ABILITY_TO_WMS_ORIENTATION_MAP {
39     {OHOS::AppExecFwk::DisplayOrientation::UNSPECIFIED, Orientation::UNSPECIFIED},
40     {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE, Orientation::HORIZONTAL},
41     {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT, Orientation::VERTICAL},
42     {OHOS::AppExecFwk::DisplayOrientation::FOLLOWRECENT, Orientation::LOCKED},
43     {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE_INVERTED, Orientation::REVERSE_HORIZONTAL},
44     {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT_INVERTED, Orientation::REVERSE_VERTICAL},
45     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION, Orientation::SENSOR},
46     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE, Orientation::SENSOR_HORIZONTAL},
47     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT, Orientation::SENSOR_VERTICAL},
48     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_RESTRICTED, Orientation::AUTO_ROTATION_RESTRICTED},
49     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED,
50         Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED},
51     {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT_RESTRICTED,
52         Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED},
53     {OHOS::AppExecFwk::DisplayOrientation::LOCKED, Orientation::LOCKED},
54 };
55 
56 std::recursive_mutex StartingWindow::mutex_;
57 WindowMode StartingWindow::defaultMode_ = WindowMode::WINDOW_MODE_FULLSCREEN;
58 bool StartingWindow::transAnimateEnable_ = true;
59 AnimationConfig StartingWindow::animationConfig_;
60 
CreateWindowNode(const sptr<WindowTransitionInfo> & info,uint32_t winId)61 sptr<WindowNode> StartingWindow::CreateWindowNode(const sptr<WindowTransitionInfo>& info, uint32_t winId)
62 {
63     sptr<WindowProperty> property = new(std::nothrow) WindowProperty();
64     if (property == nullptr || info == nullptr) {
65         return nullptr;
66     }
67 
68     property->SetRequestRect(info->GetWindowRect());
69     if (WindowHelper::IsValidWindowMode(info->GetWindowMode())) {
70         property->SetWindowMode(info->GetWindowMode());
71     } else {
72         property->SetWindowMode(defaultMode_);
73     }
74 
75     AppExecFwk::DisplayOrientation displayOrientation = info->GetOrientation();
76     if (ABILITY_TO_WMS_ORIENTATION_MAP.count(displayOrientation) == 0) {
77         WLOGFE("id:%{public}u Do not support this Orientation type", winId);
78         return nullptr;
79     }
80     Orientation orientation = ABILITY_TO_WMS_ORIENTATION_MAP.at(displayOrientation);
81     if (orientation < Orientation::BEGIN || orientation > Orientation::END) {
82         WLOGFE("Set orientation from ability failed");
83         return nullptr;
84     }
85     property->SetRequestedOrientation(orientation);
86 
87     property->SetDisplayId(info->GetDisplayId());
88     property->SetWindowType(info->GetWindowType());
89 
90     ChangePropertyByApiVersion(info, orientation, property);
91     property->SetApiCompatibleVersion(info->GetApiCompatibleVersion());
92     if (info->GetShowFlagWhenLocked()) {
93         if (property->GetApiCompatibleVersion() < 9 || info->isSystemCalling_) { // 9: api version.
94             property->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED);
95         } else {
96             WLOGFW("Only API 9- or system calling support showing when locked.");
97         }
98     }
99     property->SetWindowId(winId);
100     sptr<WindowNode> node = new(std::nothrow) WindowNode(property);
101     if (node == nullptr) {
102         return nullptr;
103     }
104     // test
105     node->stateMachine_.SetWindowId(winId);
106     node->abilityToken_ = info->GetAbilityToken();
107     node->SetWindowSizeLimits(info->GetWindowSizeLimits());
108     node->abilityInfo_.missionId_ = info->GetMissionId();
109     node->abilityInfo_.bundleName_ = info->GetBundleName();
110     node->abilityInfo_.abilityName_ = info->GetAbilityName();
111     uint32_t modeSupportInfo = WindowHelper::ConvertSupportModesToSupportInfo(info->GetWindowSupportModes());
112     node->SetModeSupportInfo(modeSupportInfo);
113 
114     if (CreateLeashAndStartingSurfaceNode(node) != WMError::WM_OK) {
115         return nullptr;
116     }
117     node->stateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED);
118     return node;
119 }
120 
ChangePropertyByApiVersion(const sptr<WindowTransitionInfo> & info,const Orientation orientation,sptr<WindowProperty> & property)121 void StartingWindow::ChangePropertyByApiVersion(const sptr<WindowTransitionInfo>& info,
122     const Orientation orientation, sptr<WindowProperty>& property)
123 {
124     // 10 ArkUI new framework support after API10
125     if (info->GetApiCompatibleVersion() < 10) {
126         auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(info->GetDisplayId());
127         if (!(displayInfo && WmsUtils::IsExpectedRotatableWindow(orientation,
128             displayInfo->GetDisplayOrientation(), property->GetWindowMode(), property->GetWindowFlags(), false))) {
129             property->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID);
130         }
131     } else {
132         if (WindowHelper::IsMainWindow(property->GetWindowType())) {
133             SystemBarProperty statusSystemBarProperty(true, 0x00FFFFFF, 0xFF000000);
134             SystemBarProperty navigationSystemBarProperty(true, 0x00FFFFFF, 0xFF000000);
135             property->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusSystemBarProperty);
136             property->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, navigationSystemBarProperty);
137         }
138     }
139 }
140 
CreateLeashAndStartingSurfaceNode(sptr<WindowNode> & node)141 WMError StartingWindow::CreateLeashAndStartingSurfaceNode(sptr<WindowNode>& node)
142 {
143     struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
144     rsSurfaceNodeConfig.SurfaceNodeName = "leashWindow" + std::to_string(node->GetWindowId());
145     node->leashWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::LEASH_WINDOW_NODE);
146     if (node->leashWinSurfaceNode_ == nullptr) {
147         WLOGFE("create leashWinSurfaceNode failed");
148         return WMError::WM_ERROR_NULLPTR;
149     }
150 
151     rsSurfaceNodeConfig.SurfaceNodeName = "startingWindow" + std::to_string(node->GetWindowId());
152     node->startingWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::STARTING_WINDOW_NODE);
153     if (node->startingWinSurfaceNode_ == nullptr) {
154         WLOGFE("create startingWinSurfaceNode failed");
155         node->leashWinSurfaceNode_ = nullptr;
156         return WMError::WM_ERROR_NULLPTR;
157     }
158     WLOGI("Create leashWinSurfaceNode and startingWinSurfaceNode success with id:%{public}u!", node->GetWindowId());
159     return WMError::WM_OK;
160 }
161 
DrawStartingWindow(sptr<WindowNode> & node,std::shared_ptr<Media::PixelMap> pixelMap,uint32_t bkgColor,bool isColdStart)162 WMError StartingWindow::DrawStartingWindow(sptr<WindowNode>& node,
163     std::shared_ptr<Media::PixelMap> pixelMap, uint32_t bkgColor, bool isColdStart)
164 {
165     if (node == nullptr) {
166         return WMError::WM_ERROR_NULLPTR;
167     }
168     // using snapshot to support hot start since node destroy when hide
169     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DrawStartingWindow(%u)", node->GetWindowId());
170     Rect rect = node->GetWindowRect();
171     if (RemoteAnimation::CheckRemoteAnimationEnabled(node->GetDisplayId()) && node->leashWinSurfaceNode_) {
172         // hides this node until RSProxyNode send valid context alpha/matrix
173         node->leashWinSurfaceNode_->ResetContextAlpha();
174     }
175     if (!isColdStart) {
176         return WMError::WM_OK;
177     }
178     if (node->startingWinSurfaceNode_ == nullptr) {
179         WLOGFE("no starting Window SurfaceNode!");
180         return WMError::WM_ERROR_NULLPTR;
181     }
182     // set window effect
183     WindowSystemEffect::SetWindowEffect(node);
184     if (pixelMap == nullptr) {
185         SurfaceDraw::DrawColor(node->startingWinSurfaceNode_, rect.width_, rect.height_, bkgColor);
186         return WMError::WM_OK;
187     }
188 
189     WLOGFD("draw background in sperate");
190     SurfaceDraw::DrawImageRect(node->startingWinSurfaceNode_, rect, pixelMap, bkgColor);
191     return WMError::WM_OK;
192 }
193 
SetStartingWindowAnimation(wptr<WindowNode> weak)194 WMError StartingWindow::SetStartingWindowAnimation(wptr<WindowNode> weak)
195 {
196     auto weakNode = weak.promote();
197     if (weakNode == nullptr || !weakNode->startingWinSurfaceNode_) {
198         WLOGFE("windowNode or startingWinSurfaceNode_ is nullptr");
199         return WMError::WM_ERROR_NULLPTR;
200     }
201     StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
202         "StartingWindowAnimate(%u)", weakNode->GetWindowId());
203     weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityStart_);
204     auto execute = [weak]() {
205         auto weakNode = weak.promote();
206         if (weakNode == nullptr) {
207             WLOGFE("windowNode is nullptr");
208             return;
209         }
210         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:ExecuteAnimate(%d)",
211             weakNode->GetWindowId());
212         weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityEnd_);
213     };
214 
215     auto finish = [weak]() {
216         auto weakNode = weak.promote();
217         if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
218             WLOGFE("windowNode or leashWinSurfaceNode_ is nullptr");
219             return;
220         }
221         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:AnimateFinish(%d)",
222             weakNode->GetWindowId());
223         WLOGFI("StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId());
224         weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
225         weakNode->startingWinSurfaceNode_ = nullptr;
226         RSTransaction::FlushImplicitTransaction();
227         FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::START_WINDOW_ANIMATION),
228             "StartingWindowAnimate(%u)", weakNode->GetWindowId());
229     };
230     RSNode::Animate(animationConfig_.startWinAnimationConfig_.timingProtocol_,
231         animationConfig_.startWinAnimationConfig_.timingCurve_, execute, finish);
232     RSTransaction::FlushImplicitTransaction();
233     FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
234     return WMError::WM_OK;
235 }
236 
HandleClientWindowCreate(sptr<WindowNode> & node,sptr<IWindow> & window,uint32_t & windowId,const std::shared_ptr<RSSurfaceNode> & surfaceNode,sptr<WindowProperty> & property,int32_t pid,int32_t uid)237 void StartingWindow::HandleClientWindowCreate(sptr<WindowNode>& node, sptr<IWindow>& window,
238     uint32_t& windowId, const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowProperty>& property,
239     int32_t pid, int32_t uid)
240 {
241     if (node == nullptr) {
242         WLOGFE("node is nullptr");
243         return;
244     }
245     node->surfaceNode_ = surfaceNode;
246     node->SetWindowToken(window);
247     node->SetCallingPid(pid);
248     node->SetCallingUid(uid);
249     windowId = node->GetWindowId();
250     // test
251     node->stateMachine_.SetWindowId(windowId);
252     node->stateMachine_.SetWindowType(property->GetWindowType());
253     WLOGI("after set Id:%{public}u, requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]",
254         node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_,
255         node->GetRequestRect().width_, node->GetRequestRect().height_);
256     // Register FirstFrame Callback to rs, replace startwin
257     wptr<WindowNode> weak = node;
258     auto firstFrameCompleteCallback = [weak]() {
259         auto task = [weak]() {
260             FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::STARTING_WINDOW),
261                 "wms:async:ShowStartingWindow");
262             auto weakNode = weak.promote();
263             if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) {
264                 WLOGFE("windowNode or leashWinSurfaceNode_ is nullptr");
265                 return;
266             }
267             WLOGI("StartingWindow::FirstFrameCallback come, id: %{public}u", weakNode->GetWindowId());
268             if (transAnimateEnable_) {
269                 SetStartingWindowAnimation(weakNode);
270             } else {
271                 weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_);
272                 weakNode->startingWinSurfaceNode_ = nullptr;
273                 RSTransaction::FlushImplicitTransaction();
274                 WLOGFI("StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId());
275             }
276             WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode);
277             weakNode->firstFrameAvailable_ = true;
278         };
279         WindowManagerService::GetInstance().PostAsyncTask(task, "firstFrameCompleteCallback");
280     };
281     node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback);
282     RSTransaction::FlushImplicitTransaction();
283 }
284 
ReleaseStartWinSurfaceNode(sptr<WindowNode> & node)285 void StartingWindow::ReleaseStartWinSurfaceNode(sptr<WindowNode>& node)
286 {
287     std::lock_guard<std::recursive_mutex> lock(mutex_);
288     if (!node->leashWinSurfaceNode_) {
289         WLOGI("cannot release leashwindow since leash is null, id:%{public}u", node->GetWindowId());
290         return;
291     }
292     node->leashWinSurfaceNode_->RemoveChild(node->startingWinSurfaceNode_);
293     node->leashWinSurfaceNode_->RemoveChild(node->closeWinSurfaceNode_);
294     node->leashWinSurfaceNode_->RemoveChild(node->surfaceNode_);
295     node->leashWinSurfaceNode_ = nullptr;
296     node->startingWinSurfaceNode_ = nullptr;
297     node->closeWinSurfaceNode_ = nullptr;
298     WLOGI("Release startwindow surfaceNode end id: %{public}u, [leashWinSurface]: use_count: %{public}ld, \
299         [startWinSurface]: use_count: %{public}ld ", node->GetWindowId(),
300         node->leashWinSurfaceNode_.use_count(), node->startingWinSurfaceNode_.use_count());
301     RSTransaction::FlushImplicitTransaction();
302 }
303 
IsWindowFollowParent(WindowType type)304 bool StartingWindow::IsWindowFollowParent(WindowType type)
305 {
306     auto isPhone = system::GetParameter("const.product.devicetype", "unknown") == "phone";
307     if (!isPhone) {
308         return false;
309     }
310     return WindowHelper::IsWindowFollowParent(type);
311 }
312 
AddNodeOnRSTree(sptr<WindowNode> & node,bool isMultiDisplay)313 void StartingWindow::AddNodeOnRSTree(sptr<WindowNode>& node, bool isMultiDisplay)
314 {
315     auto updateRSTreeFunc = [&]() {
316         auto& dms = DisplayManagerServiceInner::GetInstance();
317         DisplayId displayId = node->GetDisplayId();
318         if (!node->surfaceNode_) { // cold start
319             if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
320                 WLOGFE("window id:%{public}d type: %{public}u is not Main Window!",
321                     node->GetWindowId(), static_cast<uint32_t>(node->GetWindowType()));
322             }
323             dms.UpdateRSTree(displayId, displayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
324             node->leashWinSurfaceNode_->AddChild(node->startingWinSurfaceNode_, -1);
325             WLOGFD("Add startingWinSurfaceNode_ to leashWinSurfaceNode_ end during cold start");
326         } else { // hot start
327             const auto& displayIdVec = node->GetShowingDisplays();
328             for (auto& shownDisplayId : displayIdVec) {
329                 if (node->leashWinSurfaceNode_) { // to app
330                     dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->leashWinSurfaceNode_, true, isMultiDisplay);
331                 } else { // to launcher
332                     dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->surfaceNode_, true, isMultiDisplay);
333                 }
334                 for (auto& child : node->children_) {
335                     if (IsWindowFollowParent(child->GetWindowType())) {
336                         continue;
337                     }
338                     if (child->currentVisibility_) {
339                         dms.UpdateRSTree(shownDisplayId, shownDisplayId, child->surfaceNode_, true, isMultiDisplay);
340                     }
341                 }
342             }
343             WLOGFD("Update RsTree with hot start");
344         }
345     };
346     wptr<WindowNode> weakNode = node;
347     auto finishCallBack = [weakNode]() {
348         auto weak = weakNode.promote();
349         if (weak == nullptr) {
350             return;
351         }
352         auto winRect = weak->GetWindowRect();
353         WLOGI("before setBounds windowRect: %{public}d, %{public}d, %{public}d, %{public}d",
354             winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
355         if (weak->leashWinSurfaceNode_) {
356             weak->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
357             weak->leashWinSurfaceNode_->SetAnimationFinished();
358         }
359         RSTransaction::FlushImplicitTransaction();
360     };
361     if (!RemoteAnimation::CheckAnimationController()) {
362         RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
363             animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_,
364             updateRSTreeFunc, finishCallBack);
365     } else {
366         // add or remove window without animation
367         updateRSTreeFunc();
368     }
369 }
370 
SetDefaultWindowMode(WindowMode defaultMode)371 void StartingWindow::SetDefaultWindowMode(WindowMode defaultMode)
372 {
373     defaultMode_ = defaultMode;
374 }
375 
SetAnimationConfig(AnimationConfig config)376 void StartingWindow::SetAnimationConfig(AnimationConfig config)
377 {
378     animationConfig_ = config;
379 }
380 } // Rosen
381 } // OHOS
382