194 lines
6.7 KiB
C++
194 lines
6.7 KiB
C++
//
|
|
// Copyright (C) 2019 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include <utility>
|
|
|
|
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
|
|
|
|
#include "AutomotiveDisplayProxyService.h"
|
|
|
|
namespace android {
|
|
namespace frameworks {
|
|
namespace automotive {
|
|
namespace display {
|
|
namespace V1_0 {
|
|
namespace implementation {
|
|
|
|
|
|
Return<sp<IGraphicBufferProducer>>
|
|
AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) {
|
|
auto it = mDisplays.find(id);
|
|
sp<IBinder> displayToken = nullptr;
|
|
sp<SurfaceControl> surfaceControl = nullptr;
|
|
if (it == mDisplays.end()) {
|
|
displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id));
|
|
if (displayToken == nullptr) {
|
|
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
|
|
return nullptr;
|
|
}
|
|
|
|
// Get the resolution from stored display state.
|
|
ui::DisplayMode displayMode = {};
|
|
auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
|
|
if (err != NO_ERROR) {
|
|
ALOGE("Failed to get display mode of %lX. "
|
|
"This display will be ignored.", (unsigned long)id);
|
|
return nullptr;
|
|
}
|
|
|
|
ui::DisplayState displayState = {};
|
|
err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
|
|
if (err != NO_ERROR) {
|
|
ALOGE("Failed to get current display status of %lX. "
|
|
"This display will be ignored.", (unsigned long)id);
|
|
return nullptr;
|
|
}
|
|
|
|
auto displayWidth = displayMode.resolution.getWidth();
|
|
auto displayHeight = displayMode.resolution.getHeight();
|
|
if ((displayState.orientation != ui::ROTATION_0) &&
|
|
(displayState.orientation != ui::ROTATION_180)) {
|
|
std::swap(displayWidth, displayHeight);
|
|
}
|
|
|
|
sp<android::SurfaceComposerClient> surfaceClient = new SurfaceComposerClient();
|
|
err = surfaceClient->initCheck();
|
|
if (err != NO_ERROR) {
|
|
ALOGE("SurfaceComposerClient::initCheck error: %#x", err);
|
|
return nullptr;
|
|
}
|
|
|
|
// Create a SurfaceControl instance
|
|
surfaceControl = surfaceClient->createSurface(
|
|
String8::format("AutomotiveDisplay::%lX", (unsigned long)id),
|
|
displayWidth, displayHeight,
|
|
PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
|
|
if (surfaceControl == nullptr || !surfaceControl->isValid()) {
|
|
ALOGE("Failed to create SurfaceControl.");
|
|
return nullptr;
|
|
}
|
|
|
|
// Store
|
|
DisplayDesc descriptor = {displayToken, surfaceControl};
|
|
mDisplays.insert_or_assign(id, std::move(descriptor));
|
|
} else {
|
|
displayToken = it->second.token;
|
|
surfaceControl = it->second.surfaceControl;
|
|
}
|
|
|
|
// SurfaceControl::getSurface is guaranteed to be not null.
|
|
auto targetSurface = surfaceControl->getSurface();
|
|
return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
|
|
B2HGraphicBufferProducer(targetSurface->getIGraphicBufferProducer());
|
|
}
|
|
|
|
|
|
Return<bool> AutomotiveDisplayProxyService::showWindow(uint64_t id) {
|
|
auto it = mDisplays.find(id);
|
|
if (it == mDisplays.end()) {
|
|
ALOGE("Given display token is invalid or unknown.");
|
|
return false;
|
|
}
|
|
|
|
ui::DisplayState displayState;
|
|
auto err = SurfaceComposerClient::getDisplayState(it->second.token, &displayState);
|
|
if (err != NO_ERROR) {
|
|
ALOGE("Failed to get current state of the display 0x%lX", (unsigned long)id);
|
|
return false;
|
|
}
|
|
|
|
SurfaceComposerClient::Transaction t;
|
|
t.setDisplayLayerStack(it->second.token, displayState.layerStack);
|
|
t.setLayerStack(it->second.surfaceControl, displayState.layerStack);
|
|
|
|
status_t status = t.setLayer(it->second.surfaceControl, 0x7FFFFFFF)
|
|
.show(it->second.surfaceControl)
|
|
.apply();
|
|
|
|
return status == NO_ERROR;
|
|
}
|
|
|
|
|
|
Return<bool> AutomotiveDisplayProxyService::hideWindow(uint64_t id) {
|
|
auto it = mDisplays.find(id);
|
|
if (it == mDisplays.end()) {
|
|
ALOGE("Given display token is invalid or unknown.");
|
|
return false;
|
|
}
|
|
|
|
status_t status = SurfaceComposerClient::Transaction{}
|
|
.hide(it->second.surfaceControl)
|
|
.apply();
|
|
|
|
return status == NO_ERROR;
|
|
}
|
|
|
|
|
|
Return<void> AutomotiveDisplayProxyService::getDisplayIdList(getDisplayIdList_cb _cb) {
|
|
hardware::hidl_vec<uint64_t> ids;
|
|
|
|
// Get stable IDs of all available displays and get their tokens and
|
|
// descriptors.
|
|
auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
|
|
ids.resize(displayIds.size());
|
|
for (auto i = 0; i < displayIds.size(); ++i) {
|
|
ids[i] = displayIds[i].value;
|
|
}
|
|
|
|
_cb(ids);
|
|
return hardware::Void();
|
|
}
|
|
|
|
|
|
Return<void> AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDisplayInfo_cb _cb) {
|
|
HwDisplayConfig activeConfig;
|
|
HwDisplayState activeState;
|
|
|
|
auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(id));
|
|
if (displayToken == nullptr) {
|
|
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
|
|
} else {
|
|
ui::DisplayMode displayMode = {};
|
|
auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
|
|
if (err != NO_ERROR) {
|
|
ALOGW("Failed to get display mode of %lX. "
|
|
"This display will be ignored.", (unsigned long)id);
|
|
}
|
|
|
|
ui::DisplayState displayState = {};
|
|
err = SurfaceComposerClient::getDisplayState(displayToken, &displayState);
|
|
if (err != NO_ERROR) {
|
|
ALOGW("Failed to get current display status of %lX. "
|
|
"This display will be ignored.", (unsigned long)id);
|
|
}
|
|
|
|
activeConfig.setToExternal((uint8_t*)&displayMode, sizeof(ui::DisplayMode));
|
|
activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState));
|
|
}
|
|
|
|
_cb(activeConfig, activeState);
|
|
return hardware::Void();
|
|
}
|
|
|
|
|
|
} // namespace implementation
|
|
} // namespace V1_0
|
|
} // namespace display
|
|
} // namespace automotive
|
|
} // namespace frameworks
|
|
} // namespace android
|
|
|