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

Commit 69b281d5 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

Adapt SurfaceControl to libgui API for display info

Bug: 144601064
Test: dumpsys display
Change-Id: I477e0e3126cc15eb5f120610b4e6b6b1568df389
parent a5239e96
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -42,10 +42,10 @@

#include <android-base/properties.h>

#include <ui/DisplayConfig.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/DisplayInfo.h>

#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
@@ -283,16 +283,19 @@ status_t BootAnimation::readyToRun() {

    mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
    if (mDisplayToken == nullptr)
        return -1;
        return NAME_NOT_FOUND;

    DisplayInfo dinfo;
    status_t status = SurfaceComposerClient::getDisplayInfo(mDisplayToken, &dinfo);
    if (status)
        return -1;
    DisplayConfig displayConfig;
    const status_t error =
            SurfaceComposerClient::getActiveDisplayConfig(mDisplayToken, &displayConfig);
    if (error != NO_ERROR)
        return error;

    const ui::Size& resolution = displayConfig.resolution;

    // create the native surface
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
            resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);

    SurfaceComposerClient::Transaction t;

+38 −123
Original line number Diff line number Diff line
@@ -152,7 +152,8 @@ public final class SurfaceControl implements Parcelable {
            int L, int T, int R, int B);
    private static native void nativeSetDisplaySize(long transactionObj, IBinder displayToken,
            int width, int height);
    private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
    private static native SurfaceControl.DisplayInfo nativeGetDisplayInfo(IBinder displayToken);
    private static native SurfaceControl.DisplayConfig[] nativeGetDisplayConfigs(
            IBinder displayToken);
    private static native DisplayedContentSamplingAttributes
            nativeGetDisplayedContentSamplingAttributes(IBinder displayToken);
