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 "entities/screen_entity.h"
17
18#include <cinttypes>
19
20#include "battery_stats_service.h"
21#include "stats_log.h"
22
23namespace OHOS {
24namespace PowerMgr {
25namespace {
26}
27ScreenEntity::ScreenEntity()
28{
29    consumptionType_ = BatteryStatsInfo::CONSUMPTION_TYPE_SCREEN;
30}
31
32int64_t ScreenEntity::GetActiveTimeMs(StatsUtils::StatsType statsType, int16_t level)
33{
34    int64_t activeTimeMs = StatsUtils::DEFAULT_VALUE;
35    switch (statsType) {
36        case StatsUtils::STATS_TYPE_SCREEN_ON: {
37            if (screenOnTimer_ != nullptr) {
38                activeTimeMs = screenOnTimer_->GetRunningTimeMs();
39                STATS_HILOGD(COMP_SVC, "Get screen on time: %{public}" PRId64 "ms", activeTimeMs);
40                break;
41            }
42            STATS_HILOGD(COMP_SVC, "Didn't find related timer, return 0");
43            break;
44        }
45        case StatsUtils::STATS_TYPE_SCREEN_BRIGHTNESS: {
46            if (level != StatsUtils::INVALID_VALUE) {
47                auto iter = screenBrightnessTimerMap_.find(level);
48                if (iter != screenBrightnessTimerMap_.end() && iter->second != nullptr) {
49                    activeTimeMs = iter->second->GetRunningTimeMs();
50                    STATS_HILOGD(COMP_SVC,
51                        "Get screen brightness time: %{public}" PRId64 "ms of brightness level: %{public}d",
52                        activeTimeMs, level);
53                    break;
54                }
55                STATS_HILOGD(COMP_SVC, "No screen brightness timer found, return 0");
56                break;
57            }
58            activeTimeMs = GetBrightnessTotalTimeMs();
59            STATS_HILOGD(COMP_SVC, "Get screen brightness total time: %{public}" PRId64 "ms", activeTimeMs);
60            break;
61        }
62        default:
63            break;
64    }
65    return activeTimeMs;
66}
67
68int64_t ScreenEntity::GetBrightnessTotalTimeMs()
69{
70    int64_t totalTimeMs = StatsUtils::DEFAULT_VALUE;
71    for (auto timerIter : screenBrightnessTimerMap_) {
72        totalTimeMs += timerIter.second->GetRunningTimeMs();
73    }
74    return totalTimeMs;
75}
76
77void ScreenEntity::Calculate(int32_t uid)
78{
79    auto bss = BatteryStatsService::GetInstance();
80    auto screenOnAverageMa =
81        bss->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_SCREEN_ON);
82    auto screenOnTimeMs = GetActiveTimeMs(StatsUtils::STATS_TYPE_SCREEN_ON);
83    double screenOnPowerMah = screenOnAverageMa * screenOnTimeMs;
84
85    auto brightnessAverageMa =
86        bss->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_SCREEN_BRIGHTNESS);
87    double brightnessPowerMah = StatsUtils::DEFAULT_VALUE;
88    for (auto& iter : screenBrightnessTimerMap_) {
89        if (iter.second != nullptr) {
90            auto averageMa = brightnessAverageMa * iter.first;
91            auto timeMs = GetActiveTimeMs(StatsUtils::STATS_TYPE_SCREEN_BRIGHTNESS, iter.first);
92            brightnessPowerMah += averageMa * timeMs;
93        }
94    }
95
96    screenPowerMah_ = (screenOnPowerMah + brightnessPowerMah) / StatsUtils::MS_IN_HOUR;
97    totalPowerMah_ += screenPowerMah_;
98    std::shared_ptr<BatteryStatsInfo> statsInfo = std::make_shared<BatteryStatsInfo>();
99    statsInfo->SetConsumptioType(BatteryStatsInfo::CONSUMPTION_TYPE_SCREEN);
100    statsInfo->SetPower(screenPowerMah_);
101    statsInfoList_.push_back(statsInfo);
102    STATS_HILOGD(COMP_SVC, "Calculate screen active power consumption: %{public}lfmAh", screenPowerMah_);
103}
104
105double ScreenEntity::GetEntityPowerMah(int32_t uidOrUserId)
106{
107    return screenPowerMah_;
108}
109
110double ScreenEntity::GetStatsPowerMah(StatsUtils::StatsType statsType, int32_t uid)
111{
112    return screenPowerMah_;
113}
114
115std::shared_ptr<StatsHelper::ActiveTimer> ScreenEntity::GetOrCreateTimer(StatsUtils::StatsType statsType, int16_t level)
116{
117    std::shared_ptr<StatsHelper::ActiveTimer> timer = nullptr;
118    switch (statsType) {
119        case StatsUtils::STATS_TYPE_SCREEN_ON: {
120            if (screenOnTimer_ != nullptr) {
121                STATS_HILOGD(COMP_SVC, "Get screen on timer");
122                timer = screenOnTimer_;
123                break;
124            }
125            STATS_HILOGD(COMP_SVC, "Create screen on timer");
126            screenOnTimer_ = std::make_shared<StatsHelper::ActiveTimer>();
127            timer = screenOnTimer_;
128            break;
129        }
130        case StatsUtils::STATS_TYPE_SCREEN_BRIGHTNESS: {
131            if (level <= StatsUtils::INVALID_VALUE || level > StatsUtils::SCREEN_BRIGHTNESS_BIN) {
132                STATS_HILOGD(COMP_SVC, "Illegal brightness");
133                break;
134            }
135            auto iter = screenBrightnessTimerMap_.find(level);
136            if (iter != screenBrightnessTimerMap_.end() && iter->second != nullptr) {
137                STATS_HILOGD(COMP_SVC, "Get screen brightness timer of brightness level: %{public}d", level);
138                timer = iter->second;
139                break;
140            }
141            STATS_HILOGD(COMP_SVC, "Create screen brightness timer of brightness level: %{public}d", level);
142            std::shared_ptr<StatsHelper::ActiveTimer> brightnessTimer = std::make_shared<StatsHelper::ActiveTimer>();
143            screenBrightnessTimerMap_.insert(
144                std::pair<int32_t, std::shared_ptr<StatsHelper::ActiveTimer>>(level, brightnessTimer));
145            timer = brightnessTimer;
146            break;
147        }
148        default:
149            STATS_HILOGW(COMP_SVC, "Create active timer failed");
150            break;
151    }
152    return timer;
153}
154
155void ScreenEntity::Reset()
156{
157    // Reset app Screen total power consumption
158    screenPowerMah_ = StatsUtils::DEFAULT_VALUE;
159
160    // Reset Screen on timer
161    if (screenOnTimer_ != nullptr) {
162        screenOnTimer_->Reset();
163    }
164
165    // Reset Screen brightness timer
166    for (auto& iter : screenBrightnessTimerMap_) {
167        if (iter.second != nullptr) {
168            iter.second->Reset();
169        }
170    }
171}
172
173void ScreenEntity::DumpInfo(std::string& result, int32_t uid)
174{
175    int64_t onTime = GetActiveTimeMs(StatsUtils::STATS_TYPE_SCREEN_ON);
176    result.append("Screen dump:\n")
177        .append("Screen on time: ")
178        .append(ToString(onTime))
179        .append("ms")
180        .append("\n");
181}
182} // namespace PowerMgr
183} // namespace OHOS