Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a904b83 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

SurfaceFlinger: get rid of LayerStats

LayerStats is not in use, so let's just remove it. If later SurfaceTracing has
been moved back to main thread, we could probably plumb HWC layer stats into
SurfaceTracing. For now, if we are interested in any statistical HWC stats, we
could add that into TimeStats so that we get the stats from the field as well.

Test: build, flash and boot
Change-Id: Iff418f60bc22d8867294f919699300cf25eee258
parent 54322025
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -138,7 +138,6 @@ filegroup {
        "Layer.cpp",
        "LayerProtoHelper.cpp",
        "LayerRejecter.cpp",
        "LayerStats.cpp",
        "LayerVector.cpp",
        "MonitoredProducer.cpp",
        "NativeWindowSurface.cpp",
+0 −29
Original line number Diff line number Diff line
@@ -1932,35 +1932,6 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
    }
}

void Layer::writeToProtoCompositionState(LayerProto* layerInfo,
                                         const sp<DisplayDevice>& displayDevice,
                                         uint32_t traceFlags) const {
    auto outputLayer = findOutputLayerForDisplay(displayDevice);
    if (!outputLayer) {
        return;
    }

    writeToProtoDrawingState(layerInfo, traceFlags);
    writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags);

    const auto& compositionState = outputLayer->getState();

    const Rect& frame = compositionState.displayFrame;
    LayerProtoHelper::writeToProto(frame, [&]() { return layerInfo->mutable_hwc_frame(); });

    const FloatRect& crop = compositionState.sourceCrop;
    LayerProtoHelper::writeToProto(crop, [&]() { return layerInfo->mutable_hwc_crop(); });

    const int32_t transform =
            getCompositionLayer() ? static_cast<int32_t>(compositionState.bufferTransform) : 0;
    layerInfo->set_hwc_transform(transform);

    const int32_t compositionType =
            static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
                                                      : Hwc2::IComposerClient::Composition::CLIENT);
    layerInfo->set_hwc_composition_type(compositionType);
}

bool Layer::isRemovedFromCurrentState() const  {
    return mRemovedFromCurrentState;
}
+0 −5
Original line number Diff line number Diff line
@@ -440,11 +440,6 @@ public:
    // thread.
    void writeToProtoDrawingState(LayerProto* layerInfo,
                                  uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
    // Write states that are modified by the main thread. This includes drawing
    // state as well as buffer data and composition data for layers on the specified
    // display. This should be called in the main or tracing thread.
    void writeToProtoCompositionState(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice,
                                      uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
    // Write drawing or current state. If writing current state, the caller should hold the
    // external mStateLock. If writing drawing state, this function should be called on the
    // main or tracing thread.
+0 −233
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */
#undef LOG_TAG
#define LOG_TAG "LayerStats"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "LayerStats.h"
#include "DisplayHardware/HWComposer.h"
#include "ui/DebugUtils.h"

#include <android-base/stringprintf.h>
#include <log/log.h>
#include <utils/Trace.h>

namespace android {

using base::StringAppendF;
using base::StringPrintf;

void LayerStats::enable() {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mMutex);
    if (mEnabled) return;
    mLayerShapeStatsMap.clear();
    mEnabled = true;
    ALOGD("Logging enabled");
}

void LayerStats::disable() {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mMutex);
    if (!mEnabled) return;
    mEnabled = false;
    ALOGD("Logging disabled");
}

void LayerStats::clear() {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mMutex);
    mLayerShapeStatsMap.clear();
    ALOGD("Cleared current layer stats");
}

bool LayerStats::isEnabled() {
    return mEnabled;
}