@@ -1278,158 +1279,72 @@ public final class SurfaceControl implements Parcelable {
                Integer.toHexString(System.identityHashCode(this));
    }

    /*
     * set display parameters.
     * needs to be inside open/closeTransaction block
     */

    /**
     * Describes the properties of a physical display known to surface flinger.
     * @hide
     */
    public static final class PhysicalDisplayInfo {
        /**
         * @hide
         */
        @UnsupportedAppUsage
        public int width;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public int height;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public float refreshRate;

    /**
     * Immutable information about physical display.
     *
     * @hide
     */
        @UnsupportedAppUsage
    public static final class DisplayInfo {
        public float density;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public float xDpi;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public float yDpi;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public boolean secure;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public long appVsyncOffsetNanos;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public long presentationDeadlineNanos;

        /**
         * @hide
         */
        @UnsupportedAppUsage
        public PhysicalDisplayInfo() {
        @Override
        public String toString() {
            return "DisplayInfo{density=" + density + ", secure=" + secure + "}";
        }

        /**
         * @hide
         */
        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
            copyFrom(other);
    }

    /**
     * Configuration supported by physical display.
     *
     * @hide
     */
        @Override
        public boolean equals(Object o) {
            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
        }
    public static final class DisplayConfig {
        public int width;
        public int height;
        public float xDpi;
        public float yDpi;

        /**
         * @hide
         */
        public boolean equals(PhysicalDisplayInfo other) {
            return other != null
                    && width == other.width
                    && height == other.height
                    && refreshRate == other.refreshRate
                    && density == other.density
                    && xDpi == other.xDpi
                    && yDpi == other.yDpi
                    && secure == other.secure
                    && appVsyncOffsetNanos == other.appVsyncOffsetNanos
                    && presentationDeadlineNanos == other.presentationDeadlineNanos;
        }
        public float refreshRate;
        public long appVsyncOffsetNanos;
        public long presentationDeadlineNanos;

        /**
         * @hide
         */
        @Override
        public int hashCode() {
            return 0; // don't care
        public String toString() {
            return "DisplayConfig{width=" + width
                    + ", height=" + height
                    + ", xDpi=" + xDpi
                    + ", yDpi=" + yDpi
                    + ", refreshRate=" + refreshRate
                    + ", appVsyncOffsetNanos=" + appVsyncOffsetNanos
                    + ", presentationDeadlineNanos=" + presentationDeadlineNanos + "}";
        }

        /**
         * @hide
         */
        public void copyFrom(PhysicalDisplayInfo other) {
            width = other.width;
            height = other.height;
            refreshRate = other.refreshRate;
            density = other.density;
            xDpi = other.xDpi;
            yDpi = other.yDpi;
            secure = other.secure;
            appVsyncOffsetNanos = other.appVsyncOffsetNanos;
            presentationDeadlineNanos = other.presentationDeadlineNanos;
    }

    /**
     * @hide
     */
        @Override
        public String toString() {
            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
                    + ", appVsyncOffset " + appVsyncOffsetNanos
                    + ", bufferDeadline " + presentationDeadlineNanos + "}";
    public static void setDisplayPowerMode(IBinder displayToken, int mode) {
        if (displayToken == null) {
            throw new IllegalArgumentException("displayToken must not be null");
        }
        nativeSetDisplayPowerMode(displayToken, mode);
    }

    /**
     * @hide
     */
    public static void setDisplayPowerMode(IBinder displayToken, int mode) {
    public static SurfaceControl.DisplayInfo getDisplayInfo(IBinder displayToken) {
        if (displayToken == null) {
            throw new IllegalArgumentException("displayToken must not be null");
        }
        nativeSetDisplayPowerMode(displayToken, mode);
        return nativeGetDisplayInfo(displayToken);
    }

    /**
     * @hide
     */
    @UnsupportedAppUsage
    public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
    public static SurfaceControl.DisplayConfig[] getDisplayConfigs(IBinder displayToken) {
        if (displayToken == null) {
            throw new IllegalArgumentException("displayToken must not be null");
        }
@@ -1825,7 +1740,7 @@ public final class SurfaceControl implements Parcelable {
    }

    /**
     * TODO(116025192): Remove this stopgap once framework is display-agnostic.
     * TODO(b/116025192): Remove this stopgap once framework is display-agnostic.
     *
     * @hide
     */
+71 −50
Original line number Diff line number Diff line
@@ -22,20 +22,22 @@
#include "android_hardware_input_InputWindowHandle.h"
#include "core_jni_helpers.h"

#include <memory>

#include <android-base/chrono_utils.h>
#include <android/graphics/region.h>
#include <android_runtime/AndroidRuntime.h>
#include <android-base/chrono_utils.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_view_SurfaceSession.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <jni.h>
#include <memory>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include <stdio.h>
#include <system/graphics.h>
#include <ui/ConfigStoreTypes.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayedFrameStats.h>
#include <ui/FrameStats.h>
@@ -60,19 +62,24 @@ static void doThrowIAE(JNIEnv* env, const char* msg = nullptr) {
static const char* const OutOfResourcesException =
    "android/view/Surface$OutOfResourcesException";

static struct {
    jclass clazz;
    jmethodID ctor;
    jfieldID density;
    jfieldID secure;
} gDisplayInfoClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
    jfieldID width;
    jfieldID height;
    jfieldID refreshRate;
    jfieldID density;
    jfieldID xDpi;
    jfieldID yDpi;
    jfieldID secure;
    jfieldID refreshRate;
    jfieldID appVsyncOffsetNanos;
    jfieldID presentationDeadlineNanos;
} gPhysicalDisplayInfoClassInfo;
} gDisplayConfigClassInfo;

static struct {
    jfieldID bottom;
@@ -766,37 +773,46 @@ static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
    }
}

static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
        jobject tokenObj) {
    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    if (token == NULL) return NULL;
static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
    DisplayInfo info;
    if (const auto token = ibinderForJavaObject(env, tokenObj);
        !token || SurfaceComposerClient::getDisplayInfo(token, &info) != NO_ERROR) {
        return nullptr;
    }

    Vector<DisplayInfo> configs;
    if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR ||
            configs.size() == 0) {
        return NULL;
    jobject object = env->NewObject(gDisplayInfoClassInfo.clazz, gDisplayInfoClassInfo.ctor);
    env->SetFloatField(object, gDisplayInfoClassInfo.density, info.density);
    env->SetBooleanField(object, gDisplayInfoClassInfo.secure, info.secure);
    return object;
}

static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz, jobject tokenObj) {
    Vector<DisplayConfig> configs;
    if (const auto token = ibinderForJavaObject(env, tokenObj); !token ||
        SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR ||
        configs.isEmpty()) {
        return nullptr;
    }

    jobjectArray configArray = env->NewObjectArray(configs.size(),
            gPhysicalDisplayInfoClassInfo.clazz, NULL);
    jobjectArray configArray =
            env->NewObjectArray(configs.size(), gDisplayConfigClassInfo.clazz, nullptr);

    for (size_t c = 0; c < configs.size(); ++c) {
        const DisplayInfo& info = configs[c];
        jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz,
                gPhysicalDisplayInfoClassInfo.ctor);
        env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
        env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
        env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
        env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
        env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos,
                info.appVsyncOffset);
        env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos,
                info.presentationDeadline);
        env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
        env->DeleteLocalRef(infoObj);
        const DisplayConfig& config = configs[c];
        jobject object =
                env->NewObject(gDisplayConfigClassInfo.clazz, gDisplayConfigClassInfo.ctor);
        env->SetIntField(object, gDisplayConfigClassInfo.width, config.resolution.getWidth());
        env->SetIntField(object, gDisplayConfigClassInfo.height, config.resolution.getHeight());
        env->SetFloatField(object, gDisplayConfigClassInfo.xDpi, config.xDpi);
        env->SetFloatField(object, gDisplayConfigClassInfo.yDpi, config.yDpi);

        env->SetFloatField(object, gDisplayConfigClassInfo.refreshRate, config.refreshRate);
        env->SetLongField(object, gDisplayConfigClassInfo.appVsyncOffsetNanos,
                          config.appVsyncOffset);
        env->SetLongField(object, gDisplayConfigClassInfo.presentationDeadlineNanos,
                          config.presentationDeadline);
        env->SetObjectArrayElement(configArray, static_cast<jsize>(c), object);
        env->DeleteLocalRef(object);
    }

    return configArray;
@@ -1409,7 +1425,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeSetDisplayProjection },
    {"nativeSetDisplaySize", "(JLandroid/os/IBinder;II)V",
            (void*)nativeSetDisplaySize },
    {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayInfo;",
            (void*)nativeGetDisplayInfo },
    {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$DisplayConfig;",
            (void*)nativeGetDisplayConfigs },
    {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
            (void*)nativeGetActiveConfig },
