1/*
2 * Copyright (c) 2021-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 "abstract_display.h"
17
18#include "abstract_screen_controller.h"
19#include "display_manager_config.h"
20#include "display_manager_service.h"
21#include "window_manager_hilog.h"
22
23namespace OHOS::Rosen {
24namespace {
25constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractDisplay"};
26constexpr int32_t PAD_SCREEN_WIDTH = 2560;
27constexpr int32_t PHONE_SCREEN_WIDTH = 2160;
28constexpr float INCH_2_MM = 25.4f;
29}
30
31AbstractDisplay::AbstractDisplay(DisplayId id, sptr<SupportedScreenModes>& info, sptr<AbstractScreen>& absScreen)
32    : id_(id)
33{
34    if (info == nullptr || absScreen == nullptr) {
35        WLOGFE("info or absScreen is nullptr");
36        return;
37    }
38    screenId_ = absScreen->dmsId_;
39    screenGroupId_ = absScreen->groupDmsId_;
40    width_ = static_cast<int32_t>(info->width_);
41    height_ = static_cast<int32_t>(info->height_);
42    refreshRate_ = info->refreshRate_;
43    orientation_ = absScreen->orientation_;
44    name_ = absScreen->GetScreenName();
45    static_cast<void>(RequestRotation(absScreen->rotation_));
46    if (width_ > height_) {
47        displayOrientation_ = DisplayOrientation::LANDSCAPE;
48    } else {
49        displayOrientation_ = DisplayOrientation::PORTRAIT;
50    }
51    if (info->width_ < info->height_) {
52        isDefaultVertical_ = true;
53    } else {
54        isDefaultVertical_ = false;
55    }
56
57    CalculateXYDpi(absScreen->GetPhyWidth(), absScreen->GetPhyHeight());
58    auto numbersConfig = DisplayManagerConfig::GetIntNumbersConfig();
59    if (numbersConfig.count("dpi") != 0) {
60        uint32_t densityDpi = static_cast<uint32_t>(numbersConfig["dpi"][0]);
61        if (densityDpi >= DOT_PER_INCH_MINIMUM_VALUE && densityDpi <= DOT_PER_INCH_MAXIMUM_VALUE) {
62            virtualPixelRatio_ = static_cast<float>(densityDpi) / BASELINE_DENSITY;
63            absScreen->SetVirtualPixelRatio(virtualPixelRatio_);
64            return;
65        }
66    }
67    if ((info->width_ >= PHONE_SCREEN_WIDTH) || (info->height_ >= PHONE_SCREEN_WIDTH)) {
68        if ((info->width_ == PAD_SCREEN_WIDTH) || (info->height_ == PAD_SCREEN_WIDTH)) {
69            virtualPixelRatio_ = 2.0f; // Pad is 2.0
70        } else {
71            virtualPixelRatio_ = 3.0f; // Phone is 3.0
72        }
73    } else {
74        virtualPixelRatio_ = 1.0f; // Other is 1.0
75    }
76    absScreen->SetVirtualPixelRatio(virtualPixelRatio_);
77}
78
79void AbstractDisplay::CalculateXYDpi(uint32_t phyWidth, uint32_t phyHeight)
80{
81    if (phyWidth == 0 || phyHeight == 0) {
82        return;
83    }
84
85    phyWidth_ = phyWidth;
86    phyHeight_ = phyHeight;
87    xDpi_ = width_ * INCH_2_MM / phyWidth_;
88    yDpi_ = height_ * INCH_2_MM / phyHeight_;
89}
90
91DisplayId AbstractDisplay::GetId() const
92{
93    return id_;
94}
95
96int32_t AbstractDisplay::GetWidth() const
97{
98    return width_;
99}
100
101int32_t AbstractDisplay::GetHeight() const
102{
103    return height_;
104}
105
106uint32_t AbstractDisplay::GetRefreshRate() const
107{
108    return refreshRate_;
109}
110
111float AbstractDisplay::GetVirtualPixelRatio() const
112{
113    return virtualPixelRatio_;
114}
115
116int32_t AbstractDisplay::GetOffsetX() const
117{
118    return offsetX_;
119}
120
121int32_t AbstractDisplay::GetOffsetY() const
122{
123    return offsetY_;
124}
125
126void AbstractDisplay::SetOffsetX(int32_t offsetX)
127{
128    offsetX_ = offsetX;
129}
130
131void AbstractDisplay::SetOffsetY(int32_t offsetY)
132{
133    offsetY_ = offsetY;
134}
135
136void AbstractDisplay::SetWidth(int32_t width)
137{
138    width_ = width;
139    UpdateXDpi();
140}
141
142void AbstractDisplay::SetHeight(int32_t height)
143{
144    height_ = height;
145    UpdateYDpi();
146}
147
148void AbstractDisplay::UpdateXDpi()
149{
150    if (phyWidth_ != UINT32_MAX) {
151        xDpi_ = width_ * INCH_2_MM / phyWidth_;
152    }
153}
154
155void AbstractDisplay::UpdateYDpi()
156{
157    if (phyHeight_ != UINT32_MAX) {
158        yDpi_ = height_ * INCH_2_MM / phyHeight_;
159    }
160}
161
162void AbstractDisplay::SetOffset(int32_t offsetX, int32_t offsetY)
163{
164    offsetX_ = offsetX;
165    offsetY_ = offsetY;
166}
167
168void AbstractDisplay::SetRefreshRate(uint32_t refreshRate)
169{
170    refreshRate_ = refreshRate;
171}
172
173void AbstractDisplay::SetVirtualPixelRatio(float virtualPixelRatio)
174{
175    virtualPixelRatio_ = virtualPixelRatio;
176}
177
178void AbstractDisplay::SetId(DisplayId id)
179{
180    id_ = id;
181}
182
183void AbstractDisplay::SetOrientation(Orientation orientation)
184{
185    orientation_ = orientation;
186}
187
188void AbstractDisplay::SetDisplayOrientation(DisplayOrientation displayOrientation)
189{
190    displayOrientation_ = displayOrientation;
191}
192
193bool AbstractDisplay::RequestRotation(Rotation rotation)
194{
195    WLOGD("request rotation from %{public}u to %{public}u, display %{public}" PRIu64"", rotation_, rotation, id_);
196    if (rotation_ == rotation) {
197        WLOGFE("rotation not change %{public}u", rotation);
198        return false;
199    }
200    if (IsVertical(rotation) != IsVertical(rotation_)) {
201        std::swap(width_, height_);
202    }
203    rotation_ = rotation;
204    return true;
205}
206
207Rotation AbstractDisplay::GetRotation() const
208{
209    return rotation_;
210}
211
212Orientation AbstractDisplay::GetOrientation() const
213{
214    return orientation_;
215}
216
217DisplayOrientation AbstractDisplay::GetDisplayOrientation() const
218{
219    return displayOrientation_;
220}
221
222void AbstractDisplay::SetFreezeFlag(FreezeFlag freezeFlag)
223{
224    freezeFlag_ = freezeFlag;
225}
226
227FreezeFlag AbstractDisplay::GetFreezeFlag() const
228{
229    return freezeFlag_;
230}
231
232bool AbstractDisplay::BindAbstractScreen(sptr<AbstractScreen> abstractScreen)
233{
234    if (abstractScreen == nullptr) {
235        WLOGE("display bind screen error, cannot get screen. display:%{public}" PRIu64"", id_);
236        return false;
237    }
238    ScreenId dmsScreenId = abstractScreen->dmsId_;
239    sptr<SupportedScreenModes> info = abstractScreen->GetActiveScreenMode();
240    if (info == nullptr) {
241        WLOGE("display bind screen error, cannot get info. display:%{public}" PRIu64", screen:%{public}" PRIu64"",
242            id_, dmsScreenId);
243        return false;
244    }
245
246    Point point = abstractScreen->GetGroup()->GetChildPosition(dmsScreenId);
247    offsetX_ = point.posX_;
248    offsetY_ = point.posY_;
249    width_ = static_cast<int32_t>(info->width_);
250    height_ = static_cast<int32_t>(info->height_);
251    refreshRate_ = info->refreshRate_;
252    screenId_ = dmsScreenId;
253    WLOGD("display bind to screen. display:%{public}" PRIu64", screen:%{public}" PRIu64"", id_, dmsScreenId);
254    return true;
255}
256
257ScreenId AbstractDisplay::GetAbstractScreenId() const
258{
259    return screenId_;
260}
261
262ScreenId AbstractDisplay::GetAbstractScreenGroupId() const
263{
264    return screenGroupId_;
265}
266
267sptr<DisplayInfo> AbstractDisplay::ConvertToDisplayInfo() const
268{
269    sptr<DisplayInfo> displayInfo = new(std::nothrow) DisplayInfo();
270    if (displayInfo == nullptr) {
271        return displayInfo;
272    }
273
274    displayInfo->name_ = name_;
275    displayInfo->SetDisplayId(id_);
276    displayInfo->SetWidth(width_);
277    displayInfo->SetHeight(height_);
278    displayInfo->SetRefreshRate(refreshRate_);
279    displayInfo->SetScreenId(screenId_);
280    displayInfo->SetScreenGroupId(screenGroupId_);
281    displayInfo->SetVirtualPixelRatio(virtualPixelRatio_);
282    displayInfo->SetXDpi(xDpi_);
283    displayInfo->SetYDpi(yDpi_);
284    displayInfo->SetDpi(virtualPixelRatio_ * DOT_PER_INCH);
285    displayInfo->SetRotation(rotation_);
286    displayInfo->SetOrientation(orientation_);
287    displayInfo->SetOffsetX(offsetX_);
288    displayInfo->SetOffsetY(offsetY_);
289    displayInfo->displayState_ = displayState_;
290    displayInfo->SetWaterfallDisplayCompressionStatus(waterfallDisplayCompressionStatus_);
291    displayInfo->SetDisplayOrientation(displayOrientation_);
292    displayInfo->SetIsDefaultVertical(isDefaultVertical_);
293    return displayInfo;
294}
295} // namespace OHOS::Rosen