void LayerStats::traverseLayerTreeStatsLocked(
        const std::vector<LayerProtoParser::Layer*>& layerTree,
        const LayerProtoParser::LayerGlobal& layerGlobal,
        std::vector<std::string>* const outLayerShapeVec) {
    for (const auto& layer : layerTree) {
        if (!layer) continue;
        traverseLayerTreeStatsLocked(layer->children, layerGlobal, outLayerShapeVec);
        std::string key = "";
        StringAppendF(&key, ",%s", layer->type.c_str());
        StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
        StringAppendF(&key, ",%d", layer->isProtected);
        StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
        StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
        StringAppendF(&key, ",%s", layer->dataspace.c_str());
        StringAppendF(&key, ",%s",
                      destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0], true));
        StringAppendF(&key, ",%s",
                      destinationLocation(layer->hwcFrame.top, layerGlobal.resolution[1], false));
        StringAppendF(&key, ",%s",
                      destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
                                      layerGlobal.resolution[0], true));
        StringAppendF(&key, ",%s",
                      destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
                                      layerGlobal.resolution[1], false));
        StringAppendF(&key, ",%s", scaleRatioWH(layer).c_str());
        StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));

        outLayerShapeVec->push_back(key);
        ALOGV("%s", key.c_str());
    }
}

void LayerStats::logLayerStats(const LayersProto& layersProto) {
    ATRACE_CALL();
    ALOGV("Logging");
    auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto);
    auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
    std::vector<std::string> layerShapeVec;

    std::lock_guard<std::mutex> lock(mMutex);
    traverseLayerTreeStatsLocked(layerTree.topLevelLayers, layerGlobal, &layerShapeVec);

    std::string layerShapeKey =
            StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
                         layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(),
                         layerTransform(layerGlobal.globalTransform));
    ALOGV("%s", layerShapeKey.c_str());

    std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater<std::string>());
    for (auto const& s : layerShapeVec) {
        layerShapeKey += s;
    }

    mLayerShapeStatsMap[layerShapeKey]++;
}

void LayerStats::dump(std::string& result) {
    ATRACE_CALL();
    ALOGD("Dumping");
    std::lock_guard<std::mutex> lock(mMutex);
    result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n");
    result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,");
    result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n");
    for (auto& u : mLayerShapeStatsMap) {
        StringAppendF(&result, "%u,%s\n", u.second, u.first.c_str());
    }
}

const char* LayerStats::destinationLocation(int32_t location, int32_t range, bool isHorizontal) {
    static const char* locationArray[8] = {"0", "1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8"};
    int32_t ratio = location * 8 / range;
    if (ratio < 0) return "N/A";
    if (isHorizontal) {
        // X location is divided into 4 buckets {"0", "1/4", "1/2", "3/4"}
        if (ratio > 6) return "3/4";
        // use index 0, 2, 4, 6
        return locationArray[ratio & ~1];
    }
    if (ratio > 7) return "7/8";
    return locationArray[ratio];
}

const char* LayerStats::destinationSize(int32_t size, int32_t range, bool isWidth) {
    static const char* sizeArray[8] = {"1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"};
    int32_t ratio = size * 8 / range;
    if (ratio < 0) return "N/A";
    if (isWidth) {
        // width is divided into 4 buckets {"1/4", "1/2", "3/4", "1"}
        if (ratio > 6) return "1";
        // use index 1, 3, 5, 7
        return sizeArray[ratio | 1];
    }
    if (ratio > 7) return "1";
    return sizeArray[ratio];
}

const char* LayerStats::layerTransform(int32_t transform) {
    return getTransformName(static_cast<hwc_transform_t>(transform));
}

const char* LayerStats::layerCompositionType(int32_t compositionType) {
    return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
}

std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
    return decodePixelFormat(pixelFormat);
}

std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
    if (!layer->type.compare("ColorLayer")) return "N/A,N/A";
    std::string ret = "";
    if (isRotated(layer->hwcTransform)) {
        ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left,
                          static_cast<int32_t>(layer->hwcCrop.bottom - layer->hwcCrop.top));
        ret += ",";
        ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top,
                          static_cast<int32_t>(layer->hwcCrop.right - layer->hwcCrop.left));
    } else {
        ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left,
                          static_cast<int32_t>(layer->hwcCrop.right - layer->hwcCrop.left));
        ret += ",";
        ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top,
                          static_cast<int32_t>(layer->hwcCrop.bottom - layer->hwcCrop.top));
    }
    return ret;
}

