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