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

Commit d0566bc2 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

Add support for sending VSYNC events to the framework

use gui/DisplayEvent to receive the events. Events are
dispatched through a unix pipe, so the API is compatible
with utils/Looper. see gui/DisplayEvent.h for more info.

Bug: 1475048
Change-Id: Ia720f64d1b950328b47b22c6a86042e481d35f09
parent 439cf857
Loading
Loading
Loading
Loading
+105 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.
 */

#ifndef ANDROID_GUI_DISPLAY_EVENT_H
#define ANDROID_GUI_DISPLAY_EVENT_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>

#include <binder/IInterface.h>

// ----------------------------------------------------------------------------

namespace android {

// ----------------------------------------------------------------------------

class BitTube;
class IDisplayEventConnection;

// ----------------------------------------------------------------------------

class DisplayEventReceiver {
public:
    enum {
        DISPLAY_EVENT_VSYNC = 'vsyn'
    };

    struct Event {

        struct Header {
            uint32_t type;
            nsecs_t timestamp;
        };

        struct VSync {
            uint32_t count;
        };

        Header header;
        union {
            VSync vsync;
        };
    };

public:
    /*
     * DisplayEventReceiver creates and registers an event connection with
     * SurfaceFlinger. Events start being delivered immediately.
     */
    DisplayEventReceiver();

    /*
     * ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
     * stop being delivered immediately. Note that the queue could have
     * some events pending. These will be delivered.
     */
    ~DisplayEventReceiver();

    /*
     * initCheck returns the state of DisplayEventReceiver after construction.
     */
    status_t initCheck() const;

    /*
     * getFd returns the file descriptor to use to receive events.
     * OWNERSHIP IS RETAINED by DisplayEventReceiver. DO NOT CLOSE this
     * file-descriptor.
     */
    int getFd() const;

    /*
     * getEvents reads event from the queue and returns how many events were
     * read. Returns 0 if there are no more events or a negative error code.
     * If NOT_ENOUGH_DATA is returned, the object has become invalid forever, it
     * should be destroyed and getEvents() shouldn't be called again.
     */
    ssize_t getEvents(Event* events, size_t count);

private:
    sp<IDisplayEventConnection> mEventConnection;
    sp<BitTube> mDataChannel;
};

// ----------------------------------------------------------------------------
}; // namespace android

#endif // ANDROID_GUI_DISPLAY_EVENT_H
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.
 */

#ifndef ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
#define ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/RefBase.h>

#include <binder/IInterface.h>

namespace android {
// ----------------------------------------------------------------------------

class BitTube;

class IDisplayEventConnection : public IInterface
{
public:
    DECLARE_META_INTERFACE(DisplayEventConnection);

    virtual sp<BitTube> getDataChannel() const = 0;
};

// ----------------------------------------------------------------------------

class BnDisplayEventConnection : public BnInterface<IDisplayEventConnection>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

// ----------------------------------------------------------------------------
}; // namespace android

#endif // ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
+9 −1
Original line number Diff line number Diff line
@@ -33,8 +33,9 @@
namespace android {
// ----------------------------------------------------------------------------

class IMemoryHeap;
class ComposerState;
class IDisplayEventConnection;
class IMemoryHeap;

class ISurfaceComposer : public IInterface
{
@@ -124,13 +125,19 @@ public:
            uint32_t reqWidth, uint32_t reqHeight,
            uint32_t minLayerZ, uint32_t maxLayerZ) = 0;

    /* triggers screen off animation */
    virtual status_t turnElectronBeamOff(int32_t mode) = 0;

    /* triggers screen on animation */
    virtual status_t turnElectronBeamOn(int32_t mode) = 0;

    /* verify that an ISurfaceTexture was created by SurfaceFlinger.
     */
    virtual bool authenticateSurfaceTexture(
            const sp<ISurfaceTexture>& surface) const = 0;

    /* return an IDisplayEventConnection */
    virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
};

// ----------------------------------------------------------------------------
@@ -151,6 +158,7 @@ public:
        TURN_ELECTRON_BEAM_OFF,
        TURN_ELECTRON_BEAM_ON,
        AUTHENTICATE_SURFACE,
        CREATE_DISPLAY_EVENT_CONNECTION,
    };

    virtual status_t    onTransact( uint32_t code,
+2 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	BitTube.cpp \
	DisplayEventReceiver.cpp \
	IDisplayEventConnection.cpp \
	ISensorEventConnection.cpp \
	ISensorServer.cpp \
	ISurfaceTexture.cpp \
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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 <string.h>

#include <utils/Errors.h>

#include <gui/BitTube.h>
#include <gui/DisplayEventReceiver.h>
#include <gui/IDisplayEventConnection.h>

#include <private/gui/ComposerService.h>

#include <surfaceflinger/ISurfaceComposer.h>

// ---------------------------------------------------------------------------

namespace android {

// ---------------------------------------------------------------------------

DisplayEventReceiver::DisplayEventReceiver() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != NULL) {
        mEventConnection = sf->createDisplayEventConnection();
        if (mEventConnection != NULL) {
            mDataChannel = mEventConnection->getDataChannel();
        }
    }
}

DisplayEventReceiver::~DisplayEventReceiver() {
}

status_t DisplayEventReceiver::initCheck() const {
    if (mDataChannel != NULL)
        return NO_ERROR;
    return NO_INIT;
}

int DisplayEventReceiver::getFd() const {
    if (mDataChannel == NULL)
        return NO_INIT;

    return mDataChannel->getFd();
}

ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
        size_t count) {
    ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
    LOGE_IF(size<0,
            "DisplayEventReceiver::getEvents error (%s)",
            strerror(-size));
    if (size >= 0) {
        // Note: if (size % sizeof(events[0])) != 0, we've got a
        // partial read. This can happen if the queue filed up (ie: if we
        // didn't pull from it fast enough).
        // We discard the partial event and rely on the sender to
        // re-send the event if appropriate (some events, like VSYNC
        // can be lost forever).

        // returns number of events read
        size /= sizeof(events[0]);
    }
    return size;
}

// ---------------------------------------------------------------------------

}; // namespace android
Loading