@@ -1507,21 +1525,24 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
            sSurfaceControlMethods, NELEM(sSurfaceControlMethods));

    jclass clazz = FindClassOrDie(env, "android/view/SurfaceControl$PhysicalDisplayInfo");
    gPhysicalDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    gPhysicalDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env,
            gPhysicalDisplayInfoClassInfo.clazz, "<init>", "()V");
    gPhysicalDisplayInfoClassInfo.width =       GetFieldIDOrDie(env, clazz, "width", "I");
    gPhysicalDisplayInfoClassInfo.height =      GetFieldIDOrDie(env, clazz, "height", "I");
    gPhysicalDisplayInfoClassInfo.refreshRate = GetFieldIDOrDie(env, clazz, "refreshRate", "F");
    gPhysicalDisplayInfoClassInfo.density =     GetFieldIDOrDie(env, clazz, "density", "F");
    gPhysicalDisplayInfoClassInfo.xDpi =        GetFieldIDOrDie(env, clazz, "xDpi", "F");
    gPhysicalDisplayInfoClassInfo.yDpi =        GetFieldIDOrDie(env, clazz, "yDpi", "F");
    gPhysicalDisplayInfoClassInfo.secure =      GetFieldIDOrDie(env, clazz, "secure", "Z");
    gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos = GetFieldIDOrDie(env,
            clazz, "appVsyncOffsetNanos", "J");
    gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env,
            clazz, "presentationDeadlineNanos", "J");
    jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayInfo");
    gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
    gDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
    gDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
    gDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");

    jclass configClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayConfig");
    gDisplayConfigClassInfo.clazz = MakeGlobalRefOrDie(env, configClazz);
    gDisplayConfigClassInfo.ctor = GetMethodIDOrDie(env, configClazz, "<init>", "()V");
    gDisplayConfigClassInfo.width = GetFieldIDOrDie(env, configClazz, "width", "I");
    gDisplayConfigClassInfo.height = GetFieldIDOrDie(env, configClazz, "height", "I");
    gDisplayConfigClassInfo.xDpi = GetFieldIDOrDie(env, configClazz, "xDpi", "F");
    gDisplayConfigClassInfo.yDpi = GetFieldIDOrDie(env, configClazz, "yDpi", "F");
    gDisplayConfigClassInfo.refreshRate = GetFieldIDOrDie(env, configClazz, "refreshRate", "F");
    gDisplayConfigClassInfo.appVsyncOffsetNanos =
            GetFieldIDOrDie(env, configClazz, "appVsyncOffsetNanos", "J");
    gDisplayConfigClassInfo.presentationDeadlineNanos =
            GetFieldIDOrDie(env, configClazz, "presentationDeadlineNanos", "J");

    jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect");
    gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I");
