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

Commit 9e818bab authored by John Reck's avatar John Reck Committed by Gerrit Code Review
Browse files

Merge "Fix implementation of ANW_read/write parcel"

parents 04d05a69 7e2284ca
Loading
Loading
Loading
Loading
+47 −5
Original line number Diff line number Diff line
@@ -16,17 +16,59 @@

#define LOG_TAG "Surface"

#include <gui/view/Surface.h>

#include <android/binder_libbinder.h>
#include <android/binder_parcel.h>
#include <android/native_window.h>
#include <binder/Parcel.h>

#include <utils/Log.h>

#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <gui/view/Surface.h>
#include <system/window.h>
#include <utils/Log.h>

namespace android {
namespace view {

// Since this is a parcelable utility and we want to keep the wire format stable, only build this
// when building the system libgui to detect any issues loading the wrong libgui from
// libnativewindow

#if (!defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__))

extern "C" status_t android_view_Surface_writeToParcel(ANativeWindow* _Nonnull window,
                                                       Parcel* _Nonnull parcel) {
    int value;
    int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
        ALOGE("Error: ANativeWindow is not backed by Surface");
        return STATUS_BAD_VALUE;
    }
    // Use a android::view::Surface to parcelize the window
    android::view::Surface shimSurface;
    shimSurface.graphicBufferProducer = android::Surface::getIGraphicBufferProducer(window);
    shimSurface.surfaceControlHandle = android::Surface::getSurfaceControlHandle(window);
    return shimSurface.writeToParcel(parcel);
}

extern "C" status_t android_view_Surface_readFromParcel(
        const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
    // Use a android::view::Surface to unparcel the window
    android::view::Surface shimSurface;
    status_t ret = shimSurface.readFromParcel(parcel);
    if (ret != OK) {
        ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
        return STATUS_BAD_VALUE;
    }
    auto surface = sp<android::Surface>::make(shimSurface.graphicBufferProducer, false,
                                              shimSurface.surfaceControlHandle);
    ANativeWindow* anw = surface.get();
    ANativeWindow_acquire(anw);
    *outWindow = anw;
    return STATUS_OK;
}

#endif

status_t Surface::writeToParcel(Parcel* parcel) const {
    return writeToParcel(parcel, false);
}
+49 −35
Original line number Diff line number Diff line
@@ -24,14 +24,49 @@

#include <private/android/AHardwareBufferHelpers.h>

#include <android/binder_libbinder.h>
#include <dlfcn.h>
#include <log/log.h>
#include <ui/GraphicBuffer.h>
#include <gui/Surface.h>
#include <gui/view/Surface.h>
#include <android/binder_libbinder.h>

using namespace android;

#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__)
#error libnativewindow can only be built for system
#endif

using android_view_Surface_writeToParcel = status_t (*)(ANativeWindow* _Nonnull window,
                                                        Parcel* _Nonnull parcel);

using android_view_Surface_readFromParcel =
        status_t (*)(const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow);

struct SurfaceParcelables {
    android_view_Surface_writeToParcel write = nullptr;
    android_view_Surface_readFromParcel read = nullptr;
};

const SurfaceParcelables* getSurfaceParcelFunctions() {
    static SurfaceParcelables funcs = []() -> SurfaceParcelables {
        SurfaceParcelables ret;
        void* dl = dlopen("libgui.so", RTLD_NOW);
        LOG_ALWAYS_FATAL_IF(!dl, "Failed to find libgui.so");
        ret.write =
                (android_view_Surface_writeToParcel)dlsym(dl, "android_view_Surface_writeToParcel");
        LOG_ALWAYS_FATAL_IF(!ret.write,
                            "libgui.so missing android_view_Surface_writeToParcel; "
                            "loaded wrong libgui?");
        ret.read =
                (android_view_Surface_readFromParcel)dlsym(dl,
                                                           "android_view_Surface_readFromParcel");
        LOG_ALWAYS_FATAL_IF(!ret.read,
                            "libgui.so missing android_view_Surface_readFromParcel; "
                            "loaded wrong libgui?");
        return ret;
    }();
    return &funcs;
}

static int32_t query(ANativeWindow* window, int what) {
    int value;
    int res = window->query(window, what, &value);
@@ -64,13 +99,6 @@ static bool isDataSpaceValid(ANativeWindow* window, int32_t dataSpace) {
            return false;
    }
}
static sp<IGraphicBufferProducer> IGraphicBufferProducer_from_ANativeWindow(ANativeWindow* window) {
    return Surface::getIGraphicBufferProducer(window);
}

static sp<IBinder> SurfaceControlHandle_from_ANativeWindow(ANativeWindow* window) {
    return Surface::getSurfaceControlHandle(window);
}

/**************************************************************************************************
 * NDK
@@ -348,38 +376,24 @@ int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation

binder_status_t ANativeWindow_readFromParcel(
        const AParcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
    const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);

    // Use a android::view::Surface to unparcel the window
    std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
    status_t ret = shimSurface->readFromParcel(nativeParcel);
    if (ret != OK) {
        ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
        return STATUS_BAD_VALUE;
    auto funcs = getSurfaceParcelFunctions();
    if (funcs->read == nullptr) {
        ALOGE("Failed to load Surface_readFromParcel implementation");
        return STATUS_FAILED_TRANSACTION;
    }
    sp<Surface> surface = sp<Surface>::make(
            shimSurface->graphicBufferProducer, false, shimSurface->surfaceControlHandle);
    ANativeWindow* anw = surface.get();
    ANativeWindow_acquire(anw);
    *outWindow = anw;
    return STATUS_OK;
    const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
    return funcs->read(nativeParcel, outWindow);
}

binder_status_t ANativeWindow_writeToParcel(
        ANativeWindow* _Nonnull window, AParcel* _Nonnull parcel) {
    int value;
    int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
        ALOGE("Error: ANativeWindow is not backed by Surface");
        return STATUS_BAD_VALUE;
    auto funcs = getSurfaceParcelFunctions();
    if (funcs->write == nullptr) {
        ALOGE("Failed to load Surface_writeToParcel implementation");
        return STATUS_FAILED_TRANSACTION;
    }
    // Use a android::view::Surface to parcelize the window
    std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
    shimSurface->graphicBufferProducer = IGraphicBufferProducer_from_ANativeWindow(window);
    shimSurface->surfaceControlHandle = SurfaceControlHandle_from_ANativeWindow(window);

    Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
    return shimSurface->writeToParcel(nativeParcel);
    return funcs->write(window, nativeParcel);
}

/**************************************************************************************************