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