+42 −32
Original line number Diff line number Diff line
@@ -22,43 +22,50 @@ namespace android {
namespace uirenderer {
namespace test {

static const int IDENT_DISPLAYEVENT = 1;

static android::DisplayInfo DUMMY_DISPLAY{
        1080,           // w
        1920,           // h
        320.0,          // xdpi
        320.0,          // ydpi
        60.0,           // fps
        2.0,            // density
        ui::ROTATION_0, // orientation
        false,          // secure?
        0,              // appVsyncOffset
        0,              // presentationDeadline
};

DisplayInfo getInternalDisplay() {
#if !HWUI_NULL_GPU
    DisplayInfo display;
    const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
    LOG_ALWAYS_FATAL_IF(token == nullptr,
                        "Failed to get display info because internal display is disconnected\n");
    status_t status = SurfaceComposerClient::getDisplayInfo(token, &display);
    LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
    return display;
const DisplayInfo& getDisplayInfo() {
    static DisplayInfo info = [] {
        DisplayInfo info;
#if HWUI_NULL_GPU
        info.density = 2.f;
#else
    return DUMMY_DISPLAY;
        const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
        LOG_ALWAYS_FATAL_IF(!token, "%s: No internal display", __FUNCTION__);

        const status_t status = SurfaceComposerClient::getDisplayInfo(token, &info);
        LOG_ALWAYS_FATAL_IF(status, "%s: Failed to get display info", __FUNCTION__);
#endif
        return info;
    }();

    return info;
}

// Initialize to a dummy default
android::DisplayInfo gDisplay = DUMMY_DISPLAY;
const DisplayConfig& getActiveDisplayConfig() {
    static DisplayConfig config = [] {
        DisplayConfig config;
#if HWUI_NULL_GPU
        config.resolution = ui::Size(1080, 1920);
        config.xDpi = config.yDpi = 320.f;
        config.refreshRate = 60.f;
#else
        const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
        LOG_ALWAYS_FATAL_IF(!token, "%s: No internal display", __FUNCTION__);

        const status_t status = SurfaceComposerClient::getActiveDisplayConfig(token, &config);
        LOG_ALWAYS_FATAL_IF(status, "%s: Failed to get active display config", __FUNCTION__);
#endif
        return config;
    }();

    return config;
}

TestContext::TestContext() {
    mLooper = new Looper(true);
    mSurfaceComposerClient = new SurfaceComposerClient();
    mLooper->addFd(mDisplayEventReceiver.getFd(), IDENT_DISPLAYEVENT, Looper::EVENT_INPUT, nullptr,
                   nullptr);

    constexpr int EVENT_ID = 1;
    mLooper->addFd(mDisplayEventReceiver.getFd(), EVENT_ID, Looper::EVENT_INPUT, nullptr, nullptr);
}

TestContext::~TestContext() {}
@@ -79,8 +86,10 @@ void TestContext::createSurface() {
}

void TestContext::createWindowSurface() {
    mSurfaceControl = mSurfaceComposerClient->createSurface(String8("HwuiTest"), gDisplay.w,
                                                            gDisplay.h, PIXEL_FORMAT_RGBX_8888);
    const ui::Size& resolution = getActiveDisplayResolution();
    mSurfaceControl =
            mSurfaceComposerClient->createSurface(String8("HwuiTest"), resolution.getWidth(),
                                                  resolution.getHeight(), PIXEL_FORMAT_RGBX_8888);

    SurfaceComposerClient::Transaction t;
    t.setLayer(mSurfaceControl, 0x7FFFFFF).show(mSurfaceControl).apply();
@@ -94,7 +103,8 @@ void TestContext::createOffscreenSurface() {
    producer->setMaxDequeuedBufferCount(3);
    producer->setAsyncMode(true);
    mConsumer = new BufferItemConsumer(consumer, GRALLOC_USAGE_HW_COMPOSER, 4);
    mConsumer->setDefaultBufferSize(gDisplay.w, gDisplay.h);
    const ui::Size& resolution = getActiveDisplayResolution();
    mConsumer->setDefaultBufferSize(resolution.getWidth(), resolution.getHeight());
    mSurface = new Surface(producer);
}

+8 −3
Original line number Diff line number Diff line
@@ -23,20 +23,25 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
#include <ui/DisplayConfig.h>
#include <ui/DisplayInfo.h>
#include <utils/Looper.h>

#include <atomic>
#include <thread>

#define dp(x) ((x) * android::uirenderer::test::getDisplayInfo().density)

namespace android {
namespace uirenderer {
namespace test {

extern DisplayInfo gDisplay;
#define dp(x) ((x)*android::uirenderer::test::gDisplay.density)
const DisplayInfo& getDisplayInfo();
const DisplayConfig& getActiveDisplayConfig();

DisplayInfo getInternalDisplay();
inline const ui::Size& getActiveDisplayResolution() {
    return getActiveDisplayConfig().resolution;
}

class TestContext {
public:
Loading