1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "DisplayStateResidencyWatcher.h"
18 
19 #include <android-base/properties.h>
20 #include <android/binder_ibinder.h>
21 
22 #include "ExynosHWCHelper.h"
23 #include "Utils.h"
24 
25 using aidl::android::vendor::powerstats::IPixelStateResidencyCallback;
26 using aidl::android::vendor::powerstats::IPixelStateResidencyProvider;
27 
28 namespace android::hardware::graphics::composer {
29 
30 constexpr std::string_view kPowerStatsPropertyPrefix = "ro.vendor";
31 constexpr std::string_view kPowerStatsPropertySuffix = "powerstats.entity_name";
32 
DisplayStateResidencyWatcher(std::shared_ptr<CommonDisplayContextProvider> displayerInstance,std::shared_ptr<StatisticsProvider> statisticsProvider)33 DisplayStateResidencyWatcher::DisplayStateResidencyWatcher(
34         std::shared_ptr<CommonDisplayContextProvider> displayerInstance,
35         std::shared_ptr<StatisticsProvider> statisticsProvider)
36       : mDeathRecipient(AIBinder_DeathRecipient_new(binderDied)),
37         mStatisticsProvider(statisticsProvider) {
38     mDisplayPresentStatisticsProvider =
39             std::make_unique<DisplayStateResidencyProvider>(displayerInstance, statisticsProvider);
40 
41     registerWithPowerStats();
42 
43     std::string displayEntityNameId = std::string(kPowerStatsPropertyPrefix) + "." +
44             "primarydisplay" + "." + std::string(kPowerStatsPropertySuffix);
45     // Retrieve the entity name from the property.
46     mEntityName = android::base::GetProperty(displayEntityNameId, "Display");
47 }
48 
~DisplayStateResidencyWatcher()49 DisplayStateResidencyWatcher::~DisplayStateResidencyWatcher() {
50     mRunning.store(false);
51     if (mTaskHandler.joinable()) {
52         mTaskHandler.join();
53     }
54     if (mProvider) {
55         AIBinder_unlinkToDeath(mProvider->asBinder().get(), mDeathRecipient.get(),
56                                reinterpret_cast<void*>(this));
57         mProvider->unregisterCallback(this->ref<IPixelStateResidencyCallback>());
58     }
59 }
60 
getStateResidency(std::vector<StateResidency> * stats)61 ::ndk::ScopedAStatus DisplayStateResidencyWatcher::getStateResidency(
62         std::vector<StateResidency>* stats) {
63     mDisplayPresentStatisticsProvider->getStateResidency(stats);
64 
65     return ::ndk::ScopedAStatus::ok();
66 }
67 
68 constexpr std::chrono::seconds kOneSecondPeriod{1};
69 
registerWithPowerStats()70 void DisplayStateResidencyWatcher::registerWithPowerStats() {
71     if (mProvider) {
72         LOG(INFO) << "Need to reconnect PowerStats service";
73         mProvider.reset();
74     }
75     LOG(INFO) << "Registering PowerStats callback";
76     if (mTaskHandler.joinable()) {
77         mTaskHandler.join();
78     }
79     mTaskHandler = std::thread([this]() {
80         static const std::string kInstance = "power.stats-vendor";
81         static const int64_t kMaxWaitServiceTimeMs =
82                 100 * std::milli::den; // Default timeout is 100 seconds.
83 
84         int64_t startMs = getSteadyClockTimeMs();
85         while (mRunning.load()) {
86             ndk::SpAIBinder binder(AServiceManager_waitForService(kInstance.c_str()));
87             mProvider = IPixelStateResidencyProvider::fromBinder(binder);
88             if (mProvider) {
89                 break;
90             } else {
91                 int64_t nowMs = getSteadyClockTimeMs();
92                 if ((nowMs - startMs) > kMaxWaitServiceTimeMs) {
93                     LOG(ERROR) << "Cannot get PowerStats service";
94                     break;
95                 }
96                 std::this_thread::sleep_for(kOneSecondPeriod);
97             }
98         }
99 
100         if (!mRunning.load() || !mProvider) {
101             return;
102         }
103 
104         if (auto status =
105                     mProvider->registerCallbackByStates(mEntityName,
106                                                         this->ref<IPixelStateResidencyCallback>(),
107                                                         mDisplayPresentStatisticsProvider
108                                                                 ->getStates());
109             status.isOk()) {
110             LOG(INFO) << "PowerStats callback is successfully registered.";
111         } else {
112             LOG(ERROR) << "failed to register callback: " << status.getDescription();
113         }
114         AIBinder_linkToDeath(mProvider->asBinder().get(), mDeathRecipient.get(),
115                              reinterpret_cast<void*>(this));
116     });
117 }
118 
binderDied(void * cookie)119 void DisplayStateResidencyWatcher::binderDied(void* cookie) {
120     LOG(ERROR) << "power.stats died";
121 
122     auto residencyWatcher = reinterpret_cast<DisplayStateResidencyWatcher*>(cookie);
123 
124     residencyWatcher->registerWithPowerStats();
125 }
126 
127 } // namespace android::hardware::graphics::composer
128