• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "hwc_tester.h"
18 #include <inttypes.h>
19 #include <log/log.h>
20 
21 namespace hcct {
22 
23 namespace {
24 static constexpr uint32_t kBufferSlotCount = 64;
25 } // namespace
26 
HwcTester()27 HwcTester::HwcTester() {
28   // Add thread pool configuration for Binder IPC
29   android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
30   android::ProcessState::self()->startThreadPool();
31 
32   mComposerClient = std::make_unique<libhwc_aidl_test::ComposerClientWrapper>(
33       IComposer::descriptor + std::string("/default"));
34   if (!mComposerClient) {
35     ALOGE("Failed to create HWC client");
36   }
37 
38   if (!mComposerClient->createClient().isOk()) {
39     ALOGE("Failed to create HWC client connection");
40   }
41 
42   const auto &[status, displays] = mComposerClient->getDisplays();
43   if (!status.isOk() || displays.empty()) {
44     ALOGE("Failed to get displays");
45     return;
46   }
47 
48   for (const auto &display : displays) {
49     mDisplays.emplace(display.getDisplayId(), std::move(display));
50   }
51 }
52 
~HwcTester()53 HwcTester::~HwcTester() {
54   std::unordered_map<int64_t, ComposerClientWriter *> displayWriters;
55   for (const auto &[id, _] : mDisplays) {
56     displayWriters.emplace(id, &GetWriter(id));
57   }
58   mComposerClient->tearDown(displayWriters);
59   mComposerClient.reset();
60 }
61 
GetAllDisplayIds() const62 std::vector<int64_t> HwcTester::GetAllDisplayIds() const {
63   std::vector<int64_t> displayIds(mDisplays.size());
64 
65   for (const auto &[id, _] : mDisplays) {
66     displayIds.push_back(id);
67   }
68 
69   return displayIds;
70 }
71 
72 std::vector<std::pair<int64_t, common::DisplayHotplugEvent>>
getAndClearLatestHotplugs()73 HwcTester::getAndClearLatestHotplugs() {
74   return mComposerClient->getAndClearLatestHotplugs();
75 }
76 
77 std::vector<DisplayConfiguration>
GetDisplayConfigs(int64_t displayId)78 HwcTester::GetDisplayConfigs(int64_t displayId) {
79   const auto &[configStatus, configs] =
80       mComposerClient->getDisplayConfigurations(displayId);
81   if (!configStatus.isOk() || configs.empty()) {
82     ALOGE("Failed to get display configs for display %" PRId64, displayId);
83   }
84 
85   return configs;
86 }
87 
GetDisplayActiveConfigs(int64_t displayId)88 DisplayConfiguration HwcTester::GetDisplayActiveConfigs(int64_t displayId) {
89   auto [activeConfigStatus, activeConfig] =
90       mComposerClient->getActiveConfig(displayId);
91   if (!activeConfigStatus.isOk()) {
92     ALOGE("Failed to get active config for display %" PRId64, displayId);
93     return {};
94   }
95 
96   DisplayConfiguration displayConfig;
97   const auto &configs = GetDisplayConfigs(displayId);
98   for (const auto &config : configs) {
99     if (config.configId == activeConfig) {
100       return config;
101     }
102   }
103 
104   ALOGE("Active config was not found in configs for display %" PRId64,
105         displayId);
106   return {};
107 }
108 
DrawSolidColorToScreen(int64_t displayId,Color color)109 bool HwcTester::DrawSolidColorToScreen(int64_t displayId, Color color) {
110   // Create a layer for solid color
111   const auto &[status, layer] =
112       mComposerClient->createLayer(displayId, kBufferSlotCount, nullptr);
113   if (!status.isOk()) {
114     ALOGE("Failed to create layer on display %" PRId64, displayId);
115     return false;
116   }
117 
118   // Create a writer for the display commands
119   auto &writer = GetWriter(displayId);
120 
121   // Set layer properties
122   writer.setLayerCompositionType(displayId, layer, Composition::SOLID_COLOR);
123   writer.setLayerPlaneAlpha(displayId, layer, color.a);
124   writer.setLayerColor(displayId, layer, color);
125 
126   DisplayConfiguration displayConfig = GetDisplayActiveConfigs(displayId);
127   writer.setLayerDisplayFrame(
128       displayId, layer, Rect{0, 0, displayConfig.width, displayConfig.height});
129   writer.setLayerZOrder(displayId, layer, 0);
130 
131   // Validate and present display
132   writer.validateDisplay(displayId, ComposerClientWriter::kNoTimestamp, 0);
133   writer.presentDisplay(displayId);
134 
135   // Execute the commands
136   auto commands = writer.takePendingCommands();
137   std::pair<ScopedAStatus, std::vector<CommandResultPayload>> executeRes =
138       mComposerClient->executeCommands(commands);
139   return executeRes.first.isOk();
140 }
141 
GetWriter(int64_t display)142 ComposerClientWriter &HwcTester::GetWriter(int64_t display) {
143   auto [it, _] = mWriters.try_emplace(display, display);
144   return it->second;
145 }
146 
147 } // namespace hcct
148