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

Commit 0f6f7184 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6047681 from 75bed1e6 to rvc-release

Change-Id: I41cc37054d70ae66071beba9454f15febc02c9cb
parents 67077188 75bed1e6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ cc_library_shared {
        "ConsumerBase.cpp",
        "CpuConsumer.cpp",
        "DebugEGLImageTracker.cpp",
        "DisplayEventDispatcher.cpp",
        "DisplayEventReceiver.cpp",
        "GLConsumer.cpp",
        "GuiConfig.cpp",
+156 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.
 */

#define LOG_TAG "DisplayEventDispatcher"

#include <cinttypes>
#include <cstdint>

#include <gui/DisplayEventDispatcher.h>
#include <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
#include <utils/Looper.h>

#include <utils/Timers.h>

namespace android {

// Number of events to read at a time from the DisplayEventDispatcher pipe.
// The value should be large enough that we can quickly drain the pipe
// using just a few large reads.
static const size_t EVENT_BUFFER_SIZE = 100;

DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
                                               ISurfaceComposer::VsyncSource vsyncSource,
                                               ISurfaceComposer::ConfigChanged configChanged)
      : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) {
    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}

status_t DisplayEventDispatcher::initialize() {
    status_t result = mReceiver.initCheck();
    if (result) {
        ALOGW("Failed to initialize display event receiver, status=%d", result);
        return result;
    }

    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

void DisplayEventDispatcher::dispose() {
    ALOGV("dispatcher %p ~ Disposing display event dispatcher.", this);

    if (!mReceiver.initCheck()) {
        mLooper->removeFd(mReceiver.getFd());
    }
}

status_t DisplayEventDispatcher::scheduleVsync() {
    if (!mWaitingForVsync) {
        ALOGV("dispatcher %p ~ Scheduling vsync.", this);

        // Drain all pending events.
        nsecs_t vsyncTimestamp;
        PhysicalDisplayId vsyncDisplayId;
        uint32_t vsyncCount;
        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
                  ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
        }

        status_t status = mReceiver.requestNextVsync();
        if (status) {
            ALOGW("Failed to request next vsync, status=%d", status);
            return status;
        }

        mWaitingForVsync = true;
    }
    return OK;
}

int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
        ALOGE("Display event receiver pipe was closed or an error occurred.  "
              "events=0x%x",
              events);
        return 0; // remove the callback
    }

    if (!(events & Looper::EVENT_INPUT)) {
        ALOGW("Received spurious callback for unhandled poll event.  "
              "events=0x%x",
              events);
        return 1; // keep the callback
    }

    // Drain all pending events, keep the last vsync.
    nsecs_t vsyncTimestamp;
    PhysicalDisplayId vsyncDisplayId;
    uint32_t vsyncCount;
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
              ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d",
              this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);
        mWaitingForVsync = false;
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
    }

    return 1; // keep the callback
}

bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                                                  PhysicalDisplayId* outDisplayId,
                                                  uint32_t* outCount) {
    bool gotVsync = false;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    ssize_t n;
    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
        for (ssize_t i = 0; i < n; i++) {
            const DisplayEventReceiver::Event& ev = buf[i];
            switch (ev.header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    // Later vsync events will just overwrite the info from earlier
                    // ones. That's fine, we only care about the most recent.
                    gotVsync = true;
                    *outTimestamp = ev.header.timestamp;
                    *outDisplayId = ev.header.displayId;
                    *outCount = ev.vsync.count;
                    break;
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
                    break;
                case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
                    dispatchConfigChanged(ev.header.timestamp, ev.header.displayId,
                                          ev.config.configId);
                    break;
                default:
                    ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
                    break;
            }
        }
    }
    if (n < 0) {
        ALOGW("Failed to get events from display event dispatcher, status=%d", status_t(n));
    }
    return gotVsync;
}
} // namespace android
+83 −9
Original line number Diff line number Diff line
@@ -878,6 +878,33 @@ public:
        return reply.readInt32();
    }

    virtual status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                              std::vector<int32_t>* outAllowedConfigs) {
        if (!outAllowedConfigs) return BAD_VALUE;
        Parcel data, reply;
        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to writeInterfaceToken: %d", result);
            return result;
        }
        result = data.writeStrongBinder(displayToken);
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to writeStrongBinder: %d", result);
            return result;
        }
        result = remote()->transact(BnSurfaceComposer::GET_ALLOWED_DISPLAY_CONFIGS, data, &reply);
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to transact: %d", result);
            return result;
        }
        result = reply.readInt32Vector(outAllowedConfigs);
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to readInt32Vector: %d", result);
            return result;
        }
        return reply.readInt32();
    }

    virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
                                                  int32_t defaultModeId, float minRefreshRate,
                                                  float maxRefreshRate) {
@@ -917,28 +944,41 @@ public:
        return reply.readInt32();
    }

    virtual status_t getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                              std::vector<int32_t>* outAllowedConfigs) {
        if (!outAllowedConfigs) return BAD_VALUE;
    virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
                                                  int32_t* outDefaultModeId,
                                                  float* outMinRefreshRate,
                                                  float* outMaxRefreshRate) {
        if (!outDefaultModeId || !outMinRefreshRate || !outMaxRefreshRate) return BAD_VALUE;
        Parcel data, reply;
        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to writeInterfaceToken: %d", result);
            ALOGE("getDesiredDisplayConfigSpecs failed to writeInterfaceToken: %d", result);
            return result;
        }
        result = data.writeStrongBinder(displayToken);
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to writeStrongBinder: %d", result);
            ALOGE("getDesiredDisplayConfigSpecs failed to writeStrongBinder: %d", result);
            return result;
        }
        result = remote()->transact(BnSurfaceComposer::GET_ALLOWED_DISPLAY_CONFIGS, data, &reply);
        result = remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_CONFIG_SPECS, data,
                                    &reply);
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to transact: %d", result);
            ALOGE("getDesiredDisplayConfigSpecs failed to transact: %d", result);
            return result;
        }
        result = reply.readInt32Vector(outAllowedConfigs);
        result = reply.readInt32(outDefaultModeId);
        if (result != NO_ERROR) {
            ALOGE("getAllowedDisplayConfigs failed to readInt32Vector: %d", result);
            ALOGE("getDesiredDisplayConfigSpecs failed to read defaultModeId: %d", result);
            return result;
        }
        result = reply.readFloat(outMinRefreshRate);
        if (result != NO_ERROR) {
            ALOGE("getDesiredDisplayConfigSpecs failed to read minRefreshRate: %d", result);
            return result;
        }
        result = reply.readFloat(outMaxRefreshRate);
        if (result != NO_ERROR) {
            ALOGE("getDesiredDisplayConfigSpecs failed to read maxRefreshRate: %d", result);
            return result;
        }
        return reply.readInt32();
@@ -1654,6 +1694,40 @@ status_t BnSurfaceComposer::onTransact(
            reply->writeInt32(result);
            return result;
        }
        case GET_DESIRED_DISPLAY_CONFIG_SPECS: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> displayToken = data.readStrongBinder();
            int32_t defaultModeId;
            float minRefreshRate;
            float maxRefreshRate;

            status_t result = getDesiredDisplayConfigSpecs(displayToken, &defaultModeId,
                                                           &minRefreshRate, &maxRefreshRate);
            if (result != NO_ERROR) {
                ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: "
                      "%d",
                      result);
                return result;
            }

            result = reply->writeInt32(defaultModeId);
            if (result != NO_ERROR) {
                ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultModeId: %d", result);
                return result;
            }
            result = reply->writeFloat(minRefreshRate);
            if (result != NO_ERROR) {
                ALOGE("getDesiredDisplayConfigSpecs: failed to write minRefreshRate: %d", result);
                return result;
            }
            result = reply->writeFloat(maxRefreshRate);
            if (result != NO_ERROR) {
                ALOGE("getDesiredDisplayConfigSpecs: failed to write maxRefreshRate: %d", result);
                return result;
            }
            reply->writeInt32(result);
            return result;
        }
        case GET_DISPLAY_BRIGHTNESS_SUPPORT: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> displayToken;
+10 −0
Original line number Diff line number Diff line
@@ -1627,6 +1627,16 @@ status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs(const sp<IBinder>&
                                                                               maxRefreshRate);
}

status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
                                                             int32_t* outDefaultModeId,
                                                             float* outMinRefreshRate,
                                                             float* outMaxRefreshRate) {
    return ComposerService::getComposerService()->getDesiredDisplayConfigSpecs(displayToken,
                                                                               outDefaultModeId,
                                                                               outMinRefreshRate,
                                                                               outMaxRefreshRate);
}

status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
        Vector<ColorMode>* outColorModes) {
    return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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 <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
#include <utils/Looper.h>

namespace android {

class DisplayEventDispatcher : public LooperCallback {
public:
    explicit DisplayEventDispatcher(
            const sp<Looper>& looper,
            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
            ISurfaceComposer::ConfigChanged configChanged =
                    ISurfaceComposer::eConfigChangedSuppress);

    status_t initialize();
    void dispose();
    status_t scheduleVsync();

protected:
    virtual ~DisplayEventDispatcher() = default;

private:
    sp<Looper> mLooper;
    DisplayEventReceiver mReceiver;
    bool mWaitingForVsync;

    virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0;
    virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
                                 bool connected) = 0;
    virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
                                       int32_t configId) = 0;

    virtual int handleEvent(int receiveFd, int events, void* data);
    bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
                              uint32_t* outCount);
};
} // namespace android
Loading