xref: /aosp_15_r20/frameworks/native/services/automotive/display/AutomotiveDisplayProxyService.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker //
2*38e8c45fSAndroid Build Coastguard Worker // Copyright (C) 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker //
4*38e8c45fSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker //
8*38e8c45fSAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker //
10*38e8c45fSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker // limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker //
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include <utility>
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
20*38e8c45fSAndroid Build Coastguard Worker 
21*38e8c45fSAndroid Build Coastguard Worker #include "AutomotiveDisplayProxyService.h"
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker namespace android {
24*38e8c45fSAndroid Build Coastguard Worker namespace frameworks {
25*38e8c45fSAndroid Build Coastguard Worker namespace automotive {
26*38e8c45fSAndroid Build Coastguard Worker namespace display {
27*38e8c45fSAndroid Build Coastguard Worker namespace V1_0 {
28*38e8c45fSAndroid Build Coastguard Worker namespace implementation {
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker Return<sp<IGraphicBufferProducer>>
getIGraphicBufferProducer(uint64_t id)32*38e8c45fSAndroid Build Coastguard Worker AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) {
33*38e8c45fSAndroid Build Coastguard Worker     auto it = mDisplays.find(id);
34*38e8c45fSAndroid Build Coastguard Worker     sp<IBinder> displayToken = nullptr;
35*38e8c45fSAndroid Build Coastguard Worker     sp<SurfaceControl> surfaceControl = nullptr;
36*38e8c45fSAndroid Build Coastguard Worker     if (it == mDisplays.end()) {
37*38e8c45fSAndroid Build Coastguard Worker         if (const auto displayId = DisplayId::fromValue<PhysicalDisplayId>(id)) {
38*38e8c45fSAndroid Build Coastguard Worker             displayToken = SurfaceComposerClient::getPhysicalDisplayToken(*displayId);
39*38e8c45fSAndroid Build Coastguard Worker         }
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker         if (displayToken == nullptr) {
42*38e8c45fSAndroid Build Coastguard Worker             ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
43*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
44*38e8c45fSAndroid Build Coastguard Worker         }
45*38e8c45fSAndroid Build Coastguard Worker 
46*38e8c45fSAndroid Build Coastguard Worker         // Get the resolution from stored display state.
47*38e8c45fSAndroid Build Coastguard Worker         ui::DisplayMode displayMode = {};
48*38e8c45fSAndroid Build Coastguard Worker         auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
49*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
50*38e8c45fSAndroid Build Coastguard Worker             ALOGE("Failed to get display mode of %lX.  "
51*38e8c45fSAndroid Build Coastguard Worker                   "This display will be ignored.", (unsigned long)id);
52*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
53*38e8c45fSAndroid Build Coastguard Worker         }
54*38e8c45fSAndroid Build Coastguard Worker 
55*38e8c45fSAndroid Build Coastguard Worker         ui::DisplayState displayState = {};
56*38e8c45fSAndroid Build Coastguard Worker         err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
57*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
58*38e8c45fSAndroid Build Coastguard Worker             ALOGE("Failed to get current display status of %lX.  "
59*38e8c45fSAndroid Build Coastguard Worker                   "This display will be ignored.", (unsigned long)id);
60*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
61*38e8c45fSAndroid Build Coastguard Worker         }
62*38e8c45fSAndroid Build Coastguard Worker 
63*38e8c45fSAndroid Build Coastguard Worker         auto displayWidth  = displayMode.resolution.getWidth();
64*38e8c45fSAndroid Build Coastguard Worker         auto displayHeight = displayMode.resolution.getHeight();
65*38e8c45fSAndroid Build Coastguard Worker         if ((displayState.orientation != ui::ROTATION_0) &&
66*38e8c45fSAndroid Build Coastguard Worker             (displayState.orientation != ui::ROTATION_180)) {
67*38e8c45fSAndroid Build Coastguard Worker             std::swap(displayWidth, displayHeight);
68*38e8c45fSAndroid Build Coastguard Worker         }
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker         sp<android::SurfaceComposerClient> surfaceClient = new SurfaceComposerClient();
71*38e8c45fSAndroid Build Coastguard Worker         err = surfaceClient->initCheck();
72*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
73*38e8c45fSAndroid Build Coastguard Worker             ALOGE("SurfaceComposerClient::initCheck error: %#x", err);
74*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
75*38e8c45fSAndroid Build Coastguard Worker         }
76*38e8c45fSAndroid Build Coastguard Worker 
77*38e8c45fSAndroid Build Coastguard Worker         // Create a SurfaceControl instance
78*38e8c45fSAndroid Build Coastguard Worker         surfaceControl = surfaceClient->createSurface(
79*38e8c45fSAndroid Build Coastguard Worker                 String8::format("AutomotiveDisplay::%lX", (unsigned long)id),
80*38e8c45fSAndroid Build Coastguard Worker                 displayWidth, displayHeight,
81*38e8c45fSAndroid Build Coastguard Worker                 PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
82*38e8c45fSAndroid Build Coastguard Worker         if (surfaceControl == nullptr || !surfaceControl->isValid()) {
83*38e8c45fSAndroid Build Coastguard Worker             ALOGE("Failed to create SurfaceControl.");
84*38e8c45fSAndroid Build Coastguard Worker             return nullptr;
85*38e8c45fSAndroid Build Coastguard Worker         }
86*38e8c45fSAndroid Build Coastguard Worker 
87*38e8c45fSAndroid Build Coastguard Worker         // Store
88*38e8c45fSAndroid Build Coastguard Worker         DisplayDesc descriptor = {displayToken, surfaceControl};
89*38e8c45fSAndroid Build Coastguard Worker         mDisplays.insert_or_assign(id, std::move(descriptor));
90*38e8c45fSAndroid Build Coastguard Worker     } else {
91*38e8c45fSAndroid Build Coastguard Worker         displayToken = it->second.token;
92*38e8c45fSAndroid Build Coastguard Worker         surfaceControl = it->second.surfaceControl;
93*38e8c45fSAndroid Build Coastguard Worker     }
94*38e8c45fSAndroid Build Coastguard Worker 
95*38e8c45fSAndroid Build Coastguard Worker     // SurfaceControl::getSurface is guaranteed to be not null.
96*38e8c45fSAndroid Build Coastguard Worker     auto targetSurface = surfaceControl->getSurface();
97*38e8c45fSAndroid Build Coastguard Worker     return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
98*38e8c45fSAndroid Build Coastguard Worker                B2HGraphicBufferProducer(targetSurface->getIGraphicBufferProducer());
99*38e8c45fSAndroid Build Coastguard Worker }
100*38e8c45fSAndroid Build Coastguard Worker 
101*38e8c45fSAndroid Build Coastguard Worker 
showWindow(uint64_t id)102*38e8c45fSAndroid Build Coastguard Worker Return<bool> AutomotiveDisplayProxyService::showWindow(uint64_t id) {
103*38e8c45fSAndroid Build Coastguard Worker     auto it = mDisplays.find(id);
104*38e8c45fSAndroid Build Coastguard Worker     if (it == mDisplays.end()) {
105*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Given display token is invalid or unknown.");
106*38e8c45fSAndroid Build Coastguard Worker         return false;
107*38e8c45fSAndroid Build Coastguard Worker     }
108*38e8c45fSAndroid Build Coastguard Worker 
109*38e8c45fSAndroid Build Coastguard Worker     ui::DisplayState displayState;
110*38e8c45fSAndroid Build Coastguard Worker     auto err = SurfaceComposerClient::getDisplayState(it->second.token, &displayState);
111*38e8c45fSAndroid Build Coastguard Worker     if (err != NO_ERROR) {
112*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Failed to get current state of the display 0x%lX", (unsigned long)id);
113*38e8c45fSAndroid Build Coastguard Worker         return false;
114*38e8c45fSAndroid Build Coastguard Worker     }
115*38e8c45fSAndroid Build Coastguard Worker 
116*38e8c45fSAndroid Build Coastguard Worker     SurfaceComposerClient::Transaction t;
117*38e8c45fSAndroid Build Coastguard Worker     t.setDisplayLayerStack(it->second.token, displayState.layerStack);
118*38e8c45fSAndroid Build Coastguard Worker     t.setLayerStack(it->second.surfaceControl, displayState.layerStack);
119*38e8c45fSAndroid Build Coastguard Worker 
120*38e8c45fSAndroid Build Coastguard Worker     status_t status = t.setLayer(it->second.surfaceControl, 0x7FFFFFFF)
121*38e8c45fSAndroid Build Coastguard Worker                       .show(it->second.surfaceControl)
122*38e8c45fSAndroid Build Coastguard Worker                       .apply();
123*38e8c45fSAndroid Build Coastguard Worker 
124*38e8c45fSAndroid Build Coastguard Worker     return status == NO_ERROR;
125*38e8c45fSAndroid Build Coastguard Worker }
126*38e8c45fSAndroid Build Coastguard Worker 
127*38e8c45fSAndroid Build Coastguard Worker 
hideWindow(uint64_t id)128*38e8c45fSAndroid Build Coastguard Worker Return<bool> AutomotiveDisplayProxyService::hideWindow(uint64_t id) {
129*38e8c45fSAndroid Build Coastguard Worker     auto it = mDisplays.find(id);
130*38e8c45fSAndroid Build Coastguard Worker     if (it == mDisplays.end()) {
131*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Given display token is invalid or unknown.");
132*38e8c45fSAndroid Build Coastguard Worker         return false;
133*38e8c45fSAndroid Build Coastguard Worker     }
134*38e8c45fSAndroid Build Coastguard Worker 
135*38e8c45fSAndroid Build Coastguard Worker     status_t status = SurfaceComposerClient::Transaction{}
136*38e8c45fSAndroid Build Coastguard Worker                       .hide(it->second.surfaceControl)
137*38e8c45fSAndroid Build Coastguard Worker                       .apply();
138*38e8c45fSAndroid Build Coastguard Worker 
139*38e8c45fSAndroid Build Coastguard Worker     return status == NO_ERROR;
140*38e8c45fSAndroid Build Coastguard Worker }
141*38e8c45fSAndroid Build Coastguard Worker 
142*38e8c45fSAndroid Build Coastguard Worker 
getDisplayIdList(getDisplayIdList_cb _cb)143*38e8c45fSAndroid Build Coastguard Worker Return<void> AutomotiveDisplayProxyService::getDisplayIdList(getDisplayIdList_cb _cb) {
144*38e8c45fSAndroid Build Coastguard Worker     hardware::hidl_vec<uint64_t> ids;
145*38e8c45fSAndroid Build Coastguard Worker 
146*38e8c45fSAndroid Build Coastguard Worker     // Get stable IDs of all available displays and get their tokens and
147*38e8c45fSAndroid Build Coastguard Worker     // descriptors.
148*38e8c45fSAndroid Build Coastguard Worker     auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
149*38e8c45fSAndroid Build Coastguard Worker     ids.resize(displayIds.size());
150*38e8c45fSAndroid Build Coastguard Worker     for (auto i = 0; i < displayIds.size(); ++i) {
151*38e8c45fSAndroid Build Coastguard Worker         ids[i] = displayIds[i].value;
152*38e8c45fSAndroid Build Coastguard Worker     }
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker     _cb(ids);
155*38e8c45fSAndroid Build Coastguard Worker     return hardware::Void();
156*38e8c45fSAndroid Build Coastguard Worker }
157*38e8c45fSAndroid Build Coastguard Worker 
158*38e8c45fSAndroid Build Coastguard Worker 
getDisplayInfo(uint64_t id,getDisplayInfo_cb _cb)159*38e8c45fSAndroid Build Coastguard Worker Return<void> AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDisplayInfo_cb _cb) {
160*38e8c45fSAndroid Build Coastguard Worker     HwDisplayConfig activeConfig;
161*38e8c45fSAndroid Build Coastguard Worker     HwDisplayState  activeState;
162*38e8c45fSAndroid Build Coastguard Worker 
163*38e8c45fSAndroid Build Coastguard Worker     sp<IBinder> displayToken;
164*38e8c45fSAndroid Build Coastguard Worker     if (const auto displayId = DisplayId::fromValue<PhysicalDisplayId>(id)) {
165*38e8c45fSAndroid Build Coastguard Worker         displayToken = SurfaceComposerClient::getPhysicalDisplayToken(*displayId);
166*38e8c45fSAndroid Build Coastguard Worker     }
167*38e8c45fSAndroid Build Coastguard Worker 
168*38e8c45fSAndroid Build Coastguard Worker     if (displayToken == nullptr) {
169*38e8c45fSAndroid Build Coastguard Worker         ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
170*38e8c45fSAndroid Build Coastguard Worker     } else {
171*38e8c45fSAndroid Build Coastguard Worker         ui::DisplayMode displayMode = {};
172*38e8c45fSAndroid Build Coastguard Worker         auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
173*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
174*38e8c45fSAndroid Build Coastguard Worker             ALOGW("Failed to get display mode of %lX.  "
175*38e8c45fSAndroid Build Coastguard Worker                   "This display will be ignored.", (unsigned long)id);
176*38e8c45fSAndroid Build Coastguard Worker         }
177*38e8c45fSAndroid Build Coastguard Worker 
178*38e8c45fSAndroid Build Coastguard Worker         ui::DisplayState displayState = {};
179*38e8c45fSAndroid Build Coastguard Worker         err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
180*38e8c45fSAndroid Build Coastguard Worker         if (err != NO_ERROR) {
181*38e8c45fSAndroid Build Coastguard Worker             ALOGW("Failed to get current display status of %lX.  "
182*38e8c45fSAndroid Build Coastguard Worker                   "This display will be ignored.", (unsigned long)id);
183*38e8c45fSAndroid Build Coastguard Worker         }
184*38e8c45fSAndroid Build Coastguard Worker 
185*38e8c45fSAndroid Build Coastguard Worker         activeConfig.setToExternal((uint8_t*)&displayMode, sizeof(ui::DisplayMode));
186*38e8c45fSAndroid Build Coastguard Worker         activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState));
187*38e8c45fSAndroid Build Coastguard Worker     }
188*38e8c45fSAndroid Build Coastguard Worker 
189*38e8c45fSAndroid Build Coastguard Worker     _cb(activeConfig, activeState);
190*38e8c45fSAndroid Build Coastguard Worker     return hardware::Void();
191*38e8c45fSAndroid Build Coastguard Worker }
192*38e8c45fSAndroid Build Coastguard Worker 
193*38e8c45fSAndroid Build Coastguard Worker 
194*38e8c45fSAndroid Build Coastguard Worker }  // namespace implementation
195*38e8c45fSAndroid Build Coastguard Worker }  // namespace V1_0
196*38e8c45fSAndroid Build Coastguard Worker }  // namespace display
197*38e8c45fSAndroid Build Coastguard Worker }  // namespace automotive
198*38e8c45fSAndroid Build Coastguard Worker }  // namespace frameworks
199*38e8c45fSAndroid Build Coastguard Worker }  // namespace android
200*38e8c45fSAndroid Build Coastguard Worker 
201