From 1f1ea0038bb17f3f134b0a209019e412edeaf035 Mon Sep 17 00:00:00 2001 From: Hinix Date: Wed, 14 May 2025 11:20:35 +0800 Subject: [PATCH] add cme, support 32bit apps --- .../wpa_supplicant/wpa_supplicant.c | 2 +- .../services/surfaceflinger/DisplayDevice.cpp | 622 ++++ .../utils/hwc2on1adapter/HWC2On1Adapter.cpp | 2651 +++++++++++++++++ .../android/server/ConnectivityService.java | 1 + .../android/server/NetworkStackService.java | 747 ----- .../wifi/SupplicantStaIfaceHalAidlImpl.java | 2 +- aosp/system/core/rootdir/init.rc | 1 + aosp/vendor/common/prebuild/Android.mk | 90 + aosp/vendor/common/prebuild/media_engine.mk | 36 + aosp/vendor/isula/common.mk | 14 +- aosp/vendor/isula/copyfiles.mk | 1 + aosp/vendor/isula/hals/Android.mk | 44 - aosp/vendor/isula/hals/CleanSpec.mk | 1 - aosp/vendor/isula/packages.mk | 44 +- aosp/vendor/isula/properties.mk | 2 +- aosp/vendor/isula/vagpu/Android.bp | 27 + aosp/vendor/isula/vagpu/Android.mk | 150 +- 17 files changed, 3543 insertions(+), 892 deletions(-) create mode 100644 aosp/frameworks/native/services/surfaceflinger/DisplayDevice.cpp create mode 100644 aosp/hardware/interfaces/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp delete mode 100644 aosp/packages/modules/NetworkStack/src/com/android/server/NetworkStackService.java create mode 100644 aosp/vendor/common/prebuild/Android.mk create mode 100644 aosp/vendor/common/prebuild/media_engine.mk delete mode 100644 aosp/vendor/isula/hals/Android.mk delete mode 100644 aosp/vendor/isula/hals/CleanSpec.mk create mode 100644 aosp/vendor/isula/vagpu/Android.bp diff --git a/aosp/external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant.c b/aosp/external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant.c index 86b8419da..2d48ff59a 100644 --- a/aosp/external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant.c +++ b/aosp/external/wpa_supplicant_8/wpa_supplicant/wpa_supplicant.c @@ -7277,7 +7277,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->num_multichan_concurrent = 1; if (wpa_helpers_enable()) { - goto wpa_helpers_ctrl_iface; + goto wpa_helpers_ctrl_iface; } if (wpa_supplicant_driver_init(wpa_s) < 0) return -1; diff --git a/aosp/frameworks/native/services/surfaceflinger/DisplayDevice.cpp b/aosp/frameworks/native/services/surfaceflinger/DisplayDevice.cpp new file mode 100644 index 000000000..1e62854b1 --- /dev/null +++ b/aosp/frameworks/native/services/surfaceflinger/DisplayDevice.cpp @@ -0,0 +1,622 @@ +/* + * Copyright (C) 2007 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. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + +// #define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "DisplayDevice" + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#define VA_ROTATION_CONFIG_FLAG (1ULL << 10) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DisplayDevice.h" +#include "FrontEnd/DisplayInfo.h" +#include "HdrSdrRatioOverlay.h" +#include "Layer.h" +#include "RefreshRateOverlay.h" +#include "SurfaceFlinger.h" + +namespace android { + +namespace hal = hardware::graphics::composer::hal; + +DisplayDeviceCreationArgs::DisplayDeviceCreationArgs( + const sp& flinger, HWComposer& hwComposer, const wp& displayToken, + std::shared_ptr compositionDisplay) + : flinger(flinger), + hwComposer(hwComposer), + displayToken(displayToken), + compositionDisplay(compositionDisplay) {} + +DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) + : mFlinger(args.flinger), + mHwComposer(args.hwComposer), + mDisplayToken(args.displayToken), + mSequenceId(args.sequenceId), + mCompositionDisplay{args.compositionDisplay}, + mPendingModeFpsTrace(concatId("PendingModeFps")), + mActiveModeFpsTrace(concatId("ActiveModeFps")), + mRenderRateFpsTrace(concatId("RenderRateFps")), + mPhysicalOrientation(args.physicalOrientation), + mPowerMode(ftl::Concat("PowerMode ", getId().value).c_str(), args.initialPowerMode), + mIsPrimary(args.isPrimary), + mRequestedRefreshRate(args.requestedRefreshRate), + mRefreshRateSelector(std::move(args.refreshRateSelector)), + mHasDesiredModeTrace(concatId("HasDesiredMode"), false) { + mCompositionDisplay->editState().isSecure = args.isSecure; + mCompositionDisplay->editState().isProtected = args.isProtected; + mCompositionDisplay->createRenderSurface( + compositionengine::RenderSurfaceCreationArgsBuilder() + .setDisplayWidth(ANativeWindow_getWidth(args.nativeWindow.get())) + .setDisplayHeight(ANativeWindow_getHeight(args.nativeWindow.get())) + .setNativeWindow(std::move(args.nativeWindow)) + .setDisplaySurface(std::move(args.displaySurface)) + .setMaxTextureCacheSize( + static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)) + .build()); + + if (!mFlinger->mDisableClientCompositionCache && + SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { + mCompositionDisplay->createClientCompositionCache( + static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)); + } + + mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy); + mCompositionDisplay->setTreat170mAsSrgb(mFlinger->mTreat170mAsSrgb); + mCompositionDisplay->createDisplayColorProfile( + compositionengine::DisplayColorProfileCreationArgsBuilder() + .setHasWideColorGamut(args.hasWideColorGamut) + .setHdrCapabilities(std::move(args.hdrCapabilities)) + .setSupportedPerFrameMetadata(args.supportedPerFrameMetadata) + .setHwcColorModes(std::move(args.hwcColorModes)) + .Build()); + + if (!mCompositionDisplay->isValid()) { + ALOGE("Composition Display did not validate!"); + } + + mCompositionDisplay->getRenderSurface()->initialize(); + + setPowerMode(args.initialPowerMode); + + // initialize the display orientation transform. + setProjection(ui::ROTATION_0, Rect::INVALID_RECT, Rect::INVALID_RECT); +} + +DisplayDevice::~DisplayDevice() = default; + +void DisplayDevice::disconnect() { + mCompositionDisplay->disconnect(); +} + +int DisplayDevice::getWidth() const { + return mCompositionDisplay->getState().displaySpace.getBounds().width; +} + +int DisplayDevice::getHeight() const { + return mCompositionDisplay->getState().displaySpace.getBounds().height; +} + +void DisplayDevice::setDisplayName(const std::string& displayName) { + if (!displayName.empty()) { + // never override the name with an empty name + mDisplayName = displayName; + mCompositionDisplay->setName(displayName); + } +} + +auto DisplayDevice::getFrontEndInfo() const -> frontend::DisplayInfo { + gui::DisplayInfo info; + info.displayId = getLayerStack().id; + + // The physical orientation is set when the orientation of the display panel is + // different than the default orientation of the device. Other services like + // InputFlinger do not know about this, so we do not need to expose the physical + // orientation of the panel outside of SurfaceFlinger. + const ui::Rotation inversePhysicalOrientation = ui::ROTATION_0 - mPhysicalOrientation; + auto width = getWidth(); + auto height = getHeight(); + if (inversePhysicalOrientation == ui::ROTATION_90 || + inversePhysicalOrientation == ui::ROTATION_270) { + std::swap(width, height); + } + const ui::Transform undoPhysicalOrientation(ui::Transform::toRotationFlags( + inversePhysicalOrientation), + width, height); + const auto& displayTransform = undoPhysicalOrientation * getTransform(); + // Send the inverse display transform to input so it can convert display coordinates to + // logical display. + info.transform = displayTransform.inverse(); + + info.logicalWidth = getLayerStackSpaceRect().width(); + info.logicalHeight = getLayerStackSpaceRect().height(); + + return {.info = info, + .transform = displayTransform, + .receivesInput = receivesInput(), + .isSecure = isSecure(), + .isPrimary = isPrimary(), + .isVirtual = isVirtual(), + .rotationFlags = ui::Transform::toRotationFlags(mOrientation), + .transformHint = getTransformHint()}; +} + +void DisplayDevice::setPowerMode(hal::PowerMode mode) { + // TODO(b/241285876): Skip this for virtual displays. + if (mode == hal::PowerMode::OFF || mode == hal::PowerMode::ON) { + if (mStagedBrightness && mBrightness != mStagedBrightness) { + getCompositionDisplay()->setNextBrightness(*mStagedBrightness); + mBrightness = *mStagedBrightness; + } + mStagedBrightness = std::nullopt; + getCompositionDisplay()->applyDisplayBrightness(true); + } + + mPowerMode = mode; + + getCompositionDisplay()->setCompositionEnabled(isPoweredOn()); +} + +void DisplayDevice::tracePowerMode() { + // Assign the same value for tracing. + mPowerMode = mPowerMode.get(); +} + +void DisplayDevice::enableLayerCaching(bool enable) { + getCompositionDisplay()->setLayerCachingEnabled(enable); +} + +hal::PowerMode DisplayDevice::getPowerMode() const { + return mPowerMode; +} + +bool DisplayDevice::isPoweredOn() const { + return mPowerMode != hal::PowerMode::OFF; +} + +void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) { + ATRACE_INT(mActiveModeFpsTrace.c_str(), vsyncRate.getIntValue()); + ATRACE_INT(mRenderRateFpsTrace.c_str(), renderFps.getIntValue()); + + mRefreshRateSelector->setActiveMode(modeId, renderFps); + updateRefreshRateOverlayRate(vsyncRate, renderFps); +} + +bool DisplayDevice::initiateModeChange(display::DisplayModeRequest&& desiredMode, + const hal::VsyncPeriodChangeConstraints& constraints, + hal::VsyncPeriodChangeTimeline& outTimeline) { + // TODO(b/255635711): Flow the DisplayModeRequest through the desired/pending/active states. For + // now, `desiredMode` and `mDesiredModeOpt` are one and the same, but the latter is not cleared + // until the next `SF::initiateDisplayModeChanges`. However, the desired mode has been consumed + // at this point, so clear the `force` flag to prevent an endless loop of `initiateModeChange`. + if (FlagManager::getInstance().connected_display()) { + std::scoped_lock lock(mDesiredModeLock); + if (mDesiredModeOpt) { + mDesiredModeOpt->force = false; + } + } + + mPendingModeOpt = std::move(desiredMode); + mIsModeSetPending = true; + + const auto& mode = *mPendingModeOpt->mode.modePtr; + + if (mHwComposer.setActiveModeWithConstraints(getPhysicalId(), mode.getHwcId(), constraints, + &outTimeline) != OK) { + return false; + } + + ATRACE_INT(mPendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue()); + return true; +} + +void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) { + setActiveMode(modeId, vsyncRate, renderFps); + mIsModeSetPending = false; +} + +nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const { + const auto physicalId = getPhysicalId(); + if (!mHwComposer.isConnected(physicalId)) { + return 0; + } + + if (const auto vsyncPeriodOpt = mHwComposer.getDisplayVsyncPeriod(physicalId).value_opt()) { + return *vsyncPeriodOpt; + } + + return refreshRateSelector().getActiveMode().modePtr->getVsyncRate().getPeriodNsecs(); +} + +ui::Dataspace DisplayDevice::getCompositionDataSpace() const { + return mCompositionDisplay->getState().dataspace; +} + +void DisplayDevice::setLayerFilter(ui::LayerFilter filter) { + mCompositionDisplay->setLayerFilter(filter); + if (mRefreshRateOverlay) { + mRefreshRateOverlay->setLayerStack(filter.layerStack); + } + if (mHdrSdrRatioOverlay) { + mHdrSdrRatioOverlay->setLayerStack(filter.layerStack); + } +} + +void DisplayDevice::setFlags(uint32_t flags) { + mFlags = flags; +} + +void DisplayDevice::setDisplaySize(int width, int height) { + LOG_FATAL_IF(!isVirtual(), "Changing the display size is supported only for virtual displays."); + const auto size = ui::Size(width, height); + mCompositionDisplay->setDisplaySize(size); + if (mRefreshRateOverlay) { + mRefreshRateOverlay->setViewport(size); + } + if (mHdrSdrRatioOverlay) { + mHdrSdrRatioOverlay->setViewport(size); + } +} + +void DisplayDevice::setProjection(ui::Rotation orientation, Rect layerStackSpaceRect, + Rect orientedDisplaySpaceRect) { + mIsOrientationChanged = mOrientation != orientation; + mOrientation = orientation; + + if (isPrimary()) { + hal::HWDisplayId Id = mHwComposer.getPrimaryHwcDisplayId(); + int error = (int)mHwComposer.getComposer()->setActiveConfig(Id, VA_ROTATION_CONFIG_FLAG | (unsigned int)orientation); + if (error != 0) { + ALOGE("%s(%d): hwc set rotation failed, id: %d, orientation: %d, error: %d", __func__, __LINE__, (int)Id, (int)error, (int)orientation); + } + } + + // We need to take care of display rotation for globalTransform for case if the panel is not + // installed aligned with device orientation. + const auto transformOrientation = orientation + mPhysicalOrientation; + + const auto& state = getCompositionDisplay()->getState(); + + // If the layer stack and destination frames have never been set, then configure them to be the + // same as the physical device, taking into account the total transform. + if (!orientedDisplaySpaceRect.isValid()) { + ui::Size bounds = state.displaySpace.getBounds(); + bounds.rotate(transformOrientation); + orientedDisplaySpaceRect = Rect(bounds); + } + if (layerStackSpaceRect.isEmpty()) { + ui::Size bounds = state.framebufferSpace.getBounds(); + bounds.rotate(transformOrientation); + layerStackSpaceRect = Rect(bounds); + } + getCompositionDisplay()->setProjection(transformOrientation, layerStackSpaceRect, + orientedDisplaySpaceRect); +} + +void DisplayDevice::stageBrightness(float brightness) { + mStagedBrightness = brightness; +} + +void DisplayDevice::persistBrightness(bool needsComposite) { + if (mStagedBrightness && mBrightness != mStagedBrightness) { + if (needsComposite) { + getCompositionDisplay()->setNextBrightness(*mStagedBrightness); + } + mBrightness = *mStagedBrightness; + } + mStagedBrightness = std::nullopt; +} + +std::optional DisplayDevice::getStagedBrightness() const { + return mStagedBrightness; +} + +void DisplayDevice::dump(utils::Dumper& dumper) const { + using namespace std::string_view_literals; + + dumper.dump("name"sv, '"' + mDisplayName + '"'); + dumper.dump("powerMode"sv, mPowerMode); + + if (mRefreshRateSelector) { + mRefreshRateSelector->dump(dumper); + } +} + +bool DisplayDevice::hasRenderIntent(ui::RenderIntent intent) const { + return mCompositionDisplay->getDisplayColorProfile()->hasRenderIntent(intent); +} + +DisplayId DisplayDevice::getId() const { + return mCompositionDisplay->getId(); +} + +bool DisplayDevice::isSecure() const { + return mCompositionDisplay->isSecure(); +} + +void DisplayDevice::setSecure(bool secure) { + mCompositionDisplay->setSecure(secure); +} + +const Rect DisplayDevice::getBounds() const { + return mCompositionDisplay->getState().displaySpace.getBoundsAsRect(); +} + +const Region& DisplayDevice::getUndefinedRegion() const { + return mCompositionDisplay->getState().undefinedRegion; +} + +ui::LayerStack DisplayDevice::getLayerStack() const { + return mCompositionDisplay->getState().layerFilter.layerStack; +} + +ui::Transform::RotationFlags DisplayDevice::getTransformHint() const { + return mCompositionDisplay->getTransformHint(); +} + +const ui::Transform& DisplayDevice::getTransform() const { + return mCompositionDisplay->getState().transform; +} + +const Rect& DisplayDevice::getLayerStackSpaceRect() const { + return mCompositionDisplay->getState().layerStackSpace.getContent(); +} + +const Rect& DisplayDevice::getOrientedDisplaySpaceRect() const { + return mCompositionDisplay->getState().orientedDisplaySpace.getContent(); +} + +bool DisplayDevice::hasWideColorGamut() const { + return mCompositionDisplay->getDisplayColorProfile()->hasWideColorGamut(); +} + +bool DisplayDevice::hasHDR10PlusSupport() const { + return mCompositionDisplay->getDisplayColorProfile()->hasHDR10PlusSupport(); +} + +bool DisplayDevice::hasHDR10Support() const { + return mCompositionDisplay->getDisplayColorProfile()->hasHDR10Support(); +} + +bool DisplayDevice::hasHLGSupport() const { + return mCompositionDisplay->getDisplayColorProfile()->hasHLGSupport(); +} + +bool DisplayDevice::hasDolbyVisionSupport() const { + return mCompositionDisplay->getDisplayColorProfile()->hasDolbyVisionSupport(); +} + +int DisplayDevice::getSupportedPerFrameMetadata() const { + return mCompositionDisplay->getDisplayColorProfile()->getSupportedPerFrameMetadata(); +} + +void DisplayDevice::overrideHdrTypes(const std::vector& hdrTypes) { + mOverrideHdrTypes = hdrTypes; +} + +HdrCapabilities DisplayDevice::getHdrCapabilities() const { + const HdrCapabilities& capabilities = + mCompositionDisplay->getDisplayColorProfile()->getHdrCapabilities(); + std::vector hdrTypes = capabilities.getSupportedHdrTypes(); + if (!mOverrideHdrTypes.empty()) { + hdrTypes = mOverrideHdrTypes; + } + return HdrCapabilities(hdrTypes, capabilities.getDesiredMaxLuminance(), + capabilities.getDesiredMaxAverageLuminance(), + capabilities.getDesiredMinLuminance()); +} + +void DisplayDevice::enableHdrSdrRatioOverlay(bool enable) { + if (!enable) { + mHdrSdrRatioOverlay.reset(); + return; + } + + mHdrSdrRatioOverlay = HdrSdrRatioOverlay::create(); + if (mHdrSdrRatioOverlay) { + mHdrSdrRatioOverlay->setLayerStack(getLayerStack()); + mHdrSdrRatioOverlay->setViewport(getSize()); + updateHdrSdrRatioOverlayRatio(mHdrSdrRatio); + } +} + +void DisplayDevice::updateHdrSdrRatioOverlayRatio(float currentHdrSdrRatio) { + ATRACE_CALL(); + mHdrSdrRatio = currentHdrSdrRatio; + if (mHdrSdrRatioOverlay) { + mHdrSdrRatioOverlay->changeHdrSdrRatio(currentHdrSdrRatio); + } +} + +void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, + bool showRenderRate, bool showInMiddle) { + if (!enable) { + mRefreshRateOverlay.reset(); + return; + } + + ftl::Flags features; + if (showSpinner) { + features |= RefreshRateOverlay::Features::Spinner; + } + + if (showRenderRate) { + features |= RefreshRateOverlay::Features::RenderRate; + } + + if (showInMiddle) { + features |= RefreshRateOverlay::Features::ShowInMiddle; + } + + if (setByHwc) { + features |= RefreshRateOverlay::Features::SetByHwc; + } + + // TODO(b/296636258) Update to use the render rate range in VRR mode. + const auto fpsRange = mRefreshRateSelector->getSupportedRefreshRateRange(); + mRefreshRateOverlay = RefreshRateOverlay::create(fpsRange, features); + if (mRefreshRateOverlay) { + mRefreshRateOverlay->setLayerStack(getLayerStack()); + mRefreshRateOverlay->setViewport(getSize()); + updateRefreshRateOverlayRate(getActiveMode().modePtr->getVsyncRate(), getActiveMode().fps, + setByHwc); + } +} + +void DisplayDevice::updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc) { + ATRACE_CALL(); + if (mRefreshRateOverlay) { + if (!mRefreshRateOverlay->isSetByHwc() || setByHwc) { + mRefreshRateOverlay->changeRefreshRate(vsyncRate, renderFps); + } else { + mRefreshRateOverlay->changeRenderRate(renderFps); + } + } +} + +bool DisplayDevice::onKernelTimerChanged(std::optional desiredModeId, + bool timerExpired) { + if (mRefreshRateSelector && mRefreshRateOverlay) { + const auto newMode = + mRefreshRateSelector->onKernelTimerChanged(desiredModeId, timerExpired); + if (newMode) { + updateRefreshRateOverlayRate(newMode->modePtr->getVsyncRate(), newMode->fps); + return true; + } + } + + return false; +} + +void DisplayDevice::animateOverlay() { + if (mRefreshRateOverlay) { + mRefreshRateOverlay->animate(); + } + if (mHdrSdrRatioOverlay) { + // hdr sdr ratio is designed to be on the top right of the screen, + // therefore, we need to re-calculate the display's width and height + if (mIsOrientationChanged) { + auto width = getWidth(); + auto height = getHeight(); + if (mOrientation == ui::ROTATION_90 || mOrientation == ui::ROTATION_270) { + std::swap(width, height); + } + mHdrSdrRatioOverlay->setViewport({width, height}); + } + mHdrSdrRatioOverlay->animate(); + } +} + +auto DisplayDevice::setDesiredMode(display::DisplayModeRequest&& desiredMode) -> DesiredModeAction { + ATRACE_NAME(concatId(__func__).c_str()); + ALOGD("%s %s", concatId(__func__).c_str(), to_string(desiredMode).c_str()); + + std::scoped_lock lock(mDesiredModeLock); + if (mDesiredModeOpt) { + // A mode transition was already scheduled, so just override the desired mode. + const bool emitEvent = mDesiredModeOpt->emitEvent; + const bool force = mDesiredModeOpt->force; + mDesiredModeOpt = std::move(desiredMode); + mDesiredModeOpt->emitEvent |= emitEvent; + if (FlagManager::getInstance().connected_display()) { + mDesiredModeOpt->force |= force; + } + return DesiredModeAction::None; + } + + // If the desired mode is already active... + const auto activeMode = refreshRateSelector().getActiveMode(); + if (const auto& desiredModePtr = desiredMode.mode.modePtr; + !desiredMode.force && activeMode.modePtr->getId() == desiredModePtr->getId()) { + if (activeMode == desiredMode.mode) { + return DesiredModeAction::None; + } + + // ...but the render rate changed: + setActiveMode(desiredModePtr->getId(), desiredModePtr->getVsyncRate(), + desiredMode.mode.fps); + return DesiredModeAction::InitiateRenderRateSwitch; + } + + // Set the render frame rate to the active physical refresh rate to schedule the next + // frame as soon as possible. + setActiveMode(activeMode.modePtr->getId(), activeMode.modePtr->getVsyncRate(), + activeMode.modePtr->getVsyncRate()); + + // Initiate a mode change. + mDesiredModeOpt = std::move(desiredMode); + mHasDesiredModeTrace = true; + return DesiredModeAction::InitiateDisplayModeSwitch; +} + +auto DisplayDevice::getDesiredMode() const -> DisplayModeRequestOpt { + std::scoped_lock lock(mDesiredModeLock); + return mDesiredModeOpt; +} + +void DisplayDevice::clearDesiredMode() { + std::scoped_lock lock(mDesiredModeLock); + mDesiredModeOpt.reset(); + mHasDesiredModeTrace = false; +} + +void DisplayDevice::adjustRefreshRate(Fps pacesetterDisplayRefreshRate) { + using fps_approx_ops::operator<=; + if (mRequestedRefreshRate <= 0_Hz) { + return; + } + + using fps_approx_ops::operator>; + if (mRequestedRefreshRate > pacesetterDisplayRefreshRate) { + mAdjustedRefreshRate = pacesetterDisplayRefreshRate; + return; + } + + unsigned divisor = static_cast( + std::floor(pacesetterDisplayRefreshRate.getValue() / mRequestedRefreshRate.getValue())); + if (divisor == 0) { + mAdjustedRefreshRate = 0_Hz; + return; + } + + mAdjustedRefreshRate = pacesetterDisplayRefreshRate / divisor; +} + +std::atomic DisplayDeviceState::sNextSequenceId(1); + +} // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/aosp/hardware/interfaces/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/aosp/hardware/interfaces/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp new file mode 100644 index 000000000..55eff8e29 --- /dev/null +++ b/aosp/hardware/interfaces/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp @@ -0,0 +1,2651 @@ +/* + * Copyright 2015 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 "hwc2on1adapter/HWC2On1Adapter.h" + +//#define LOG_NDEBUG 0 + +#undef LOG_TAG +#define LOG_TAG "HWC2On1Adapter" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#define VA_ROTATION_CONFIG_FLAG (1ULL << 10) +#define IS_VA_ROTATION_CONFIG(config) ((config & VA_ROTATION_CONFIG_FLAG) != 0) + +#include + +#include +#include +#include + +#include +#include +#include + +using namespace std::chrono_literals; + +static uint8_t getMinorVersion(struct hwc_composer_device_1* device) +{ + auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; + return (version >> 16) & 0xF; +} + +template +static hwc2_function_pointer_t asFP(T function) +{ + static_assert(std::is_same::value, "Incompatible function pointer"); + return reinterpret_cast(function); +} + +using namespace HWC2; + +static constexpr Attribute ColorMode = static_cast(6); + +namespace android { + +class HWC2On1Adapter::Callbacks : public hwc_procs_t { + public: + explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) { + invalidate = &invalidateHook; + vsync = &vsyncHook; + hotplug = &hotplugHook; + } + + static void invalidateHook(const hwc_procs_t* procs) { + auto callbacks = static_cast(procs); + callbacks->mAdapter.hwc1Invalidate(); + } + + static void vsyncHook(const hwc_procs_t* procs, int display, + int64_t timestamp) { + auto callbacks = static_cast(procs); + callbacks->mAdapter.hwc1Vsync(display, timestamp); + } + + static void hotplugHook(const hwc_procs_t* procs, int display, + int connected) { + auto callbacks = static_cast(procs); + callbacks->mAdapter.hwc1Hotplug(display, connected); + } + + private: + HWC2On1Adapter& mAdapter; +}; + +static int closeHook(hw_device_t* /*device*/) +{ + // Do nothing, since the real work is done in the class destructor, but we + // need to provide a valid function pointer for hwc2_close to call + return 0; +} + +HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device) + : mDumpString(), + mHwc1Device(hwc1Device), + mHwc1MinorVersion(getMinorVersion(hwc1Device)), + mHwc1SupportsVirtualDisplays(false), + mHwc1SupportsBackgroundColor(false), + mHwc1Callbacks(std::make_unique(*this)), + mCapabilities(), + mLayers(), + mHwc1VirtualDisplay(), + mStateMutex(), + mCallbacks(), + mHasPendingInvalidate(false), + mPendingVsyncs(), + mPendingHotplugs(), + mDisplays(), + mHwc1DisplayMap() +{ + common.close = closeHook; + getCapabilities = getCapabilitiesHook; + getFunction = getFunctionHook; + populateCapabilities(); + populatePrimary(); + mHwc1Device->registerProcs(mHwc1Device, + static_cast(mHwc1Callbacks.get())); +} + +HWC2On1Adapter::~HWC2On1Adapter() { + hwc_close_1(mHwc1Device); +} + +void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount, + int32_t* outCapabilities) { + if (outCapabilities == nullptr) { + *outCount = mCapabilities.size(); + return; + } + + auto capabilityIter = mCapabilities.cbegin(); + for (size_t written = 0; written < *outCount; ++written) { + if (capabilityIter == mCapabilities.cend()) { + return; + } + outCapabilities[written] = static_cast(*capabilityIter); + ++capabilityIter; + } +} + +hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( + FunctionDescriptor descriptor) { + switch (descriptor) { + // Device functions + case FunctionDescriptor::CreateVirtualDisplay: + return asFP( + createVirtualDisplayHook); + case FunctionDescriptor::DestroyVirtualDisplay: + return asFP( + destroyVirtualDisplayHook); + case FunctionDescriptor::Dump: + return asFP(dumpHook); + case FunctionDescriptor::GetMaxVirtualDisplayCount: + return asFP( + getMaxVirtualDisplayCountHook); + case FunctionDescriptor::RegisterCallback: + return asFP(registerCallbackHook); + + // Display functions + case FunctionDescriptor::AcceptDisplayChanges: + return asFP( + displayHook); + case FunctionDescriptor::CreateLayer: + return asFP( + displayHook); + case FunctionDescriptor::DestroyLayer: + return asFP( + displayHook); + case FunctionDescriptor::GetActiveConfig: + return asFP( + displayHook); + case FunctionDescriptor::GetChangedCompositionTypes: + return asFP( + displayHook); + case FunctionDescriptor::GetColorModes: + return asFP( + displayHook); + case FunctionDescriptor::GetDisplayAttribute: + return asFP( + getDisplayAttributeHook); + case FunctionDescriptor::GetDisplayConfigs: + return asFP( + displayHook); + case FunctionDescriptor::GetDisplayName: + return asFP( + displayHook); + case FunctionDescriptor::GetDisplayRequests: + return asFP( + displayHook); + case FunctionDescriptor::GetDisplayType: + return asFP( + displayHook); + case FunctionDescriptor::GetDozeSupport: + return asFP( + displayHook); + case FunctionDescriptor::GetHdrCapabilities: + return asFP( + displayHook); + case FunctionDescriptor::GetReleaseFences: + return asFP( + displayHook); + case FunctionDescriptor::PresentDisplay: + return asFP( + displayHook); + case FunctionDescriptor::SetActiveConfig: + return asFP( + displayHook); + case FunctionDescriptor::SetClientTarget: + return asFP( + displayHook); + case FunctionDescriptor::SetColorMode: + return asFP(setColorModeHook); + case FunctionDescriptor::SetColorTransform: + return asFP(setColorTransformHook); + case FunctionDescriptor::SetOutputBuffer: + return asFP( + displayHook); + case FunctionDescriptor::SetPowerMode: + return asFP(setPowerModeHook); + case FunctionDescriptor::SetVsyncEnabled: + return asFP(setVsyncEnabledHook); + case FunctionDescriptor::ValidateDisplay: + return asFP( + displayHook); + case FunctionDescriptor::GetClientTargetSupport: + return asFP( + displayHook); + + // Layer functions + case FunctionDescriptor::SetCursorPosition: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerBuffer: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerSurfaceDamage: + return asFP( + layerHook); + + // Layer state functions + case FunctionDescriptor::SetLayerBlendMode: + return asFP( + setLayerBlendModeHook); + case FunctionDescriptor::SetLayerColor: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerCompositionType: + return asFP( + setLayerCompositionTypeHook); + case FunctionDescriptor::SetLayerDataspace: + return asFP(setLayerDataspaceHook); + case FunctionDescriptor::SetLayerDisplayFrame: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerPlaneAlpha: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerSidebandStream: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerSourceCrop: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerTransform: + return asFP(setLayerTransformHook); + case FunctionDescriptor::SetLayerVisibleRegion: + return asFP( + layerHook); + case FunctionDescriptor::SetLayerZOrder: + return asFP(setLayerZOrderHook); + + default: + ALOGE("doGetFunction: Unknown function descriptor: %d (%s)", + static_cast(descriptor), + to_string(descriptor).c_str()); + return nullptr; + } +} + +// Device functions + +Error HWC2On1Adapter::createVirtualDisplay(uint32_t width, + uint32_t height, hwc2_display_t* outDisplay) { + std::unique_lock lock(mStateMutex); + + if (mHwc1VirtualDisplay) { + // We have already allocated our only HWC1 virtual display + ALOGE("createVirtualDisplay: HWC1 virtual display already allocated"); + return Error::NoResources; + } + + mHwc1VirtualDisplay = std::make_shared(*this, + HWC2::DisplayType::Virtual); + mHwc1VirtualDisplay->populateConfigs(width, height); + const auto displayId = mHwc1VirtualDisplay->getId(); + mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId; + mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL); + mDisplays.emplace(displayId, mHwc1VirtualDisplay); + *outDisplay = displayId; + + return Error::None; +} + +Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) { + std::unique_lock lock(mStateMutex); + + if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) { + return Error::BadDisplay; + } + + mHwc1VirtualDisplay.reset(); + mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL); + mDisplays.erase(displayId); + + return Error::None; +} + +void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) { + if (outBuffer != nullptr) { + auto copiedBytes = mDumpString.copy(outBuffer, *outSize); + *outSize = static_cast(copiedBytes); + return; + } + + std::stringstream output; + + output << "-- HWC2On1Adapter --\n"; + + output << "Adapting to a HWC 1." << static_cast(mHwc1MinorVersion) << + " device\n"; + + // Attempt to acquire the lock for 1 second, but proceed without the lock + // after that, so we can still get some information if we're deadlocked + std::unique_lock lock(mStateMutex, + std::defer_lock); + lock.try_lock_for(1s); + + if (mCapabilities.empty()) { + output << "Capabilities: None\n"; + } else { + output << "Capabilities:\n"; + for (auto capability : mCapabilities) { + output << " " << to_string(capability) << '\n'; + } + } + + output << "Displays:\n"; + for (const auto& element : mDisplays) { + const auto& display = element.second; + output << display->dump(); + } + output << '\n'; + + // Release the lock before calling into HWC1, and since we no longer require + // mutual exclusion to access mCapabilities or mDisplays + lock.unlock(); + + if (mHwc1Device->dump) { + output << "HWC1 dump:\n"; + std::vector hwc1Dump(4096); + // Call with size - 1 to preserve a null character at the end + mHwc1Device->dump(mHwc1Device, hwc1Dump.data(), + static_cast(hwc1Dump.size() - 1)); + output << hwc1Dump.data(); + } + + mDumpString = output.str(); + *outSize = static_cast(mDumpString.size()); +} + +uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() { + return mHwc1SupportsVirtualDisplays ? 1 : 0; +} + +static bool isValid(Callback descriptor) { + switch (descriptor) { + case Callback::Hotplug: // Fall-through + case Callback::Refresh: // Fall-through + case Callback::Vsync: return true; + default: return false; + } +} + +Error HWC2On1Adapter::registerCallback(Callback descriptor, + hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { + if (!isValid(descriptor)) { + return Error::BadParameter; + } + + ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(), + callbackData, pointer); + + std::unique_lock lock(mStateMutex); + + if (pointer != nullptr) { + mCallbacks[descriptor] = {callbackData, pointer}; + } else { + ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str()); + mCallbacks.erase(descriptor); + return Error::None; + } + + bool hasPendingInvalidate = false; + std::vector displayIds; + std::vector> pendingVsyncs; + std::vector> pendingHotplugs; + + if (descriptor == Callback::Refresh) { + hasPendingInvalidate = mHasPendingInvalidate; + if (hasPendingInvalidate) { + for (auto& displayPair : mDisplays) { + displayIds.emplace_back(displayPair.first); + } + } + mHasPendingInvalidate = false; + } else if (descriptor == Callback::Vsync) { + for (auto pending : mPendingVsyncs) { + auto hwc1DisplayId = pending.first; + if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { + ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", + hwc1DisplayId); + continue; + } + auto displayId = mHwc1DisplayMap[hwc1DisplayId]; + auto timestamp = pending.second; + pendingVsyncs.emplace_back(displayId, timestamp); + } + mPendingVsyncs.clear(); + } else if (descriptor == Callback::Hotplug) { + // Hotplug the primary display + pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY], + static_cast(Connection::Connected)); + + for (auto pending : mPendingHotplugs) { + auto hwc1DisplayId = pending.first; + if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { + ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d", + hwc1DisplayId); + continue; + } + auto displayId = mHwc1DisplayMap[hwc1DisplayId]; + auto connected = pending.second; + pendingHotplugs.emplace_back(displayId, connected); + } + } + + // Call pending callbacks without the state lock held + lock.unlock(); + + if (hasPendingInvalidate) { + auto refresh = reinterpret_cast(pointer); + for (auto displayId : displayIds) { + refresh(callbackData, displayId); + } + } + if (!pendingVsyncs.empty()) { + auto vsync = reinterpret_cast(pointer); + for (auto& pendingVsync : pendingVsyncs) { + vsync(callbackData, pendingVsync.first, pendingVsync.second); + } + } + if (!pendingHotplugs.empty()) { + auto hotplug = reinterpret_cast(pointer); + for (auto& pendingHotplug : pendingHotplugs) { + hotplug(callbackData, pendingHotplug.first, pendingHotplug.second); + } + } + return Error::None; +} + +// Display functions + +std::atomic HWC2On1Adapter::Display::sNextId(1); + +HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type) + : mId(sNextId++), + mDevice(device), + mStateMutex(), + mHwc1RequestedContents(nullptr), + mRetireFence(), + mChanges(), + mHwc1Id(-1), + mConfigs(), + mActiveConfig(nullptr), + mActiveColorMode(static_cast(-1)), + mName(), + mType(type), + mPowerMode(PowerMode::Off), + mVsyncEnabled(Vsync::Invalid), + mClientTarget(), + mOutputBuffer(), + mHasColorTransform(false), + mLayers(), + mHwc1LayerMap(), + mNumAvailableRects(0), + mNextAvailableRect(nullptr), + mGeometryChanged(false) + {} + +Error HWC2On1Adapter::Display::acceptChanges() { + std::unique_lock lock(mStateMutex); + + if (!mChanges) { + ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId); + return Error::NotValidated; + } + + ALOGV("[%" PRIu64 "] acceptChanges", mId); + + for (auto& change : mChanges->getTypeChanges()) { + auto layerId = change.first; + auto type = change.second; + if (mDevice.mLayers.count(layerId) == 0) { + // This should never happen but somehow does. + ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")", + layerId); + continue; + } + auto layer = mDevice.mLayers[layerId]; + layer->setCompositionType(type); + } + + mChanges->clearTypeChanges(); + + return Error::None; +} + +Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) { + std::unique_lock lock(mStateMutex); + + auto layer = *mLayers.emplace(std::make_shared(*this)); + mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer)); + *outLayerId = layer->getId(); + ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId); + markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) { + std::unique_lock lock(mStateMutex); + + const auto mapLayer = mDevice.mLayers.find(layerId); + if (mapLayer == mDevice.mLayers.end()) { + ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", + mId, layerId); + return Error::BadLayer; + } + const auto layer = mapLayer->second; + mDevice.mLayers.erase(mapLayer); + const auto zRange = mLayers.equal_range(layer); + for (auto current = zRange.first; current != zRange.second; ++current) { + if (**current == *layer) { + current = mLayers.erase(current); + break; + } + } + ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId); + markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) { + std::unique_lock lock(mStateMutex); + + if (!mActiveConfig) { + ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId, + to_string(Error::BadConfig).c_str()); + return Error::BadConfig; + } + auto configId = mActiveConfig->getId(); + ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId); + *outConfig = configId; + return Error::None; +} + +Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId, + Attribute attribute, int32_t* outValue) { + std::unique_lock lock(mStateMutex); + + if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { + ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId, + configId); + return Error::BadConfig; + } + *outValue = mConfigs[configId]->getAttribute(attribute); + ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId, + to_string(attribute).c_str(), *outValue); + return Error::None; +} + +Error HWC2On1Adapter::Display::getChangedCompositionTypes( + uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) { + std::unique_lock lock(mStateMutex); + + if (!mChanges) { + ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated", + mId); + return Error::NotValidated; + } + + if ((outLayers == nullptr) || (outTypes == nullptr)) { + *outNumElements = mChanges->getTypeChanges().size(); + return Error::None; + } + + uint32_t numWritten = 0; + for (const auto& element : mChanges->getTypeChanges()) { + if (numWritten == *outNumElements) { + break; + } + auto layerId = element.first; + auto intType = static_cast(element.second); + ALOGV("Adding %" PRIu64 " %s", layerId, + to_string(element.second).c_str()); + outLayers[numWritten] = layerId; + outTypes[numWritten] = intType; + ++numWritten; + } + *outNumElements = numWritten; + + return Error::None; +} + +Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, + int32_t* outModes) { + std::unique_lock lock(mStateMutex); + + if (!outModes) { + *outNumModes = mColorModes.size(); + return Error::None; + } + uint32_t numModes = std::min(*outNumModes, + static_cast(mColorModes.size())); + std::copy_n(mColorModes.cbegin(), numModes, outModes); + *outNumModes = numModes; + return Error::None; +} + +Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, + hwc2_config_t* outConfigs) { + std::unique_lock lock(mStateMutex); + + if (!outConfigs) { + *outNumConfigs = mConfigs.size(); + return Error::None; + } + uint32_t numWritten = 0; + for (const auto& config : mConfigs) { + if (numWritten == *outNumConfigs) { + break; + } + outConfigs[numWritten] = config->getId(); + ++numWritten; + } + *outNumConfigs = numWritten; + return Error::None; +} + +Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) { + std::unique_lock lock(mStateMutex); + + if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) { + *outSupport = 0; + } else { + *outSupport = 1; + } + return Error::None; +} + +Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes, + int32_t* /*outTypes*/, float* /*outMaxLuminance*/, + float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) { + // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0 + *outNumTypes = 0; + return Error::None; +} + +Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) { + std::unique_lock lock(mStateMutex); + + if (!outName) { + *outSize = mName.size(); + return Error::None; + } + auto numCopied = mName.copy(outName, *outSize); + *outSize = numCopied; + return Error::None; +} + +Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements, + hwc2_layer_t* outLayers, int32_t* outFences) { + std::unique_lock lock(mStateMutex); + + uint32_t numWritten = 0; + bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr); + for (const auto& layer : mLayers) { + if (outputsNonNull && (numWritten == *outNumElements)) { + break; + } + + auto releaseFence = layer->getReleaseFence(); + if (releaseFence != MiniFence::NO_FENCE) { + if (outputsNonNull) { + outLayers[numWritten] = layer->getId(); + outFences[numWritten] = releaseFence->dup(); + } + ++numWritten; + } + } + *outNumElements = numWritten; + + return Error::None; +} + +Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests, + uint32_t* outNumElements, hwc2_layer_t* outLayers, + int32_t* outLayerRequests) { + std::unique_lock lock(mStateMutex); + + if (!mChanges) { + return Error::NotValidated; + } + + if (outLayers == nullptr || outLayerRequests == nullptr) { + *outNumElements = mChanges->getNumLayerRequests(); + return Error::None; + } + + // Display requests (HWC2::DisplayRequest) are not supported by hwc1: + // A hwc1 has always zero requests for the client. + *outDisplayRequests = 0; + + uint32_t numWritten = 0; + for (const auto& request : mChanges->getLayerRequests()) { + if (numWritten == *outNumElements) { + break; + } + outLayers[numWritten] = request.first; + outLayerRequests[numWritten] = static_cast(request.second); + ++numWritten; + } + + return Error::None; +} + +Error HWC2On1Adapter::Display::getType(int32_t* outType) { + std::unique_lock lock(mStateMutex); + + *outType = static_cast(mType); + return Error::None; +} + +Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) { + std::unique_lock lock(mStateMutex); + + if (mChanges) { + Error error = mDevice.setAllDisplays(); + if (error != Error::None) { + ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId, + to_string(error).c_str()); + return error; + } + } + + *outRetireFence = mRetireFence.get()->dup(); + ALOGV("[%" PRIu64 "] present returning retire fence %d", mId, + *outRetireFence); + + return Error::None; +} + +Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) { + std::unique_lock lock(mStateMutex); + + if (IS_VA_ROTATION_CONFIG(configId)) { + int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, + mHwc1Id, static_cast(configId)); + if (intError != 0) { + ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)", + intError); + return Error::BadConfig; + } + return Error::None; + } + + auto config = getConfig(configId); + if (!config) { + return Error::BadConfig; + } + if (config == mActiveConfig) { + return Error::None; + } + + if (mDevice.mHwc1MinorVersion >= 4) { + uint32_t hwc1Id = 0; + auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id); + if (error != Error::None) { + return error; + } + + int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, + mHwc1Id, static_cast(hwc1Id)); + if (intError != 0) { + ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)", + intError); + return Error::BadConfig; + } + mActiveConfig = config; + } + + return Error::None; +} + +Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, + int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) { + std::unique_lock lock(mStateMutex); + + ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence); + mClientTarget.setBuffer(target); + mClientTarget.setFence(acquireFence); + // dataspace and damage can't be used by HWC1, so ignore them + return Error::None; +} + +Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) { + std::unique_lock lock (mStateMutex); + + ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode); + + if (mode == mActiveColorMode) { + return Error::None; + } + if (mColorModes.count(mode) == 0) { + ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode); + return Error::Unsupported; + } + + if (mDevice.mHwc1MinorVersion >= 4) { + uint32_t hwc1Config = 0; + auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config); + if (error != Error::None) { + return error; + } + + ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config); + int intError = + mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, hwc1Config); + if (intError != 0) { + ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError); + return Error::Unsupported; + } + } + + mActiveColorMode = mode; + return Error::None; +} + +Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) { + std::unique_lock lock(mStateMutex); + + ALOGV("%" PRIu64 "] setColorTransform(%d)", mId, + static_cast(hint)); + mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY); + return Error::None; +} + +Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer, + int32_t releaseFence) { + std::unique_lock lock(mStateMutex); + + ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence); + mOutputBuffer.setBuffer(buffer); + mOutputBuffer.setFence(releaseFence); + return Error::None; +} + +static bool isValid(PowerMode mode) { + switch (mode) { + case PowerMode::Off: // Fall-through + case PowerMode::DozeSuspend: // Fall-through + case PowerMode::Doze: // Fall-through + case PowerMode::On: return true; + } +} + +static int getHwc1PowerMode(PowerMode mode) { + switch (mode) { + case PowerMode::Off: return HWC_POWER_MODE_OFF; + case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND; + case PowerMode::Doze: return HWC_POWER_MODE_DOZE; + case PowerMode::On: return HWC_POWER_MODE_NORMAL; + } +} + +Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) { + if (!isValid(mode)) { + return Error::BadParameter; + } + if (mode == mPowerMode) { + return Error::None; + } + + std::unique_lock lock(mStateMutex); + + int error = 0; + if (mDevice.mHwc1MinorVersion < 4) { + error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id, + mode == PowerMode::Off); + } else { + error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device, + mHwc1Id, getHwc1PowerMode(mode)); + } + ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)", + error); + + ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str()); + mPowerMode = mode; + return Error::None; +} + +static bool isValid(Vsync enable) { + switch (enable) { + case Vsync::Enable: // Fall-through + case Vsync::Disable: return true; + case Vsync::Invalid: return false; + } +} + +Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) { + if (!isValid(enable)) { + return Error::BadParameter; + } + if (enable == mVsyncEnabled) { + return Error::None; + } + + std::unique_lock lock(mStateMutex); + + int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device, + mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable); + ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)", + error); + + mVsyncEnabled = enable; + return Error::None; +} + +Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes, + uint32_t* outNumRequests) { + std::unique_lock lock(mStateMutex); + + if (!mChanges) { + if (!mDevice.prepareAllDisplays()) { + return Error::BadDisplay; + } + } else { + ALOGE("Validate was called more than once!"); + } + + *outNumTypes = mChanges->getNumTypes(); + *outNumRequests = mChanges->getNumLayerRequests(); + ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes, + *outNumRequests); + for (auto request : mChanges->getTypeChanges()) { + ALOGV("Layer %" PRIu64 " --> %s", request.first, + to_string(request.second).c_str()); + } + return *outNumTypes > 0 ? Error::HasChanges : Error::None; +} + +Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) { + std::unique_lock lock(mStateMutex); + + const auto mapLayer = mDevice.mLayers.find(layerId); + if (mapLayer == mDevice.mLayers.end()) { + ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId); + return Error::BadLayer; + } + + const auto layer = mapLayer->second; + const auto zRange = mLayers.equal_range(layer); + bool layerOnDisplay = false; + for (auto current = zRange.first; current != zRange.second; ++current) { + if (**current == *layer) { + if ((*current)->getZ() == z) { + // Don't change anything if the Z hasn't changed + return Error::None; + } + current = mLayers.erase(current); + layerOnDisplay = true; + break; + } + } + + if (!layerOnDisplay) { + ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", + mId); + return Error::BadLayer; + } + + layer->setZ(z); + mLayers.emplace(std::move(layer)); + markGeometryChanged(); + + return Error::None; +} + +Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height, + int32_t format, int32_t dataspace){ + if (mActiveConfig == nullptr) { + return Error::Unsupported; + } + + if (width == mActiveConfig->getAttribute(Attribute::Width) && + height == mActiveConfig->getAttribute(Attribute::Height) && + format == HAL_PIXEL_FORMAT_RGBA_8888 && + dataspace == HAL_DATASPACE_UNKNOWN) { + return Error::None; + } + + return Error::Unsupported; +} + +static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = { + HWC_DISPLAY_VSYNC_PERIOD, + HWC_DISPLAY_WIDTH, + HWC_DISPLAY_HEIGHT, + HWC_DISPLAY_DPI_X, + HWC_DISPLAY_DPI_Y, + HWC_DISPLAY_COLOR_TRANSFORM, + HWC_DISPLAY_NO_ATTRIBUTE, +}; + +static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = { + HWC_DISPLAY_VSYNC_PERIOD, + HWC_DISPLAY_WIDTH, + HWC_DISPLAY_HEIGHT, + HWC_DISPLAY_DPI_X, + HWC_DISPLAY_DPI_Y, + HWC_DISPLAY_NO_ATTRIBUTE, +}; + +static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR = + sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t); +static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR), + "Attribute tables have unexpected sizes"); + +static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = { + 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0 + 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, + 1, // HWC_DISPLAY_WIDTH = 2, + 2, // HWC_DISPLAY_HEIGHT = 3, + 3, // HWC_DISPLAY_DPI_X = 4, + 4, // HWC_DISPLAY_DPI_Y = 5, + 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6, +}; + +static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = { + 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0 + 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, + 1, // HWC_DISPLAY_WIDTH = 2, + 2, // HWC_DISPLAY_HEIGHT = 3, + 3, // HWC_DISPLAY_DPI_X = 4, + 4, // HWC_DISPLAY_DPI_Y = 5, +}; + +template +static constexpr bool attributesMatch() +{ + bool match = (attribute == + ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]); + if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) { + return match; + } + + return match && (attribute == + ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]); +} +static_assert(attributesMatch(), + "Tables out of sync"); +static_assert(attributesMatch(), "Tables out of sync"); +static_assert(attributesMatch(), "Tables out of sync"); +static_assert(attributesMatch(), "Tables out of sync"); +static_assert(attributesMatch(), "Tables out of sync"); +static_assert(attributesMatch(), + "Tables out of sync"); + +void HWC2On1Adapter::Display::populateConfigs() { + std::unique_lock lock(mStateMutex); + + ALOGV("[%" PRIu64 "] populateConfigs", mId); + + if (mHwc1Id == -1) { + ALOGE("populateConfigs: HWC1 ID not set"); + return; + } + + const size_t MAX_NUM_CONFIGS = 128; + uint32_t configs[MAX_NUM_CONFIGS] = {}; + size_t numConfigs = MAX_NUM_CONFIGS; + mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id, + configs, &numConfigs); + + for (size_t c = 0; c < numConfigs; ++c) { + uint32_t hwc1ConfigId = configs[c]; + auto newConfig = std::make_shared(*this); + + int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {}; + bool hasColor = true; + auto result = mDevice.mHwc1Device->getDisplayAttributes( + mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, + ATTRIBUTES_WITH_COLOR, values); + if (result != 0) { + mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, + mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values); + hasColor = false; + } + + auto attributeMap = hasColor ? + ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR; + + newConfig->setAttribute(Attribute::VsyncPeriod, + values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]); + newConfig->setAttribute(Attribute::Width, + values[attributeMap[HWC_DISPLAY_WIDTH]]); + newConfig->setAttribute(Attribute::Height, + values[attributeMap[HWC_DISPLAY_HEIGHT]]); + newConfig->setAttribute(Attribute::DpiX, + values[attributeMap[HWC_DISPLAY_DPI_X]]); + newConfig->setAttribute(Attribute::DpiY, + values[attributeMap[HWC_DISPLAY_DPI_Y]]); + if (hasColor) { + // In HWC1, color modes are referred to as color transforms. To avoid confusion with + // the HWC2 concept of color transforms, we internally refer to them as color modes for + // both HWC1 and 2. + newConfig->setAttribute(ColorMode, + values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]); + } + + // We can only do this after attempting to read the color mode + newConfig->setHwc1Id(hwc1ConfigId); + + for (auto& existingConfig : mConfigs) { + if (existingConfig->merge(*newConfig)) { + ALOGV("Merged config %d with existing config %u: %s", + hwc1ConfigId, existingConfig->getId(), + existingConfig->toString().c_str()); + newConfig.reset(); + break; + } + } + + // If it wasn't merged with any existing config, add it to the end + if (newConfig) { + newConfig->setId(static_cast(mConfigs.size())); + ALOGV("Found new config %u: %s", newConfig->getId(), + newConfig->toString().c_str()); + mConfigs.emplace_back(std::move(newConfig)); + } + } + + initializeActiveConfig(); + populateColorModes(); +} + +void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) { + std::unique_lock lock(mStateMutex); + + mConfigs.emplace_back(std::make_shared(*this)); + auto& config = mConfigs[0]; + + config->setAttribute(Attribute::Width, static_cast(width)); + config->setAttribute(Attribute::Height, static_cast(height)); + config->setHwc1Id(0); + config->setId(0); + mActiveConfig = config; +} + +bool HWC2On1Adapter::Display::prepare() { + std::unique_lock lock(mStateMutex); + + // Only prepare display contents for displays HWC1 knows about + if (mHwc1Id == -1) { + return true; + } + + // It doesn't make sense to prepare a display for which there is no active + // config, so return early + if (!mActiveConfig) { + ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId); + return false; + } + + allocateRequestedContents(); + assignHwc1LayerIds(); + + mHwc1RequestedContents->retireFenceFd = -1; + mHwc1RequestedContents->flags = 0; + if (mGeometryChanged) { + mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED; + } + mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer(); + mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence(); + + // +1 is for framebuffer target layer. + mHwc1RequestedContents->numHwLayers = mLayers.size() + 1; + for (auto& layer : mLayers) { + auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()]; + hwc1Layer.releaseFenceFd = -1; + hwc1Layer.acquireFenceFd = -1; + ALOGV("Applying states for layer %" PRIu64 " ", layer->getId()); + layer->applyState(hwc1Layer); + } + + prepareFramebufferTarget(); + + resetGeometryMarker(); + + return true; +} + +void HWC2On1Adapter::Display::generateChanges() { + std::unique_lock lock(mStateMutex); + + mChanges.reset(new Changes); + + size_t numLayers = mHwc1RequestedContents->numHwLayers; + for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { + const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id]; + if (mHwc1LayerMap.count(hwc1Id) == 0) { + ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET, + "generateChanges: HWC1 layer %zd doesn't have a" + " matching HWC2 layer, and isn't the framebuffer target", + hwc1Id); + continue; + } + + Layer& layer = *mHwc1LayerMap[hwc1Id]; + updateTypeChanges(receivedLayer, layer); + updateLayerRequests(receivedLayer, layer); + } +} + +bool HWC2On1Adapter::Display::hasChanges() const { + std::unique_lock lock(mStateMutex); + return mChanges != nullptr; +} + +Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) { + std::unique_lock lock(mStateMutex); + + if (!mChanges || (mChanges->getNumTypes() > 0)) { + ALOGE("[%" PRIu64 "] set failed: not validated", mId); + return Error::NotValidated; + } + + // Set up the client/framebuffer target + auto numLayers = hwcContents.numHwLayers; + + // Close acquire fences on FRAMEBUFFER layers, since they will not be used + // by HWC + for (size_t l = 0; l < numLayers - 1; ++l) { + auto& layer = hwcContents.hwLayers[l]; + if (layer.compositionType == HWC_FRAMEBUFFER) { + ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l); + close(layer.acquireFenceFd); + layer.acquireFenceFd = -1; + } + } + + auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1]; + if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) { + clientTargetLayer.handle = mClientTarget.getBuffer(); + clientTargetLayer.acquireFenceFd = mClientTarget.getFence(); + } else { + ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET", + mId); + } + + mChanges.reset(); + + return Error::None; +} + +void HWC2On1Adapter::Display::addRetireFence(int fenceFd) { + std::unique_lock lock(mStateMutex); + mRetireFence.add(fenceFd); +} + +void HWC2On1Adapter::Display::addReleaseFences( + const hwc_display_contents_1_t& hwcContents) { + std::unique_lock lock(mStateMutex); + + size_t numLayers = hwcContents.numHwLayers; + for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { + const auto& receivedLayer = hwcContents.hwLayers[hwc1Id]; + if (mHwc1LayerMap.count(hwc1Id) == 0) { + if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) { + ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a" + " matching HWC2 layer, and isn't the framebuffer" + " target", hwc1Id); + } + // Close the framebuffer target release fence since we will use the + // display retire fence instead + if (receivedLayer.releaseFenceFd != -1) { + close(receivedLayer.releaseFenceFd); + } + continue; + } + + Layer& layer = *mHwc1LayerMap[hwc1Id]; + ALOGV("Adding release fence %d to layer %" PRIu64, + receivedLayer.releaseFenceFd, layer.getId()); + layer.addReleaseFence(receivedLayer.releaseFenceFd); + } +} + +bool HWC2On1Adapter::Display::hasColorTransform() const { + std::unique_lock lock(mStateMutex); + return mHasColorTransform; +} + +static std::string hwc1CompositionString(int32_t type) { + switch (type) { + case HWC_FRAMEBUFFER: return "Framebuffer"; + case HWC_OVERLAY: return "Overlay"; + case HWC_BACKGROUND: return "Background"; + case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget"; + case HWC_SIDEBAND: return "Sideband"; + case HWC_CURSOR_OVERLAY: return "CursorOverlay"; + default: + return std::string("Unknown (") + std::to_string(type) + ")"; + } +} + +static std::string hwc1TransformString(int32_t transform) { + switch (transform) { + case 0: return "None"; + case HWC_TRANSFORM_FLIP_H: return "FlipH"; + case HWC_TRANSFORM_FLIP_V: return "FlipV"; + case HWC_TRANSFORM_ROT_90: return "Rotate90"; + case HWC_TRANSFORM_ROT_180: return "Rotate180"; + case HWC_TRANSFORM_ROT_270: return "Rotate270"; + case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90"; + case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90"; + default: + return std::string("Unknown (") + std::to_string(transform) + ")"; + } +} + +static std::string hwc1BlendModeString(int32_t mode) { + switch (mode) { + case HWC_BLENDING_NONE: return "None"; + case HWC_BLENDING_PREMULT: return "Premultiplied"; + case HWC_BLENDING_COVERAGE: return "Coverage"; + default: + return std::string("Unknown (") + std::to_string(mode) + ")"; + } +} + +static std::string rectString(hwc_rect_t rect) { + std::stringstream output; + output << "[" << rect.left << ", " << rect.top << ", "; + output << rect.right << ", " << rect.bottom << "]"; + return output.str(); +} + +static std::string approximateFloatString(float f) { + if (static_cast(static_cast(f)) == f) { + return std::to_string(static_cast(f)); + } + int32_t truncated = static_cast(f * 10); + bool approximate = (static_cast(truncated) != f * 10); + const size_t BUFFER_SIZE = 32; + char buffer[BUFFER_SIZE] = {}; + auto bytesWritten = snprintf(buffer, BUFFER_SIZE, + "%s%.1f", approximate ? "~" : "", f); + return std::string(buffer, bytesWritten); +} + +static std::string frectString(hwc_frect_t frect) { + std::stringstream output; + output << "[" << approximateFloatString(frect.left) << ", "; + output << approximateFloatString(frect.top) << ", "; + output << approximateFloatString(frect.right) << ", "; + output << approximateFloatString(frect.bottom) << "]"; + return output.str(); +} + +static std::string colorString(hwc_color_t color) { + std::stringstream output; + output << "RGBA ["; + output << static_cast(color.r) << ", "; + output << static_cast(color.g) << ", "; + output << static_cast(color.b) << ", "; + output << static_cast(color.a) << "]"; + return output.str(); +} + +static std::string alphaString(float f) { + const size_t BUFFER_SIZE = 8; + char buffer[BUFFER_SIZE] = {}; + auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f); + return std::string(buffer, bytesWritten); +} + +static std::string to_string(const hwc_layer_1_t& hwcLayer, + int32_t hwc1MinorVersion) { + const char* fill = " "; + + std::stringstream output; + + output << " Composition: " << + hwc1CompositionString(hwcLayer.compositionType); + + if (hwcLayer.compositionType == HWC_BACKGROUND) { + output << " Color: " << colorString(hwcLayer.backgroundColor) << '\n'; + } else if (hwcLayer.compositionType == HWC_SIDEBAND) { + output << " Stream: " << hwcLayer.sidebandStream << '\n'; + } else { + output << " Buffer: " << hwcLayer.handle << "/" << + hwcLayer.acquireFenceFd << '\n'; + } + + output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) << + '\n'; + + output << fill << "Source crop: "; + if (hwc1MinorVersion >= 3) { + output << frectString(hwcLayer.sourceCropf) << '\n'; + } else { + output << rectString(hwcLayer.sourceCropi) << '\n'; + } + + output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform); + output << " Blend mode: " << hwc1BlendModeString(hwcLayer.blending); + if (hwcLayer.planeAlpha != 0xFF) { + output << " Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f); + } + output << '\n'; + + if (hwcLayer.hints != 0) { + output << fill << "Hints:"; + if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) { + output << " TripleBuffer"; + } + if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) { + output << " ClearFB"; + } + output << '\n'; + } + + if (hwcLayer.flags != 0) { + output << fill << "Flags:"; + if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) { + output << " SkipLayer"; + } + if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) { + output << " IsCursorLayer"; + } + output << '\n'; + } + + return output.str(); +} + +static std::string to_string(const hwc_display_contents_1_t& hwcContents, + int32_t hwc1MinorVersion) { + const char* fill = " "; + + std::stringstream output; + output << fill << "Geometry changed: " << + ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n"); + + output << fill << hwcContents.numHwLayers << " Layer" << + ((hwcContents.numHwLayers == 1) ? "\n" : "s\n"); + for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) { + output << fill << " Layer " << layer; + output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion); + } + + if (hwcContents.outbuf != nullptr) { + output << fill << "Output buffer: " << hwcContents.outbuf << "/" << + hwcContents.outbufAcquireFenceFd << '\n'; + } + + return output.str(); +} + +std::string HWC2On1Adapter::Display::dump() const { + std::unique_lock lock(mStateMutex); + + std::stringstream output; + + output << " Display " << mId << ": "; + output << to_string(mType) << " "; + output << "HWC1 ID: " << mHwc1Id << " "; + output << "Power mode: " << to_string(mPowerMode) << " "; + output << "Vsync: " << to_string(mVsyncEnabled) << '\n'; + + output << " Color modes [active]:"; + for (const auto& mode : mColorModes) { + if (mode == mActiveColorMode) { + output << " [" << mode << ']'; + } else { + output << " " << mode; + } + } + output << '\n'; + + output << " " << mConfigs.size() << " Config" << + (mConfigs.size() == 1 ? "" : "s") << " (* active)\n"; + for (const auto& config : mConfigs) { + output << (config == mActiveConfig ? " * " : " "); + output << config->toString(true) << '\n'; + } + + output << " " << mLayers.size() << " Layer" << + (mLayers.size() == 1 ? "" : "s") << '\n'; + for (const auto& layer : mLayers) { + output << layer->dump(); + } + + output << " Client target: " << mClientTarget.getBuffer() << '\n'; + + if (mOutputBuffer.getBuffer() != nullptr) { + output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n'; + } + + if (mHwc1RequestedContents) { + output << " Last requested HWC1 state\n"; + output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion); + } + + return output.str(); +} + +hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) { + if (numRects == 0) { + return nullptr; + } + + if (numRects > mNumAvailableRects) { + // This should NEVER happen since we calculated how many rects the + // display would need. + ALOGE("Rect allocation failure! SF is likely to crash soon!"); + return nullptr; + + } + hwc_rect_t* rects = mNextAvailableRect; + mNextAvailableRect += numRects; + mNumAvailableRects -= numRects; + return rects; +} + +hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() { + return mHwc1RequestedContents.get(); +} + +void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute, + int32_t value) { + mAttributes[attribute] = value; +} + +int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const { + if (mAttributes.count(attribute) == 0) { + return -1; + } + return mAttributes.at(attribute); +} + +void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { + android_color_mode_t colorMode = static_cast(getAttribute(ColorMode)); + mHwc1Ids.emplace(colorMode, id); +} + +bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const { + for (const auto& idPair : mHwc1Ids) { + if (id == idPair.second) { + return true; + } + } + return false; +} + +Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( + uint32_t id, android_color_mode_t* outMode) const { + for (const auto& idPair : mHwc1Ids) { + if (id == idPair.second) { + *outMode = idPair.first; + return Error::None; + } + } + ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId); + return Error::BadParameter; +} + +Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode, + uint32_t* outId) const { + for (const auto& idPair : mHwc1Ids) { + if (mode == idPair.first) { + *outId = idPair.second; + return Error::None; + } + } + ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId); + return Error::BadParameter; +} + +bool HWC2On1Adapter::Display::Config::merge(const Config& other) { + auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height, + HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX, + HWC2::Attribute::DpiY}; + for (auto attribute : attributes) { + if (getAttribute(attribute) != other.getAttribute(attribute)) { + return false; + } + } + android_color_mode_t otherColorMode = + static_cast(other.getAttribute(ColorMode)); + if (mHwc1Ids.count(otherColorMode) != 0) { + ALOGE("Attempted to merge two configs (%u and %u) which appear to be " + "identical", mHwc1Ids.at(otherColorMode), + other.mHwc1Ids.at(otherColorMode)); + return false; + } + mHwc1Ids.emplace(otherColorMode, + other.mHwc1Ids.at(otherColorMode)); + return true; +} + +std::set HWC2On1Adapter::Display::Config::getColorModes() const { + std::set colorModes; + for (const auto& idPair : mHwc1Ids) { + colorModes.emplace(idPair.first); + } + return colorModes; +} + +std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const { + std::string output; + + const size_t BUFFER_SIZE = 100; + char buffer[BUFFER_SIZE] = {}; + auto writtenBytes = snprintf(buffer, BUFFER_SIZE, + "%u x %u", mAttributes.at(HWC2::Attribute::Width), + mAttributes.at(HWC2::Attribute::Height)); + output.append(buffer, writtenBytes); + + if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) { + std::memset(buffer, 0, BUFFER_SIZE); + writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz", + 1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod)); + output.append(buffer, writtenBytes); + } + + if (mAttributes.count(HWC2::Attribute::DpiX) != 0 && + mAttributes.at(HWC2::Attribute::DpiX) != -1) { + std::memset(buffer, 0, BUFFER_SIZE); + writtenBytes = + snprintf(buffer, BUFFER_SIZE, ", DPI: %.1f x %.1f", + static_cast(mAttributes.at(HWC2::Attribute::DpiX)) / 1000.0f, + static_cast(mAttributes.at(HWC2::Attribute::DpiY)) / 1000.0f); + output.append(buffer, writtenBytes); + } + + std::memset(buffer, 0, BUFFER_SIZE); + if (splitLine) { + writtenBytes = snprintf(buffer, BUFFER_SIZE, + "\n HWC1 ID/Color transform:"); + } else { + writtenBytes = snprintf(buffer, BUFFER_SIZE, + ", HWC1 ID/Color transform:"); + } + output.append(buffer, writtenBytes); + + + for (const auto& id : mHwc1Ids) { + android_color_mode_t colorMode = id.first; + uint32_t hwc1Id = id.second; + std::memset(buffer, 0, BUFFER_SIZE); + if (colorMode == mDisplay.mActiveColorMode) { + writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id, + colorMode); + } else { + writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id, + colorMode); + } + output.append(buffer, writtenBytes); + } + + return output; +} + +std::shared_ptr + HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const { + if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { + return nullptr; + } + return mConfigs[configId]; +} + +void HWC2On1Adapter::Display::populateColorModes() { + mColorModes = mConfigs[0]->getColorModes(); + for (const auto& config : mConfigs) { + std::set intersection; + auto configModes = config->getColorModes(); + std::set_intersection(mColorModes.cbegin(), mColorModes.cend(), + configModes.cbegin(), configModes.cend(), + std::inserter(intersection, intersection.begin())); + std::swap(intersection, mColorModes); + } +} + +void HWC2On1Adapter::Display::initializeActiveConfig() { + if (mDevice.mHwc1Device->getActiveConfig == nullptr) { + ALOGV("getActiveConfig is null, choosing config 0"); + mActiveConfig = mConfigs[0]; + mActiveColorMode = HAL_COLOR_MODE_NATIVE; + return; + } + + auto activeConfig = mDevice.mHwc1Device->getActiveConfig( + mDevice.mHwc1Device, mHwc1Id); + + // Some devices startup without an activeConfig: + // We need to set one ourselves. + if (activeConfig == HWC_ERROR) { + ALOGV("There is no active configuration: Picking the first one: 0."); + const int defaultIndex = 0; + mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex); + activeConfig = defaultIndex; + } + + for (const auto& config : mConfigs) { + if (config->hasHwc1Id(activeConfig)) { + ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig); + mActiveConfig = config; + if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) { + // This should never happen since we checked for the config's presence before + // setting it as active. + ALOGE("Unable to find color mode for active HWC1 config %d", config->getId()); + mActiveColorMode = HAL_COLOR_MODE_NATIVE; + } + break; + } + } + if (!mActiveConfig) { + ALOGV("Unable to find active HWC1 config %u, defaulting to " + "config 0", activeConfig); + mActiveConfig = mConfigs[0]; + mActiveColorMode = HAL_COLOR_MODE_NATIVE; + } + + + + +} + +void HWC2On1Adapter::Display::allocateRequestedContents() { + // What needs to be allocated: + // 1 hwc_display_contents_1_t + // 1 hwc_layer_1_t for each layer + // 1 hwc_rect_t for each layer's surfaceDamage + // 1 hwc_rect_t for each layer's visibleRegion + // 1 hwc_layer_1_t for the framebuffer + // 1 hwc_rect_t for the framebuffer's visibleRegion + + // Count # of surfaceDamage + size_t numSurfaceDamages = 0; + for (const auto& layer : mLayers) { + numSurfaceDamages += layer->getNumSurfaceDamages(); + } + + // Count # of visibleRegions (start at 1 for mandatory framebuffer target + // region) + size_t numVisibleRegion = 1; + for (const auto& layer : mLayers) { + numVisibleRegion += layer->getNumVisibleRegions(); + } + + size_t numRects = numVisibleRegion + numSurfaceDamages; + auto numLayers = mLayers.size() + 1; + size_t size = sizeof(hwc_display_contents_1_t) + + sizeof(hwc_layer_1_t) * numLayers + + sizeof(hwc_rect_t) * numRects; + auto contents = static_cast(std::calloc(size, 1)); + mHwc1RequestedContents.reset(contents); + mNextAvailableRect = reinterpret_cast(&contents->hwLayers[numLayers]); + mNumAvailableRects = numRects; +} + +void HWC2On1Adapter::Display::assignHwc1LayerIds() { + mHwc1LayerMap.clear(); + size_t nextHwc1Id = 0; + for (auto& layer : mLayers) { + mHwc1LayerMap[nextHwc1Id] = layer; + layer->setHwc1Id(nextHwc1Id++); + } +} + +void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer, + const Layer& layer) { + auto layerId = layer.getId(); + switch (hwc1Layer.compositionType) { + case HWC_FRAMEBUFFER: + if (layer.getCompositionType() != Composition::Client) { + mChanges->addTypeChange(layerId, Composition::Client); + } + break; + case HWC_OVERLAY: + if (layer.getCompositionType() != Composition::Device) { + mChanges->addTypeChange(layerId, Composition::Device); + } + break; + case HWC_BACKGROUND: + ALOGE_IF(layer.getCompositionType() != Composition::SolidColor, + "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2" + " wasn't expecting SolidColor"); + break; + case HWC_FRAMEBUFFER_TARGET: + // Do nothing, since it shouldn't be modified by HWC1 + break; + case HWC_SIDEBAND: + ALOGE_IF(layer.getCompositionType() != Composition::Sideband, + "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2" + " wasn't expecting Sideband"); + break; + case HWC_CURSOR_OVERLAY: + ALOGE_IF(layer.getCompositionType() != Composition::Cursor, + "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but" + " HWC2 wasn't expecting Cursor"); + break; + } +} + +void HWC2On1Adapter::Display::updateLayerRequests( + const hwc_layer_1_t& hwc1Layer, const Layer& layer) { + if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) { + mChanges->addLayerRequest(layer.getId(), + LayerRequest::ClearClientTarget); + } +} + +void HWC2On1Adapter::Display::prepareFramebufferTarget() { + // We check that mActiveConfig is valid in Display::prepare + int32_t width = mActiveConfig->getAttribute(Attribute::Width); + int32_t height = mActiveConfig->getAttribute(Attribute::Height); + + auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()]; + hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET; + hwc1Target.releaseFenceFd = -1; + hwc1Target.hints = 0; + hwc1Target.flags = 0; + hwc1Target.transform = 0; + hwc1Target.blending = HWC_BLENDING_PREMULT; + if (mDevice.getHwc1MinorVersion() < 3) { + hwc1Target.sourceCropi = {0, 0, width, height}; + } else { + hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast(width), + static_cast(height)}; + } + hwc1Target.displayFrame = {0, 0, width, height}; + hwc1Target.planeAlpha = 255; + + hwc1Target.visibleRegionScreen.numRects = 1; + hwc_rect_t* rects = GetRects(1); + rects[0].left = 0; + rects[0].top = 0; + rects[0].right = width; + rects[0].bottom = height; + hwc1Target.visibleRegionScreen.rects = rects; + + // We will set this to the correct value in set + hwc1Target.acquireFenceFd = -1; +} + +// Layer functions + +std::atomic HWC2On1Adapter::Layer::sNextId(1); + +HWC2On1Adapter::Layer::Layer(Display& display) + : mId(sNextId++), + mDisplay(display), + mBuffer(), + mSurfaceDamage(), + mBlendMode(BlendMode::None), + mColor({0, 0, 0, 0}), + mCompositionType(Composition::Invalid), + mDisplayFrame({0, 0, -1, -1}), + mPlaneAlpha(0.0f), + mSidebandStream(nullptr), + mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}), + mTransform(Transform::None), + mVisibleRegion(), + mZ(0), + mReleaseFence(), + mHwc1Id(0), + mHasUnsupportedPlaneAlpha(false) {} + +bool HWC2On1Adapter::SortLayersByZ::operator()(const std::shared_ptr& lhs, + const std::shared_ptr& rhs) const { + return lhs->getZ() < rhs->getZ(); +} + +Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer, + int32_t acquireFence) { + ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId); + mBuffer.setBuffer(buffer); + mBuffer.setFence(acquireFence); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) { + if (mCompositionType != Composition::Cursor) { + return Error::BadLayer; + } + + if (mDisplay.hasChanges()) { + return Error::NotValidated; + } + + auto displayId = mDisplay.getHwc1Id(); + auto hwc1Device = mDisplay.getDevice().getHwc1Device(); + hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) { + // HWC1 supports surface damage starting only with version 1.5. + if (mDisplay.getDevice().mHwc1MinorVersion < 5) { + return Error::None; + } + mSurfaceDamage.resize(damage.numRects); + std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin()); + return Error::None; +} + +// Layer state functions + +Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) { + mBlendMode = mode; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) { + mColor = color; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setCompositionType(Composition type) { + mCompositionType = type; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) { + return Error::None; +} + +Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) { + mDisplayFrame = frame; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) { + mPlaneAlpha = alpha; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) { + mSidebandStream = stream; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) { + mSourceCrop = crop; + mDisplay.markGeometryChanged(); + return Error::None; +} + +Error HWC2On1Adapter::Layer::setTransform(Transform transform) { + mTransform = transform; + mDisplay.markGeometryChanged(); + return Error::None; +} + +static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) { + return rect1.left == rect2.left && + rect1.right == rect2.right && + rect1.top == rect2.top && + rect1.bottom == rect2.bottom; +} + +Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) { + if ((getNumVisibleRegions() != visible.numRects) || + !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects, + compareRects)) { + mVisibleRegion.resize(visible.numRects); + std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin()); + mDisplay.markGeometryChanged(); + } + return Error::None; +} + +Error HWC2On1Adapter::Layer::setZ(uint32_t z) { + mZ = z; + return Error::None; +} + +void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) { + ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId); + mReleaseFence.add(fenceFd); +} + +const sp& HWC2On1Adapter::Layer::getReleaseFence() const { + return mReleaseFence.get(); +} + +void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) { + applyCommonState(hwc1Layer); + applyCompositionType(hwc1Layer); + switch (mCompositionType) { + case Composition::SolidColor : applySolidColorState(hwc1Layer); break; + case Composition::Sideband : applySidebandState(hwc1Layer); break; + default: applyBufferState(hwc1Layer); break; + } +} + +static std::string regionStrings(const std::vector& visibleRegion, + const std::vector& surfaceDamage) { + std::string regions; + regions += " Visible Region"; + regions.resize(40, ' '); + regions += "Surface Damage\n"; + + size_t numPrinted = 0; + size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size()); + while (numPrinted < maxSize) { + std::string line(" "); + if (visibleRegion.empty() && numPrinted == 0) { + line += "None"; + } else if (numPrinted < visibleRegion.size()) { + line += rectString(visibleRegion[numPrinted]); + } + line.resize(40, ' '); + if (surfaceDamage.empty() && numPrinted == 0) { + line += "None"; + } else if (numPrinted < surfaceDamage.size()) { + line += rectString(surfaceDamage[numPrinted]); + } + line += '\n'; + regions += line; + ++numPrinted; + } + return regions; +} + +std::string HWC2On1Adapter::Layer::dump() const { + std::stringstream output; + const char* fill = " "; + + output << fill << to_string(mCompositionType); + output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " "; + output << "Z: " << mZ; + if (mCompositionType == HWC2::Composition::SolidColor) { + output << " " << colorString(mColor); + } else if (mCompositionType == HWC2::Composition::Sideband) { + output << " Handle: " << mSidebandStream << '\n'; + } else { + output << " Buffer: " << mBuffer.getBuffer() << '\n'; + output << fill << " Display frame [LTRB]: " << + rectString(mDisplayFrame) << '\n'; + output << fill << " Source crop: " << + frectString(mSourceCrop) << '\n'; + output << fill << " Transform: " << to_string(mTransform); + output << " Blend mode: " << to_string(mBlendMode); + if (mPlaneAlpha != 1.0f) { + output << " Alpha: " << + alphaString(mPlaneAlpha) << '\n'; + } else { + output << '\n'; + } + output << regionStrings(mVisibleRegion, mSurfaceDamage); + } + return output.str(); +} + +static int getHwc1Blending(HWC2::BlendMode blendMode) { + switch (blendMode) { + case BlendMode::Coverage: return HWC_BLENDING_COVERAGE; + case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT; + default: return HWC_BLENDING_NONE; + } +} + +void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) { + auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion(); + hwc1Layer.blending = getHwc1Blending(mBlendMode); + hwc1Layer.displayFrame = mDisplayFrame; + + auto pendingAlpha = mPlaneAlpha; + if (minorVersion < 2) { + mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f; + } else { + hwc1Layer.planeAlpha = + static_cast(255.0f * pendingAlpha + 0.5f); + } + + if (minorVersion < 3) { + auto pending = mSourceCrop; + hwc1Layer.sourceCropi.left = + static_cast(std::ceil(pending.left)); + hwc1Layer.sourceCropi.top = + static_cast(std::ceil(pending.top)); + hwc1Layer.sourceCropi.right = + static_cast(std::floor(pending.right)); + hwc1Layer.sourceCropi.bottom = + static_cast(std::floor(pending.bottom)); + } else { + hwc1Layer.sourceCropf = mSourceCrop; + } + + hwc1Layer.transform = static_cast(mTransform); + + auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen; + hwc1VisibleRegion.numRects = mVisibleRegion.size(); + hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects); + hwc1VisibleRegion.rects = rects; + for (size_t i = 0; i < mVisibleRegion.size(); i++) { + rects[i] = mVisibleRegion[i]; + } +} + +void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) { + // If the device does not support background color it is likely to make + // assumption regarding backgroundColor and handle (both fields occupy + // the same location in hwc_layer_1_t union). + // To not confuse these devices we don't set background color and we + // make sure handle is a null pointer. + if (hasUnsupportedBackgroundColor()) { + hwc1Layer.handle = nullptr; + } else { + hwc1Layer.backgroundColor = mColor; + } +} + +void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) { + hwc1Layer.sidebandStream = mSidebandStream; +} + +void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) { + hwc1Layer.handle = mBuffer.getBuffer(); + hwc1Layer.acquireFenceFd = mBuffer.getFence(); +} + +void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) { + // HWC1 never supports color transforms or dataspaces and only sometimes + // supports plane alpha (depending on the version). These require us to drop + // some or all layers to client composition. + if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() || + hasUnsupportedBackgroundColor()) { + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags = HWC_SKIP_LAYER; + return; + } + + hwc1Layer.flags = 0; + switch (mCompositionType) { + case Composition::Client: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + break; + case Composition::Device: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + break; + case Composition::SolidColor: + // In theory the following line should work, but since the HWC1 + // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1 + // devices may not work correctly. To be on the safe side, we + // fall back to client composition. + // + // hwc1Layer.compositionType = HWC_BACKGROUND; + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + break; + case Composition::Cursor: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) { + hwc1Layer.hints |= HWC_IS_CURSOR_LAYER; + } + break; + case Composition::Sideband: + if (mDisplay.getDevice().getHwc1MinorVersion() < 4) { + hwc1Layer.compositionType = HWC_SIDEBAND; + } else { + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + } + break; + default: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + break; + } + ALOGV("Layer %" PRIu64 " %s set to %d", mId, + to_string(mCompositionType).c_str(), + hwc1Layer.compositionType); + ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping"); +} + +// Adapter helpers + +void HWC2On1Adapter::populateCapabilities() { + if (mHwc1MinorVersion >= 3U) { + int supportedTypes = 0; + auto result = mHwc1Device->query(mHwc1Device, + HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes); + if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) { + ALOGI("Found support for HWC virtual displays"); + mHwc1SupportsVirtualDisplays = true; + } + } + if (mHwc1MinorVersion >= 4U) { + mCapabilities.insert(Capability::SidebandStream); + } + + // Check for HWC background color layer support. + if (mHwc1MinorVersion >= 1U) { + int backgroundColorSupported = 0; + auto result = mHwc1Device->query(mHwc1Device, + HWC_BACKGROUND_LAYER_SUPPORTED, + &backgroundColorSupported); + if ((result == 0) && (backgroundColorSupported == 1)) { + ALOGV("Found support for HWC background color"); + mHwc1SupportsBackgroundColor = true; + } + } + + // Some devices might have HWC1 retire fences that accurately emulate + // HWC2 present fences when they are deferred, but it's not very reliable. + // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices. + mCapabilities.insert(Capability::PresentFenceIsNotReliable); +} + +HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) { + std::unique_lock lock(mStateMutex); + + auto display = mDisplays.find(id); + if (display == mDisplays.end()) { + return nullptr; + } + + return display->second.get(); +} + +std::tuple HWC2On1Adapter::getLayer( + hwc2_display_t displayId, hwc2_layer_t layerId) { + auto display = getDisplay(displayId); + if (!display) { + return std::make_tuple(static_cast(nullptr), Error::BadDisplay); + } + + auto layerEntry = mLayers.find(layerId); + if (layerEntry == mLayers.end()) { + return std::make_tuple(static_cast(nullptr), Error::BadLayer); + } + + auto layer = layerEntry->second; + if (layer->getDisplay().getId() != displayId) { + return std::make_tuple(static_cast(nullptr), Error::BadLayer); + } + return std::make_tuple(layer.get(), Error::None); +} + +void HWC2On1Adapter::populatePrimary() { + std::unique_lock lock(mStateMutex); + + auto display = std::make_shared(*this, HWC2::DisplayType::Physical); + mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId(); + display->setHwc1Id(HWC_DISPLAY_PRIMARY); + display->populateConfigs(); + mDisplays.emplace(display->getId(), std::move(display)); +} + +bool HWC2On1Adapter::prepareAllDisplays() { + ATRACE_CALL(); + + std::unique_lock lock(mStateMutex); + + for (const auto& displayPair : mDisplays) { + auto& display = displayPair.second; + if (!display->prepare()) { + return false; + } + } + + if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) { + ALOGE("prepareAllDisplays: Unable to find primary HWC1 display"); + return false; + } + + // Build an array of hwc_display_contents_1 to call prepare() on HWC1. + mHwc1Contents.clear(); + + // Always push the primary display + auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY]; + auto& primaryDisplay = mDisplays[primaryDisplayId]; + mHwc1Contents.push_back(primaryDisplay->getDisplayContents()); + + // Push the external display, if present + if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) { + auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL]; + auto& externalDisplay = mDisplays[externalDisplayId]; + mHwc1Contents.push_back(externalDisplay->getDisplayContents()); + } else { + // Even if an external display isn't present, we still need to send + // at least two displays down to HWC1 + mHwc1Contents.push_back(nullptr); + } + + // Push the hardware virtual display, if supported and present + if (mHwc1MinorVersion >= 3) { + if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) { + auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL]; + auto& virtualDisplay = mDisplays[virtualDisplayId]; + mHwc1Contents.push_back(virtualDisplay->getDisplayContents()); + } else { + mHwc1Contents.push_back(nullptr); + } + } + + for (auto& displayContents : mHwc1Contents) { + if (!displayContents) { + continue; + } + + ALOGV("Display %zd layers:", mHwc1Contents.size() - 1); + for (size_t l = 0; l < displayContents->numHwLayers; ++l) { + auto& layer = displayContents->hwLayers[l]; + ALOGV(" %zd: %d", l, layer.compositionType); + } + } + + ALOGV("Calling HWC1 prepare"); + { + ATRACE_NAME("HWC1 prepare"); + mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(), + mHwc1Contents.data()); + } + + for (size_t c = 0; c < mHwc1Contents.size(); ++c) { + auto& contents = mHwc1Contents[c]; + if (!contents) { + continue; + } + ALOGV("Display %zd layers:", c); + for (size_t l = 0; l < contents->numHwLayers; ++l) { + ALOGV(" %zd: %d", l, contents->hwLayers[l].compositionType); + } + } + + // Return the received contents to their respective displays + for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { + if (mHwc1Contents[hwc1Id] == nullptr) { + continue; + } + + auto displayId = mHwc1DisplayMap[hwc1Id]; + auto& display = mDisplays[displayId]; + display->generateChanges(); + } + + return true; +} + +void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays, + hwc_display_contents_1_t** displays) { + ALOGV("*****************************"); + size_t displayId = 0; + while (displayId < numDisplays) { + hwc_display_contents_1_t* display = displays[displayId]; + + ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display); + if (display == nullptr) { + displayId++; + continue; + } + ALOGV(" retirefd:0x%08x", display->retireFenceFd); + ALOGV(" outbuf :0x%p", display->outbuf); + ALOGV(" outbuffd:0x%08x", display->outbufAcquireFenceFd); + ALOGV(" flags :0x%08x", display->flags); + for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) { + hwc_layer_1_t& layer = display->hwLayers[layerId]; + ALOGV(" Layer[%zu]:", layerId); + ALOGV(" composition : 0x%08x", layer.compositionType); + ALOGV(" hints : 0x%08x", layer.hints); + ALOGV(" flags : 0x%08x", layer.flags); + ALOGV(" handle : 0x%p", layer.handle); + ALOGV(" transform : 0x%08x", layer.transform); + ALOGV(" blending : 0x%08x", layer.blending); + ALOGV(" sourceCropf : %f, %f, %f, %f", + layer.sourceCropf.left, + layer.sourceCropf.top, + layer.sourceCropf.right, + layer.sourceCropf.bottom); + ALOGV(" displayFrame : %d, %d, %d, %d", + layer.displayFrame.left, + layer.displayFrame.left, + layer.displayFrame.left, + layer.displayFrame.left); + hwc_region_t& visReg = layer.visibleRegionScreen; + ALOGV(" visibleRegionScreen: #0x%08zx[@0x%p]", + visReg.numRects, + visReg.rects); + for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) { + if (layer.visibleRegionScreen.rects == nullptr) { + ALOGV(" null"); + } else { + ALOGV(" visibleRegionScreen[%zu] %d, %d, %d, %d", + visRegId, + visReg.rects[visRegId].left, + visReg.rects[visRegId].top, + visReg.rects[visRegId].right, + visReg.rects[visRegId].bottom); + } + } + ALOGV(" acquireFenceFd : 0x%08x", layer.acquireFenceFd); + ALOGV(" releaseFenceFd : 0x%08x", layer.releaseFenceFd); + ALOGV(" planeAlpha : 0x%08x", layer.planeAlpha); + if (getMinorVersion(device) < 5) + continue; + ALOGV(" surfaceDamage : #0x%08zx[@0x%p]", + layer.surfaceDamage.numRects, + layer.surfaceDamage.rects); + for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) { + if (layer.surfaceDamage.rects == nullptr) { + ALOGV(" null"); + } else { + ALOGV(" surfaceDamage[%zu] %d, %d, %d, %d", + sdId, + layer.surfaceDamage.rects[sdId].left, + layer.surfaceDamage.rects[sdId].top, + layer.surfaceDamage.rects[sdId].right, + layer.surfaceDamage.rects[sdId].bottom); + } + } + } + displayId++; + } + ALOGV("-----------------------------"); +} + +Error HWC2On1Adapter::setAllDisplays() { + ATRACE_CALL(); + + std::unique_lock lock(mStateMutex); + + // Make sure we're ready to validate + for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { + if (mHwc1Contents[hwc1Id] == nullptr) { + continue; + } + + auto displayId = mHwc1DisplayMap[hwc1Id]; + auto& display = mDisplays[displayId]; + Error error = display->set(*mHwc1Contents[hwc1Id]); + if (error != Error::None) { + ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id, + to_string(error).c_str()); + return error; + } + } + + ALOGV("Calling HWC1 set"); + { + ATRACE_NAME("HWC1 set"); + //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data()); + mHwc1Device->set(mHwc1Device, mHwc1Contents.size(), + mHwc1Contents.data()); + } + + // Add retire and release fences + for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { + if (mHwc1Contents[hwc1Id] == nullptr) { + continue; + } + + auto displayId = mHwc1DisplayMap[hwc1Id]; + auto& display = mDisplays[displayId]; + auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd; + ALOGV("setAllDisplays: Adding retire fence %d to display %zd", + retireFenceFd, hwc1Id); + display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd); + display->addReleaseFences(*mHwc1Contents[hwc1Id]); + } + + return Error::None; +} + +void HWC2On1Adapter::hwc1Invalidate() { + ALOGV("Received hwc1Invalidate"); + + std::unique_lock lock(mStateMutex); + + // If the HWC2-side callback hasn't been registered yet, buffer this until + // it is registered. + if (mCallbacks.count(Callback::Refresh) == 0) { + mHasPendingInvalidate = true; + return; + } + + const auto& callbackInfo = mCallbacks[Callback::Refresh]; + std::vector displays; + for (const auto& displayPair : mDisplays) { + displays.emplace_back(displayPair.first); + } + + // Call back without the state lock held. + lock.unlock(); + + auto refresh = reinterpret_cast(callbackInfo.pointer); + for (auto display : displays) { + refresh(callbackInfo.data, display); + } +} + +void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) { + ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp); + + std::unique_lock lock(mStateMutex); + + // If the HWC2-side callback hasn't been registered yet, buffer this until + // it is registered. + if (mCallbacks.count(Callback::Vsync) == 0) { + mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp); + return; + } + + if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { + ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId); + return; + } + + const auto& callbackInfo = mCallbacks[Callback::Vsync]; + auto displayId = mHwc1DisplayMap[hwc1DisplayId]; + + // Call back without the state lock held. + lock.unlock(); + + auto vsync = reinterpret_cast(callbackInfo.pointer); + vsync(callbackInfo.data, displayId, timestamp); +} + +void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) { + ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected); + + if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) { + ALOGE("hwc1Hotplug: Received hotplug for non-external display"); + return; + } + + std::unique_lock lock(mStateMutex); + + hwc2_display_t displayId = UINT64_MAX; + if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { + if (connected == 0) { + ALOGW("hwc1Hotplug: Received disconnect for unconnected display"); + return; + } + + // Create a new display on connect + auto display = std::make_shared(*this, + HWC2::DisplayType::Physical); + display->setHwc1Id(HWC_DISPLAY_EXTERNAL); + display->populateConfigs(); + displayId = display->getId(); + mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId; + mDisplays.emplace(displayId, std::move(display)); + } else { + if (connected != 0) { + ALOGW("hwc1Hotplug: Received connect for previously connected " + "display"); + return; + } + + // Disconnect an existing display + displayId = mHwc1DisplayMap[hwc1DisplayId]; + mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL); + mDisplays.erase(displayId); + } + + // If the HWC2-side callback hasn't been registered yet, buffer this until + // it is registered + if (mCallbacks.count(Callback::Hotplug) == 0) { + mPendingHotplugs.emplace_back(hwc1DisplayId, connected); + return; + } + + const auto& callbackInfo = mCallbacks[Callback::Hotplug]; + + // Call back without the state lock held + lock.unlock(); + + auto hotplug = reinterpret_cast(callbackInfo.pointer); + auto hwc2Connected = (connected == 0) ? + HWC2::Connection::Disconnected : HWC2::Connection::Connected; + hotplug(callbackInfo.data, displayId, static_cast(hwc2Connected)); +} +} // namespace android diff --git a/aosp/packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java b/aosp/packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java index 559608cd7..68660908b 100755 --- a/aosp/packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java +++ b/aosp/packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java @@ -8715,6 +8715,7 @@ public class ConnectivityService extends IConnectivityManager.Stub updateRoutes(newLp, oldLp, netId); updateDnses(newLp, oldLp, netId); } + // Make sure LinkProperties represents the latest private DNS status. // This does not need to be done before updateDnses because the // LinkProperties are not the source of the private DNS configuration. diff --git a/aosp/packages/modules/NetworkStack/src/com/android/server/NetworkStackService.java b/aosp/packages/modules/NetworkStack/src/com/android/server/NetworkStackService.java deleted file mode 100644 index 40aee2835..000000000 --- a/aosp/packages/modules/NetworkStack/src/com/android/server/NetworkStackService.java +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -package com.android.server; - -import static android.net.dhcp.IDhcpServer.STATUS_INVALID_ARGUMENT; -import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; -import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR; - -import static com.android.net.module.util.DeviceConfigUtils.getResBooleanConfig; -import static com.android.net.module.util.FeatureVersions.FEATURE_IS_UID_NETWORKING_BLOCKED; -import static com.android.networkstack.util.NetworkStackUtils.IGNORE_TCP_INFO_FOR_BLOCKED_UIDS; -import static com.android.networkstack.util.NetworkStackUtils.SKIP_TCP_POLL_IN_LIGHT_DOZE; -import static com.android.server.util.PermissionUtil.checkDumpPermission; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.IIpMemoryStore; -import android.net.IIpMemoryStoreCallbacks; -import android.net.INetd; -import android.net.INetworkMonitor; -import android.net.INetworkMonitorCallbacks; -import android.net.INetworkStackConnector; -import android.net.INetworkStackStatusCallback; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.PrivateDnsConfigParcel; -import android.net.dhcp.DhcpServer; -import android.net.dhcp.DhcpServingParams; -import android.net.dhcp.DhcpServingParamsParcel; -import android.net.dhcp.IDhcpServerCallbacks; -import android.net.ip.IIpClientCallbacks; -import android.net.ip.IpClient; -import android.net.networkstack.aidl.NetworkMonitorParameters; -import android.net.shared.PrivateDnsConfig; -import android.os.Build; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.ArraySet; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.IndentingPrintWriter; -import com.android.modules.utils.BasicShellCommandHandler; -import com.android.net.module.util.DeviceConfigUtils; -import com.android.net.module.util.SharedLog; -import com.android.networkstack.NetworkStackNotifier; -import com.android.networkstack.R; -import com.android.networkstack.apishim.common.ShimUtils; -import com.android.networkstack.ipmemorystore.IpMemoryStoreService; -import com.android.server.connectivity.NetworkMonitor; -import com.android.server.util.PermissionUtil; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.ref.WeakReference; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.SortedSet; -import java.util.TreeSet; - -/** - * Android service used to start the network stack when bound to via an intent. - * - *

The service returns a binder for the system server to communicate with the network stack. - */ -public class NetworkStackService extends Service { - private static final String TAG = NetworkStackService.class.getSimpleName(); - private static NetworkStackConnector sConnector; - - /** - * Create a binder connector for the system server to communicate with the network stack. - * - *

On platforms where the network stack runs in the system server process, this method may - * be called directly instead of obtaining the connector by binding to the service. - */ - public static synchronized IBinder makeConnector(Context context) { - if (sConnector == null) { - sConnector = new NetworkStackConnector(context); - } - return sConnector; - } - - @NonNull - @Override - public IBinder onBind(Intent intent) { - return makeConnector(this); - } - - /** - * An interface for internal clients of the network stack service that can return - * or create inline instances of the service it manages. - */ - public interface NetworkStackServiceManager { - /** - * Get an instance of the IpMemoryStoreService. - */ - IIpMemoryStore getIpMemoryStoreService(); - - /** - * Get an instance of the NetworkNotifier. - */ - NetworkStackNotifier getNotifier(); - } - - /** - * Permission checking dependency of the connector, useful for testing. - */ - public static class PermissionChecker { - /** - * @see PermissionUtil#enforceNetworkStackCallingPermission() - */ - public void enforceNetworkStackCallingPermission() { - PermissionUtil.enforceNetworkStackCallingPermission(); - } - } - - /** - * Dependencies of {@link NetworkStackConnector}, useful for testing. - */ - public static class Dependencies { - /** @see IpMemoryStoreService */ - @NonNull - public IpMemoryStoreService makeIpMemoryStoreService(@NonNull Context context) { - return new IpMemoryStoreService(context); - } - - /** @see NetworkStackNotifier */ - @NonNull - public NetworkStackNotifier makeNotifier(@NonNull Context context, @NonNull Looper looper) { - return new NetworkStackNotifier(context, looper); - } - - /** @see DhcpServer */ - @NonNull - public DhcpServer makeDhcpServer(@NonNull Context context, @NonNull String ifName, - @NonNull DhcpServingParams params, @NonNull SharedLog log) { - return new DhcpServer(context, ifName, params, log); - } - - /** @see NetworkMonitor */ - @NonNull - public NetworkMonitor makeNetworkMonitor(@NonNull Context context, - @NonNull INetworkMonitorCallbacks cb, @NonNull Network network, - @NonNull SharedLog log, @NonNull NetworkStackServiceManager nsServiceManager) { - return new NetworkMonitor(context, cb, network, log, nsServiceManager); - } - - /** @see IpClient */ - @NonNull - public IpClient makeIpClient(@NonNull Context context, @NonNull String ifName, - @NonNull IIpClientCallbacks cb, @NonNull NetworkObserverRegistry observerRegistry, - @NonNull NetworkStackServiceManager nsServiceManager) { - return new IpClient(context, ifName, cb, observerRegistry, nsServiceManager); - } - } - - /** - * Connector implementing INetworkStackConnector for clients. - */ - @VisibleForTesting - public static class NetworkStackConnector extends INetworkStackConnector.Stub - implements NetworkStackServiceManager { - private static final int NUM_VALIDATION_LOG_LINES = 20; - private final Context mContext; - private final PermissionChecker mPermChecker; - private final Dependencies mDeps; - private final INetd mNetd; - private final NetworkObserverRegistry mObserverRegistry; - @GuardedBy("mIpClients") - private final ArrayList> mIpClients = new ArrayList<>(); - private final IpMemoryStoreService mIpMemoryStoreService; - @Nullable - private final NetworkStackNotifier mNotifier; - - private static final int MAX_VALIDATION_LOGS = 10; - @GuardedBy("mValidationLogs") - private final ArrayDeque mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS); - - private static final String DUMPSYS_ARG_VERSION = "version"; - - private static final String AIDL_KEY_NETWORKSTACK = "networkstack"; - private static final String AIDL_KEY_IPMEMORYSTORE = "ipmemorystore"; - private static final String AIDL_KEY_NETD = "netd"; - - private static final int VERSION_UNKNOWN = -1; - private static final String HASH_UNKNOWN = "unknown"; - - /** - * Versions of the AIDL interfaces observed by the network stack, in other words versions - * that the framework and other modules communicating with the network stack are using. - * The map may hold multiple values as the interface is used by modules with different - * versions. - */ - @GuardedBy("mFrameworkAidlVersions") - private final ArraySet mAidlVersions = new ArraySet<>(); - - private static final class AidlVersion implements Comparable { - @NonNull - final String mKey; - final int mVersion; - @NonNull - final String mHash; - - private static final Comparator COMPARATOR = - Comparator.comparing((AidlVersion v) -> v.mKey) - .thenComparingInt(v -> v.mVersion) - .thenComparing(v -> v.mHash, String::compareTo); - - AidlVersion(@NonNull String key, int version, @NonNull String hash) { - mKey = key; - mVersion = version; - mHash = hash; - } - - @Override - public int hashCode() { - return Objects.hash(mVersion, mHash); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof AidlVersion)) return false; - final AidlVersion other = (AidlVersion) obj; - return Objects.equals(mKey, other.mKey) - && Objects.equals(mVersion, other.mVersion) - && Objects.equals(mHash, other.mHash); - } - - @NonNull - @Override - public String toString() { - // Use a format that can be easily parsed by tests for the version - return String.format("%s:%s:%s", mKey, mVersion, mHash); - } - - @Override - public int compareTo(AidlVersion o) { - return COMPARATOR.compare(this, o); - } - } - - private SharedLog addValidationLogs(Network network, String name) { - final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name); - synchronized (mValidationLogs) { - while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) { - mValidationLogs.removeLast(); - } - mValidationLogs.addFirst(log); - } - return log; - } - - NetworkStackConnector(@NonNull Context context) { - this(context, new PermissionChecker(), new Dependencies()); - } - - @VisibleForTesting - public NetworkStackConnector( - @NonNull Context context, @NonNull PermissionChecker permChecker, - @NonNull Dependencies deps) { - mContext = context; - mPermChecker = permChecker; - mDeps = deps; - mNetd = INetd.Stub.asInterface( - (IBinder) context.getSystemService(Context.NETD_SERVICE)); - mObserverRegistry = new NetworkObserverRegistry(); - mIpMemoryStoreService = mDeps.makeIpMemoryStoreService(context); - // NetworkStackNotifier only shows notifications relevant for API level > Q - if (ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) { - final HandlerThread notifierThread = new HandlerThread( - NetworkStackNotifier.class.getSimpleName()); - notifierThread.start(); - mNotifier = mDeps.makeNotifier(context, notifierThread.getLooper()); - } else { - mNotifier = null; - } - - int netdVersion; - String netdHash; - try { - netdVersion = mNetd.getInterfaceVersion(); - netdHash = mNetd.getInterfaceHash(); - } catch (RemoteException e) { - mLog.e("Error obtaining INetd version", e); - netdVersion = VERSION_UNKNOWN; - netdHash = HASH_UNKNOWN; - } - updateNetdAidlVersion(netdVersion, netdHash); - - try { - mObserverRegistry.register(mNetd); - } catch (RemoteException e) { - mLog.e("Error registering observer on Netd", e); - } - } - - private void updateNetdAidlVersion(final int version, final String hash) { - synchronized (mAidlVersions) { - mAidlVersions.add(new AidlVersion(AIDL_KEY_NETD, version, hash)); - } - } - - private void updateNetworkStackAidlVersion(final int version, final String hash) { - synchronized (mAidlVersions) { - mAidlVersions.add(new AidlVersion(AIDL_KEY_NETWORKSTACK, version, hash)); - } - } - - private void updateIpMemoryStoreAidlVersion(final int version, final String hash) { - synchronized (mAidlVersions) { - mAidlVersions.add(new AidlVersion(AIDL_KEY_IPMEMORYSTORE, version, hash)); - } - } - - @NonNull - private final SharedLog mLog = new SharedLog(TAG); - - @Override - public void makeDhcpServer(@NonNull String ifName, @NonNull DhcpServingParamsParcel params, - @NonNull IDhcpServerCallbacks cb) throws RemoteException { - mPermChecker.enforceNetworkStackCallingPermission(); - updateNetworkStackAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); - final DhcpServer server; - try { - server = mDeps.makeDhcpServer( - mContext, - ifName, - DhcpServingParams.fromParcelableObject(params), - mLog.forSubComponent(ifName + ".DHCP")); - } catch (DhcpServingParams.InvalidParameterException e) { - mLog.e("Invalid DhcpServingParams", e); - cb.onDhcpServerCreated(STATUS_INVALID_ARGUMENT, null); - return; - } catch (Exception e) { - mLog.e("Unknown error starting DhcpServer", e); - cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null); - return; - } - cb.onDhcpServerCreated(STATUS_SUCCESS, server.makeConnector()); - } - - @Override - public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) - throws RemoteException { - mPermChecker.enforceNetworkStackCallingPermission(); - updateNetworkStackAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); - final SharedLog log = addValidationLogs(network, name); - final NetworkMonitor nm = mDeps.makeNetworkMonitor(mContext, cb, network, log, this); - cb.onNetworkMonitorCreated(new NetworkMonitorConnector(nm, mPermChecker)); - } - - @Override - public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException { - mPermChecker.enforceNetworkStackCallingPermission(); - updateNetworkStackAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); - final IpClient ipClient = mDeps.makeIpClient( - mContext, ifName, cb, mObserverRegistry, this); - - synchronized (mIpClients) { - final Iterator> it = mIpClients.iterator(); - while (it.hasNext()) { - final IpClient ipc = it.next().get(); - if (ipc == null) { - it.remove(); - } - } - mIpClients.add(new WeakReference<>(ipClient)); - } - - cb.onIpClientCreated(ipClient.makeConnector()); - } - - @Override - public IIpMemoryStore getIpMemoryStoreService() { - return mIpMemoryStoreService; - } - - @Override - public NetworkStackNotifier getNotifier() { - return mNotifier; - } - - @Override - public void fetchIpMemoryStore(@NonNull final IIpMemoryStoreCallbacks cb) - throws RemoteException { - mPermChecker.enforceNetworkStackCallingPermission(); - updateIpMemoryStoreAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); - cb.onIpMemoryStoreFetched(mIpMemoryStoreService); - } - - @Override - public void allowTestUid(int uid, @Nullable INetworkStackStatusCallback cb) - throws RemoteException { - // setTestUid does its own permission checks - PermissionUtil.setTestUid(mContext, uid); - mLog.i("Allowing test uid " + uid); - if (cb != null) cb.onStatusAvailable(0); - } - - @Override @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) - public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout, - @Nullable String[] args) { - checkDumpPermission(); - - final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " "); - pw.println("NetworkStack version:"); - dumpVersion(pw); - pw.println(); - - if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) { - return; - } - - pw.println("Device Configs:"); - pw.increaseIndent(); - pw.println("SKIP_TCP_POLL_IN_LIGHT_DOZE=" - + DeviceConfigUtils.isNetworkStackFeatureNotChickenedOut( - mContext, SKIP_TCP_POLL_IN_LIGHT_DOZE)); - pw.println("FEATURE_IS_UID_NETWORKING_BLOCKED=" + DeviceConfigUtils.isFeatureSupported( - mContext, FEATURE_IS_UID_NETWORKING_BLOCKED)); - pw.println("IGNORE_TCP_INFO_FOR_BLOCKED_UIDS=" - + DeviceConfigUtils.isNetworkStackFeatureNotChickenedOut(mContext, - IGNORE_TCP_INFO_FOR_BLOCKED_UIDS)); - pw.decreaseIndent(); - pw.println(); - - - pw.println("NetworkStack logs:"); - mLog.dump(fd, pw, args); - - // Dump full IpClient logs for non-GCed clients - pw.println(); - pw.println("Recently active IpClient logs:"); - final ArrayList ipClients = new ArrayList<>(); - final HashSet dumpedIpClientIfaces = new HashSet<>(); - synchronized (mIpClients) { - for (WeakReference ipcRef : mIpClients) { - final IpClient ipc = ipcRef.get(); - if (ipc != null) { - ipClients.add(ipc); - } - } - } - - for (IpClient ipc : ipClients) { - pw.println(ipc.getName()); - pw.increaseIndent(); - ipc.dump(fd, pw, args); - pw.decreaseIndent(); - dumpedIpClientIfaces.add(ipc.getInterfaceName()); - } - - // State machine and connectivity metrics logs are kept for GCed IpClients - pw.println(); - pw.println("Other IpClient logs:"); - IpClient.dumpAllLogs(fout, dumpedIpClientIfaces); - - pw.println(); - pw.println("Validation logs (most recent first):"); - synchronized (mValidationLogs) { - for (SharedLog p : mValidationLogs) { - pw.println(p.getTag()); - pw.increaseIndent(); - p.dump(fd, pw, args); - pw.decreaseIndent(); - } - } - - pw.println(); - pw.print("useNeighborResource: "); - pw.println(getResBooleanConfig(mContext, - R.bool.config_no_sim_card_uses_neighbor_mcc, false)); - } - - @Override - public int handleShellCommand(@NonNull ParcelFileDescriptor in, - @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, - @NonNull String[] args) { - return new ShellCmd().exec(this, in.getFileDescriptor(), out.getFileDescriptor(), - err.getFileDescriptor(), args); - } - - private class ShellCmd extends BasicShellCommandHandler { - @Override - public int onCommand(String cmd) { - if (cmd == null) { - return handleDefaultCommands(cmd); - } - final PrintWriter pw = getOutPrintWriter(); - try { - switch (cmd) { - case "is-uid-networking-blocked": - if (!DeviceConfigUtils.isFeatureSupported(mContext, - FEATURE_IS_UID_NETWORKING_BLOCKED)) { - pw.println("API is unsupported"); - return -1; - } - - // Usage : cmd network_stack is-uid-networking-blocked - // If no argument, get and display the usage help. - if (getRemainingArgsCount() != 2) { - onHelp(); - return -1; - } - final int uid; - final boolean metered; - // If any fail, throws and output to the stdout. - // Let the caller handle it. - uid = Integer.parseInt(getNextArg()); - metered = Boolean.parseBoolean(getNextArg()); - final ConnectivityManager cm = - mContext.getSystemService(ConnectivityManager.class); - pw.println(cm.isUidNetworkingBlocked( - uid, metered /* isNetworkMetered */)); - return 0; - default: - return handleDefaultCommands(cmd); - } - } catch (Exception e) { - pw.println(e); - } - return -1; - } - - @Override - public void onHelp() { - PrintWriter pw = getOutPrintWriter(); - pw.println("NetworkStack service commands:"); - pw.println(" help"); - pw.println(" Print this help text."); - pw.println(" is-uid-networking-blocked "); - pw.println(" Get whether the networking is blocked for given uid and metered."); - pw.println(" : The target uid."); - pw.println(" : [true|false], Whether the target network is metered."); - } - } - - /** - * Dump version information of the module and detected system version. - */ - private void dumpVersion(@NonNull PrintWriter fout) { - if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) { - dumpVersionNumberOnly(fout); - return; - } - - fout.println("LocalInterface:" + this.VERSION + ":" + this.HASH); - synchronized (mAidlVersions) { - // Sort versions for deterministic order in output - for (AidlVersion version : sortVersions(mAidlVersions)) { - fout.println(version); - } - } - } - - private List sortVersions(Collection versions) { - final List sorted = new ArrayList<>(versions); - Collections.sort(sorted); - return sorted; - } - - /** - * Legacy version of dumpVersion, only used for Q, as only the interface version number - * was used in Q. - * - *

Q behavior needs to be preserved as conformance tests for Q still expect this format. - * Once all conformance test suites are updated to expect the new format even on Q devices, - * this can be removed. - */ - private void dumpVersionNumberOnly(@NonNull PrintWriter fout) { - fout.println("NetworkStackConnector: " + this.VERSION); - final SortedSet systemServerVersions = new TreeSet<>(); - int netdVersion = VERSION_UNKNOWN; - synchronized (mAidlVersions) { - for (AidlVersion version : mAidlVersions) { - switch (version.mKey) { - case AIDL_KEY_IPMEMORYSTORE: - case AIDL_KEY_NETWORKSTACK: - systemServerVersions.add(version.mVersion); - break; - case AIDL_KEY_NETD: - netdVersion = version.mVersion; - break; - default: - break; - } - } - } - // TreeSet.toString is formatted as [a, b], but Q used ArraySet.toString formatted as - // {a, b}. ArraySet does not have guaranteed ordering, which was not a problem in Q - // when only one interface number was expected (and there was no unit test relying on - // the ordering). - fout.println("SystemServer: {" + TextUtils.join(", ", systemServerVersions) + "}"); - fout.println("Netd: " + netdVersion); - } - - /** - * Get the version of the AIDL interface. - */ - @Override - public int getInterfaceVersion() { - return this.VERSION; - } - - @Override - public String getInterfaceHash() { - return this.HASH; - } - } - - /** - * Proxy for {@link NetworkMonitor} that implements {@link INetworkMonitor}. - */ - @VisibleForTesting - public static class NetworkMonitorConnector extends INetworkMonitor.Stub { - @NonNull - private final NetworkMonitor mNm; - @NonNull - private final PermissionChecker mPermChecker; - - public NetworkMonitorConnector(@NonNull NetworkMonitor nm, - @NonNull PermissionChecker permChecker) { - mNm = nm; - mPermChecker = permChecker; - } - - @Override - public void start() { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.start(); - } - - @Override - public void launchCaptivePortalApp() { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.launchCaptivePortalApp(); - } - - @Override - public void notifyCaptivePortalAppFinished(int response) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyCaptivePortalAppFinished(response); - } - - @Override - public void setAcceptPartialConnectivity() { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.setAcceptPartialConnectivity(); - } - - @Override - public void forceReevaluation(int uid) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.forceReevaluation(uid); - } - - @Override - public void notifyPrivateDnsChanged(PrivateDnsConfigParcel config) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyPrivateDnsSettingsChanged(PrivateDnsConfig.fromParcel(config)); - } - - @Override - public void notifyDnsResponse(int returnCode) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyDnsResponse(returnCode); - } - - /** - * Send a notification to NetworkMonitor indicating that the network is now connected. - * @Deprecated use notifyNetworkConnectedParcel, which also passes the NetworkAgentConfig. - */ - @Override - public void notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyNetworkConnected(lp, nc); - } - - /** - * Send a notification to NetworkMonitor indicating that the network is now connected. - */ - @Override - public void notifyNetworkConnectedParcel(NetworkMonitorParameters params) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyNetworkConnectedParcel(params); - } - - @Override - public void notifyNetworkDisconnected() { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyNetworkDisconnected(); - } - - @Override - public void notifyLinkPropertiesChanged(LinkProperties lp) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyLinkPropertiesChanged(lp); - } - - @Override - public void notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) { - mPermChecker.enforceNetworkStackCallingPermission(); - mNm.notifyNetworkCapabilitiesChanged(nc); - } - - @Override - public int getInterfaceVersion() { - return this.VERSION; - } - - @Override - public String getInterfaceHash() { - return this.HASH; - } - } -} diff --git a/aosp/packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java b/aosp/packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java index 7d0332007..22fbf1bb5 100644 --- a/aosp/packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java +++ b/aosp/packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java @@ -758,7 +758,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { mCurrentNetworkRemoteHandles.put(ifaceName, pair.first); mCurrentNetworkLocalConfigs.put(ifaceName, pair.second); } - + if (WifiHelpers.enable()) { // directly notify completion without visiting wpa_supplicant notifyComplete(); diff --git a/aosp/system/core/rootdir/init.rc b/aosp/system/core/rootdir/init.rc index 4ae263beb..d820138e7 100644 --- a/aosp/system/core/rootdir/init.rc +++ b/aosp/system/core/rootdir/init.rc @@ -1106,6 +1106,7 @@ on zygote-start start statsd start netd start zygote + start zygote_secondary on boot && property:ro.config.low_ram=true # Tweak background writeout diff --git a/aosp/vendor/common/prebuild/Android.mk b/aosp/vendor/common/prebuild/Android.mk new file mode 100644 index 000000000..a7f568505 --- /dev/null +++ b/aosp/vendor/common/prebuild/Android.mk @@ -0,0 +1,90 @@ +LOCAL_PATH := $(call my-dir) + +define install-system-shared-libs +include $$(CLEAR_VARS) +LOCAL_MODULE := $1 +LOCAL_SRC_FILES_arm64 := $2 +ifneq ($3,) +LOCAL_SRC_FILES_arm := $3 +endif +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +ifneq ($4,) +LOCAL_MODULE_RELATIVE_PATH := $4 +endif +LOCAL_MODULE_SUFFIX := .so +LOCAL_CHECK_ELF_FILES := false +ifneq ($5,) +LOCAL_MULTILIB := $5 +endif +include $$(BUILD_PREBUILT) +endef + +define install-vendor-shared-libs +include $$(CLEAR_VARS) +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE := $1 +LOCAL_SRC_FILES_arm64 := $2 +ifneq ($3,) +LOCAL_SRC_FILES_arm := $3 +endif +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +ifneq ($4,) +LOCAL_MODULE_RELATIVE_PATH := $4 +endif +LOCAL_MODULE_SUFFIX := .so +LOCAL_CHECK_ELF_FILES := false +ifneq ($5,) +LOCAL_MULTILIB := $5 +endif +include $$(BUILD_PREBUILT) +endef + +ifneq ($(wildcard $(LOCAL_PATH)/system/lib),) +VA_MULTILIB := both +else +VA_MULTILIB := first +endif + + +cme_libs = \ +libCPHMediaEngine \ +libCaptureEngine \ +libVmiOperation \ +libVmiCJSON \ +libVmiMediaCommon \ +libEncodeEngine \ +libVmiDevice \ +libCPHVideoEngine \ +libRemoteEncoder \ +libCPHHanboVideoEngine \ +libCPHMediaServer \ +libd310encode \ + +$(foreach lib, $(cme_libs), \ + $(if $(wildcard $(LOCAL_PATH)/system/lib64/$(lib).so), \ + $(eval $(call install-system-shared-libs, \ + $(lib), \ + system/lib64/$(lib).so, \ + system/lib/$(lib).so, \ + , \ + $(VA_MULTILIB))))) + +hal_libs = \ +audio.primary.default + +$(foreach lib, $(hal_libs), \ + $(eval $(call install-vendor-shared-libs, \ + $(lib), \ + system/vendor/lib64/hw/$(lib).so, \ + system/vendor/lib/hw/$(lib).so, \ + hw, \ + $(VA_MULTILIB)))) + +include $(CLEAR_VARS) +LOCAL_MODULE := uInput +LOCAL_SRC_FILES_arm64 := system/bin/uInput +LOCAL_MODULE_RELATIVE_PATH := $4 +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_CHECK_ELF_FILES := false +LOCAL_INIT_RC := system/etc/init/uinput.rc +include $(BUILD_PREBUILT) diff --git a/aosp/vendor/common/prebuild/media_engine.mk b/aosp/vendor/common/prebuild/media_engine.mk new file mode 100644 index 000000000..724ad4966 --- /dev/null +++ b/aosp/vendor/common/prebuild/media_engine.mk @@ -0,0 +1,36 @@ +CUR_PATH := vendor/common/prebuild + +# CME +ifeq ($(CONFIG_ENABLE_CME),y) +PRODUCT_PACKAGES += \ + libCPHMediaEngine \ + libCPHHanboVideoEngine \ + libCPHMediaServer \ + libCaptureEngine \ + libVmiOperation \ + libVmiCJSON \ + libVmiMediaCommon \ + libEncodeEngine \ + libVmiDevice \ + libCPHVideoEngine \ + libRemoteEncoder \ + libd310encode \ + libdrm \ + libgbm \ + libopus \ + uInput \ + +PRODUCT_COPY_FILES += \ + $(CUR_PATH)/system/etc/mediaEngine/media_default.json:system/etc/mediaEngine/media_default.json \ + $(CUR_PATH)/system/bin/media_logrotate.sh:system/bin/media_logrotate.sh \ + $(CUR_PATH)/system/etc/init/media-engine.rc:system/etc/init/media-engine.rc \ + $(CUR_PATH)/system/usr/keylayout/Vendor_0001_Product_0001.kl:system/usr/keylayout/Vendor_0001_Product_0001.kl + +endif + +# audio hal +ifeq ($(CONFIG_ENABLE_HW_AUDIO),y) +PRODUCT_PACKAGES += \ + audio.primary.default \ + libopus.vendor +endif \ No newline at end of file diff --git a/aosp/vendor/isula/common.mk b/aosp/vendor/isula/common.mk index fb3a86e41..42f0a116b 100644 --- a/aosp/vendor/isula/common.mk +++ b/aosp/vendor/isula/common.mk @@ -3,8 +3,10 @@ # Description: common config # +CONFIG_ENABLE_CME=y +CONFIG_ENABLE_HW_AUDIO=y + $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk) @@ -12,6 +14,7 @@ $(call inherit-product, frameworks/native/build/phone-xhdpi-2048-dalvik-heap.mk) $(call inherit-product, vendor/isula/packages.mk) $(call inherit-product, vendor/isula/properties.mk) $(call inherit-product, vendor/isula/copyfiles.mk) +$(call inherit-product, vendor/common/prebuild/media_engine.mk) # product config PRODUCT_AAPT_CONFIG := normal xhdpi @@ -23,6 +26,7 @@ PRODUCT_ENABLE_UFFD_GC := true PRODUCT_DEFAULT_DEV_CERTIFICATE := vendor/common/certificates/releasekey PRODUCT_SOONG_NAMESPACES += device/generic/goldfish PRODUCT_PACKAGE_OVERLAYS := vendor/common/overlay +PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64_32 # target config TARGET_NO_BOOTLOADER := true @@ -31,10 +35,18 @@ TARGET_ARCH := arm64 TARGET_ARCH_VARIANT := armv8-a TARGET_CPU_VARIANT := generic TARGET_CPU_ABI := arm64-v8a + +TARGET_2ND_ARCH := arm +TARGET_2ND_ARCH_VARIANT := armv7-a-neon +TARGET_2ND_CPU_VARIANT := cortex-a15 +TARGET_2ND_CPU_ABI := armeabi-v7a +TARGET_2ND_CPU_ABI2 := armeabi + TARGET_USERIMAGES_USE_EXT4 := true TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true TARGET_SUPPORTS_64_BIT_APPS := true TARGET_USES_MKE2FS := true +TARGET_SUPPORTS_32_BIT_APPS := true # build config BUILD_QEMU_IMAGES := false diff --git a/aosp/vendor/isula/copyfiles.mk b/aosp/vendor/isula/copyfiles.mk index 1f8a68d52..984992b9a 100644 --- a/aosp/vendor/isula/copyfiles.mk +++ b/aosp/vendor/isula/copyfiles.mk @@ -4,6 +4,7 @@ # PRODUCT_COPY_FILES += \ + system/core/rootdir/init.zygote64_32.rc:system/etc/init/hw/init.zygote64_32.rc \ system/core/rootdir/init.zygote64.rc:system/etc/init/hw/init.zygote64.rc \ vendor/common/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \ vendor/common/scripts/hook.sh:system/bin/hook.sh \ diff --git a/aosp/vendor/isula/hals/Android.mk b/aosp/vendor/isula/hals/Android.mk deleted file mode 100644 index e97867c27..000000000 --- a/aosp/vendor/isula/hals/Android.mk +++ /dev/null @@ -1,44 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -define install-hals-shared-libs -include $$(CLEAR_VARS) -LOCAL_MODULE := $1 -LOCAL_VENDOR_MODULE := true -LOCAL_SRC_FILES_arm64 := $2 -ifneq ($3,) -LOCAL_SRC_FILES_arm := $3 -endif -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -ifneq ($4,) -LOCAL_MODULE_RELATIVE_PATH := $4 -endif -LOCAL_MODULE_SUFFIX := .so -LOCAL_CHECK_ELF_FILES := false -ifneq ($5,) -LOCAL_MULTILIB := both -endif -include $$(BUILD_PREBUILT) -endef - - -hals_hw_libs := \ -audio.primary.default \ -gps.default \ -sensors.default \ - -$(foreach lib, $(hals_hw_libs), \ - $(eval $(call install-hals-shared-libs, \ - $(lib), \ - vendor/lib64/hw/$(lib).so, \ - vendor/lib/hw/$(lib).so, \ - hw, \ - 1))) - -include $(CLEAR_VARS) -LOCAL_MODULE := vinput -LOCAL_SRC_FILES_arm64 := vendor/bin/vinput -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_CHECK_ELF_FILES := false -LOCAL_VENDOR_MODULE := true -LOCAL_INIT_RC := vendor/etc/init/vinput.rc -include $(BUILD_PREBUILT) diff --git a/aosp/vendor/isula/hals/CleanSpec.mk b/aosp/vendor/isula/hals/CleanSpec.mk deleted file mode 100644 index 79725ffb3..000000000 --- a/aosp/vendor/isula/hals/CleanSpec.mk +++ /dev/null @@ -1 +0,0 @@ -$(call add-clean-step, rm -rf $(TARGET_OUT)/bin/vinput) diff --git a/aosp/vendor/isula/packages.mk b/aosp/vendor/isula/packages.mk index eb446cea2..68932268e 100644 --- a/aosp/vendor/isula/packages.mk +++ b/aosp/vendor/isula/packages.mk @@ -34,10 +34,6 @@ PRODUCT_PACKAGES += \ com.google.oemlock \ com.google.confirmationui \ com.google.light \ - libdumpstateutil.vendor \ - libutilscallstack.vendor \ - android.hardware.atrace@1.0.vendor \ - android.hardware.dumpstate@1.1.vendor \ # apks @@ -67,11 +63,14 @@ PRODUCT_PACKAGES += \ # kbox(to be deleted) PRODUCT_PACKAGES += \ - vinput \ gps.default \ sensors.default \ audio.primary.default \ +#cme +PRODUCT_PACKAGES += \ + uInput \ + # vagpu PRODUCT_PACKAGES += \ @@ -91,24 +90,15 @@ PRODUCT_PACKAGES += \ libvaANDROID_WSEGL \ libvalloc \ libvaccrt \ + libvaccrt.vendor \ libvmpp-enc \ libvmpp-dec \ va_gfx.ini \ - libavcodec \ - libavdevice \ - libavfilter \ - libavformat \ - libavutil \ - libswresample \ - libswscale \ - libDisplayServer \ - libpostproc \ - libvacm \ - libfn-log \ - libvame \ - libvaml \ - va_drv_video \ libdrm.vendor \ + libdumpstateutil.vendor \ + libutilscallstack.vendor \ + android.hardware.atrace@1.0.vendor \ + android.hardware.dumpstate@1.1.vendor \ libcodec2.vendor \ android.hardware.media.c2@1.0.vendor \ android.hardware.media.c2@1.1.vendor \ @@ -118,6 +108,7 @@ PRODUCT_PACKAGES += \ libcodec2_hidl@1.1.vendor \ libcodec2_hidl@1.2.vendor \ libcodec2_vndk.vendor \ + liblog.vendor \ libsfplugin_ccodec_utils.vendor \ libstagefright_foundation.vendor \ libjsoncpp.vendor \ @@ -127,11 +118,26 @@ PRODUCT_PACKAGES += \ libcodec2_default_video_dec \ libcodec2_default_video_enc \ libc++_shared \ + libc++_shared.vendor \ android.hardware.media.c2@1.0-service-default \ android.hardware.media.c2@1.0-service-default.rc \ android.hardware.media.c2@1.0-service-default.xml \ default_enc_params.json \ media_codecs_c2.xml \ + libDisplayServer \ + libavutil \ + libavcodec \ + libswresample \ + libavdevice \ + libavfilter \ + libswscale \ + libavformat \ + libpostproc \ + va_drv_video \ + libfn-log \ + libvacm \ + libvame \ + libvaml \ vslog.cfg \ # tools diff --git a/aosp/vendor/isula/properties.mk b/aosp/vendor/isula/properties.mk index 81725c1f0..53311d9a8 100644 --- a/aosp/vendor/isula/properties.mk +++ b/aosp/vendor/isula/properties.mk @@ -38,7 +38,7 @@ PRODUCT_PROPERTY_OVERRIDES += \ ro.surface_flinger.supports_background_blur=1 \ ro.surface_flinger.use_color_management=false \ ro.zygote.disable_gl_preload=1 \ - ro.zygote=zygote64 \ + ro.zygote=zygote64_32 \ wifi.direct.interface=p2p-dev-wlan0 \ wifi.interface=wlan0 \ ro.lmk.use_new_strategy=false \ diff --git a/aosp/vendor/isula/vagpu/Android.bp b/aosp/vendor/isula/vagpu/Android.bp new file mode 100644 index 000000000..103c509e0 --- /dev/null +++ b/aosp/vendor/isula/vagpu/Android.bp @@ -0,0 +1,27 @@ +cc_prebuilt_library_shared { + name: "libvaccrt", + vendor_available: true, + compile_multilib: "both", + target: { + android_arm: { + srcs: ["system/vendor/lib/libvaccrt.so"], + }, + android_arm64: { + srcs: ["system/vendor/lib64/libvaccrt.so"], + }, + }, +} + +cc_prebuilt_library_shared { + name: "libc++_shared", + vendor_available: true, + compile_multilib: "both", + target: { + android_arm: { + srcs: ["system/vendor/lib/libc++_shared.so"], + }, + android_arm64: { + srcs: ["system/vendor/lib64/libc++_shared.so"], + }, + }, +} \ No newline at end of file diff --git a/aosp/vendor/isula/vagpu/Android.mk b/aosp/vendor/isula/vagpu/Android.mk index 89fce82cb..00f61ad66 100644 --- a/aosp/vendor/isula/vagpu/Android.mk +++ b/aosp/vendor/isula/vagpu/Android.mk @@ -20,6 +20,25 @@ endif include $$(BUILD_PREBUILT) endef +define install-codec-libs-to-system +include $$(CLEAR_VARS) +LOCAL_MODULE := $1 +LOCAL_SRC_FILES_arm64 := $2 +ifneq ($3,) +LOCAL_SRC_FILES_arm := $3 +endif +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +ifneq ($4,) +LOCAL_MODULE_RELATIVE_PATH := $4 +endif +LOCAL_MODULE_SUFFIX := .so +LOCAL_CHECK_ELF_FILES := false +ifneq ($5,) +LOCAL_MULTILIB := $5 +endif +include $$(BUILD_PREBUILT) +endef + define install-va-video-libs include $$(CLEAR_VARS) LOCAL_MODULE := $1 @@ -87,7 +106,7 @@ LOCAL_OVERRIDES_PACKAGES := $1 include $$(BUILD_PREBUILT) endef -ifneq ($(wildcard $(LOCAL_PATH)/vendor/lib),) +ifneq ($(wildcard $(LOCAL_PATH)/system/vendor/lib),) VA_MULTILIB := both else VA_MULTILIB := first @@ -104,8 +123,8 @@ libGLESv1_CM_default \ $(foreach lib, $(egl_libs), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/egl/$(lib).so, \ - vendor/lib/egl/$(lib).so, \ + system/vendor/lib64/egl/$(lib).so, \ + system/vendor/lib/egl/$(lib).so, \ egl, \ $(VA_MULTILIB)))) @@ -117,8 +136,8 @@ hwcomposer.default \ $(foreach lib, $(hw_libs), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/hw/$(lib).so, \ - vendor/lib/hw/$(lib).so, \ + system/vendor/lib64/hw/$(lib).so, \ + system/vendor/lib/hw/$(lib).so, \ hw, \ $(VA_MULTILIB)))) @@ -132,13 +151,12 @@ libsutu_display \ libcreatesurface \ libvaANDROID_WSEGL \ libvalloc \ -libDisplayServer \ $(foreach lib, $(um_libs), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/$(lib).so, \ - vendor/lib/$(lib).so, \ + system/vendor/lib64/$(lib).so, \ + system/vendor/lib/$(lib).so, \ , \ $(VA_MULTILIB)))) @@ -148,7 +166,7 @@ gpu_config.sh \ $(foreach bin, $(gpu_bins), \ $(eval $(call install-va-bins, \ $(bin), \ - vendor/bin/$(bin), \ + system/vendor/bin/$(bin), \ , \ ))) @@ -158,56 +176,13 @@ va_gfx.ini \ $(foreach config, $(va_config), \ $(eval $(call install-va-configs, \ $(config), \ - vendor/etc/$(config), \ + system/vendor/etc/$(config), \ , \ $(TARGET_OUT_VENDOR_ETC)))) # VIDEO -# NDK - -ndk_libs := \ -libc++_shared \ -$(foreach lib, $(ndk_libs), \ - $(eval $(call install-va-shared-libs, \ - $(lib), \ - vendor/lib64/$(lib).so, \ - vendor/lib/$(lib).so, \ - , \ - $(VA_MULTILIB)))) - -# FFMPEG -ffmpeg_libs := \ -libavdevice \ -libavfilter \ -libswscale \ -libavutil \ -libswresample \ -libavformat \ -libavcodec \ -libpostproc \ - -$(foreach lib, $(ffmpeg_libs), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/lib64/$(lib).so), \ - $(eval $(call install-va-shared-libs, \ - $(lib), \ - vendor/lib64/$(lib).so, \ - , \ - , \ - )))) - -video_drv_libs := \ -va_drv_video \ - -$(foreach lib, $(video_drv_libs), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/lib64/$(lib).so), \ - $(eval $(call install-va-shared-libs, \ - $(lib), \ - vendor/lib64/$(lib).so, \ - , \ - , \ - )))) # vame vame_libs := \ @@ -217,10 +192,10 @@ libvame \ libvaml \ $(foreach lib, $(vame_libs), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/lib64/vame/lib/$(lib).so), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/lib64/vame/lib/$(lib).so), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/vame/lib/$(lib).so, \ + system/vendor/lib64/vame/lib/$(lib).so, \ , \ vame/lib, \ )))) @@ -229,26 +204,25 @@ vame_config := \ vslog.cfg \ $(foreach config, $(vame_config), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/etc/$(config)), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/etc/$(config)), \ $(eval $(call install-va-configs, \ $(config), \ - vendor/etc/$(config), \ + system/vendor/etc/$(config), \ , \ $(TARGET_OUT_VENDOR_ETC))))) # va libs va_libs := \ -libvaccrt \ libvmpp-enc \ libvmpp-dec \ $(foreach lib, $(va_libs), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/lib64/$(lib).so), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/lib64/$(lib).so), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/$(lib).so, \ - vendor/lib/$(lib).so, \ + system/vendor/lib64/$(lib).so, \ + system/vendor/lib/$(lib).so, \ , \ $(VA_MULTILIB))))) @@ -260,11 +234,11 @@ libVa_OMX_VideoDec_HW \ va_omx_component \ $(foreach lib, $(omx_libs), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/lib64/$(lib).so), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/lib64/$(lib).so), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/$(lib).so, \ - vendor/lib/$(lib).so, \ + system/vendor/lib64/$(lib).so, \ + system/vendor/lib/$(lib).so, \ , \ $(VA_MULTILIB))))) @@ -272,10 +246,10 @@ omx_config := \ media_codecs_va_video.xml \ $(foreach config, $(omx_config), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/etc/$(config)), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/etc/$(config)), \ $(eval $(call install-va-configs, \ $(config), \ - vendor/etc/$(config), \ + system/vendor/etc/$(config), \ , \ $(TARGET_OUT_VENDOR_ETC))))) @@ -289,11 +263,11 @@ codec2_libs := \ libcodec2_default_component \ $(foreach lib, $(codec2_libs), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/lib64/$(lib).so), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/lib64/$(lib).so), \ $(eval $(call install-va-shared-libs, \ $(lib), \ - vendor/lib64/$(lib).so, \ - vendor/lib/$(lib).so, \ + system/vendor/lib64/$(lib).so, \ + system/vendor/lib/$(lib).so, \ , \ $(VA_MULTILIB))))) @@ -301,10 +275,10 @@ codec2_service := \ android.hardware.media.c2@1.0-service-default \ $(foreach srv, $(codec2_service), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/bin/hw/$(srv)), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/bin/hw/$(srv)), \ $(eval $(call install-va-bins, \ $(srv), \ - vendor/bin/hw/$(srv), \ + system/vendor/bin/hw/$(srv), \ , \ hw)))) @@ -313,10 +287,10 @@ codec2_config := \ default_enc_params.json \ $(foreach config, $(codec2_config), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/etc/$(config)), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/etc/$(config)), \ $(eval $(call install-va-configs, \ $(config), \ - vendor/etc/$(config), \ + system/vendor/etc/$(config), \ , \ $(TARGET_OUT_VENDOR_ETC))))) @@ -324,10 +298,10 @@ codec2_init := \ android.hardware.media.c2@1.0-service-default.rc \ $(foreach srv, $(codec2_init), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/etc/init/$(srv)), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/etc/init/$(srv)), \ $(eval $(call install-va-configs, \ $(srv), \ - vendor/etc/init/$(srv), \ + system/vendor/etc/init/$(srv), \ , \ $(TARGET_OUT_VENDOR_ETC)/init)))) @@ -335,9 +309,31 @@ codec2_xml := \ android.hardware.media.c2@1.0-service-default.xml \ $(foreach srv, $(codec2_xml), \ - $(if $(wildcard $(LOCAL_PATH)/vendor/etc/vintf/manifest/$(srv)), \ + $(if $(wildcard $(LOCAL_PATH)/system/vendor/etc/vintf/manifest/$(srv)), \ $(eval $(call install-va-configs, \ $(srv), \ - vendor/etc/vintf/manifest/$(srv), \ + system/vendor/etc/vintf/manifest/$(srv), \ , \ $(TARGET_OUT_VENDOR_ETC)/vintf/manifest)))) + +# system libs: FFMPEG c2 va display_server +system_libs := \ +libavdevice \ +libavfilter \ +libswscale \ +libavutil \ +libswresample \ +libavformat \ +libavcodec \ +libpostproc \ +libDisplayServer \ +va_drv_video \ + +$(foreach lib, $(system_libs), \ + $(if $(wildcard $(LOCAL_PATH)/system/lib64/$(lib).so), \ + $(eval $(call install-codec-libs-to-system, \ + $(lib), \ + system/lib64/$(lib).so, \ + system/lib/$(lib).so, \ + , \ + $(VA_MULTILIB))))) \ No newline at end of file -- Gitee