const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale) {
    // Make scale buckets from <1/64 to >= 16, to avoid floating point
    // calculation, x64 on destinationScale first
    int32_t scale = destinationScale * 64 / sourceScale;
    if (!scale) return "<1/64";
    if (scale < 2) return "1/64";
    if (scale < 4) return "1/32";
    if (scale < 8) return "1/16";
    if (scale < 16) return "1/8";
    if (scale < 32) return "1/4";
    if (scale < 64) return "1/2";
    if (scale < 128) return "1";
    if (scale < 256) return "2";
    if (scale < 512) return "4";
    if (scale < 1024) return "8";
    return ">=16";
}

const char* LayerStats::alpha(float a) {
    if (a == 1.0f) return "1.0";
    if (a > 0.9f) return "0.99";
    if (a > 0.8f) return "0.9";
    if (a > 0.7f) return "0.8";
    if (a > 0.6f) return "0.7";
    if (a > 0.5f) return "0.6";
    if (a > 0.4f) return "0.5";
    if (a > 0.3f) return "0.4";
    if (a > 0.2f) return "0.3";
    if (a > 0.1f) return "0.2";
    if (a > 0.0f) return "0.1";
    return "0.0";
}

bool LayerStats::isRotated(int32_t transform) {
    return transform & HWC_TRANSFORM_ROT_90;
}

bool LayerStats::isVFlipped(int32_t transform) {
    return transform & HWC_TRANSFORM_FLIP_V;
}

bool LayerStats::isHFlipped(int32_t transform) {
    return transform & HWC_TRANSFORM_FLIP_H;
}

}  // namespace android
+0 −75
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */

#pragma once

#include <layerproto/LayerProtoHeader.h>
#include <layerproto/LayerProtoParser.h>
#include <mutex>
#include <unordered_map>

using namespace android::surfaceflinger;

namespace android {

class LayerStats {
public:
    void enable();
    void disable();
    void clear();
    bool isEnabled();
    void logLayerStats(const LayersProto& layersProto);
    void dump(std::string& result);

private:
    // Traverse layer tree to get all visible layers' stats
    void traverseLayerTreeStatsLocked(
            const std::vector<LayerProtoParser::Layer*>& layerTree,
            const LayerProtoParser::LayerGlobal& layerGlobal,
            std::vector<std::string>* const outLayerShapeVec);
    // Convert layer's top-left position into 8x8 percentage of the display
    static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal);
    // Convert layer's size into 8x8 percentage of the display
    static const char* destinationSize(int32_t size, int32_t range, bool isWidth);
    // Return the name of the transform
    static const char* layerTransform(int32_t transform);
    // Return the name of the composition type
    static const char* layerCompositionType(int32_t compositionType);
    // Return the name of the pixel format
    static std::string layerPixelFormat(int32_t pixelFormat);
    // Calculate scale ratios of layer's width/height with rotation information
    static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
    // Calculate scale ratio from source to destination and convert to string
    static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale);
    // Bucket the alpha into designed buckets
    static const char* alpha(float a);
    // Return whether the original buffer is rotated in final composition
    static bool isRotated(int32_t transform);
    // Return whether the original buffer is V-flipped in final composition
    static bool isVFlipped(int32_t transform);
    // Return whether the original buffer is H-flipped in final composition
    static bool isHFlipped(int32_t transform);

    bool mEnabled = false;
    // Protect mLayersStatsMap
    std::mutex mMutex;
    // Hashmap for tracking the frame(layer shape) stats
    // KEY is a concatenation of all layers' properties within a frame
    // VALUE is the number of times this particular set has been scanned out
    std::unordered_map<std::string, uint32_t> mLayerShapeStatsMap;
};

}  // namespace android
Loading