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

Commit 3c8fa3b3 authored by Ruben Brunk's avatar Ruben Brunk
Browse files

camera2: Fix configured surface check in Legacy shim.

Bug: 15116722

- Switch to checking IBinder pointer when making sure
  requested output surface has been configured (same as
  the camera service).
- Needed to use TextureView in TestingCamera2.

Change-Id: If8831a9b2f9ec3e81cc8348e067a57cca2d46440
parent d46eba18
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.util.Size;
import android.view.Surface;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static android.hardware.camera2.legacy.LegacyExceptionUtils.*;
@@ -271,6 +272,9 @@ public class LegacyCameraDevice implements AutoCloseable {
            return BAD_VALUE;
        }

        List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() :
                getSurfaceIds(mConfiguredSurfaces);

        // Make sure that there all requests have at least 1 surface; all surfaces are non-null
        for (CaptureRequest request : requestList) {
            if (request.getTargets().isEmpty()) {
@@ -287,7 +291,7 @@ public class LegacyCameraDevice implements AutoCloseable {
                    Log.e(TAG, "submitRequestList - must configure " +
                            " device with valid surfaces before submitting requests");
                    return INVALID_OPERATION;
                } else if (!mConfiguredSurfaces.contains(surface)) {
                } else if (!containsSurfaceId(surface, surfaceIds)) {
                    Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured");
                    return BAD_VALUE;
                }
@@ -430,6 +434,32 @@ public class LegacyCameraDevice implements AutoCloseable {
        LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height));
    }

    static long getSurfaceId(Surface surface) {
        checkNotNull(surface);
        return nativeGetSurfaceId(surface);
    }

    static List<Long> getSurfaceIds(Collection<Surface> surfaces) {
        if (surfaces == null) {
            throw new NullPointerException("Null argument surfaces");
        }
        List<Long> surfaceIds = new ArrayList<>();
        for (Surface s : surfaces) {
            long id = getSurfaceId(s);
            if (id == 0) {
                throw new IllegalStateException(
                        "Configured surface had null native GraphicBufferProducer pointer!");
            }
            surfaceIds.add(id);
        }
        return surfaceIds;
    }

    static boolean containsSurfaceId(Surface s, List<Long> ids) {
        long id = getSurfaceId(s);
        return ids.contains(id);
    }

    private static native int nativeDetectSurfaceType(Surface surface);

    private static native int nativeDetectSurfaceDimens(Surface surface,
@@ -445,4 +475,5 @@ public class LegacyCameraDevice implements AutoCloseable {

    private static native int nativeSetSurfaceDimens(Surface surface, int width, int height);

    private static native long nativeGetSurfaceId(Surface surface);
}
+4 −3
Original line number Diff line number Diff line
@@ -492,19 +492,20 @@ public class SurfaceTextureRenderer {
                && (mConversionSurfaces == null || mConversionSurfaces.size() == 0)) {
            return;
        }

        checkGlError("before updateTexImage");
        mSurfaceTexture.updateTexImage();
        if (targetSurfaces == null) return;
        List<Long> targetSurfaceIds = LegacyCameraDevice.getSurfaceIds(targetSurfaces);
        for (EGLSurfaceHolder holder : mSurfaces) {
            if (targetSurfaces.contains(holder.surface)) {
            if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) {
                makeCurrent(holder.eglSurface);
                drawFrame(mSurfaceTexture);
                swapBuffers(holder.eglSurface);
            }

        }
        for (EGLSurfaceHolder holder : mConversionSurfaces) {
            if (targetSurfaces.contains(holder.surface)) {
            if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) {
                makeCurrent(holder.eglSurface);
                drawFrame(mSurfaceTexture);
                mPBufferPixels.clear();
+61 −10
Original line number Diff line number Diff line
@@ -25,10 +25,15 @@
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"

#include <gui/Surface.h>
#include <gui/IGraphicBufferProducer.h>
#include <ui/GraphicBuffer.h>
#include <system/window.h>
#include <hardware/camera3.h>

#include <stdint.h>
#include <inttypes.h>

using namespace android;

// fully-qualified class name
@@ -192,8 +197,8 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
    switch(pixelFmt) {
        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
            if (bufSize < width * height * 4) {
                ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
                        bufSize);
                ALOGE("%s: PixelBuffer size %" PRId32 " to small for given dimensions",
                        __FUNCTION__, bufSize);
                return BAD_VALUE;
            }
            uint8_t* img = NULL;
@@ -214,8 +219,8 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
        }
        case HAL_PIXEL_FORMAT_YV12: {
            if (bufSize < width * height * 4) {
                ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
                        bufSize);
                ALOGE("%s: PixelBuffer size %" PRId32 " to small for given dimensions",
                        __FUNCTION__, bufSize);
                return BAD_VALUE;
            }

@@ -251,8 +256,8 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
            // Software writes with YCbCr_420_888 format are unsupported
            // by the gralloc module for now
            if (bufSize < width * height * 4) {
                ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
                      bufSize);
                ALOGE("%s: PixelBuffer size %" PRId32 " to small for given dimensions",
                        __FUNCTION__, bufSize);
                return BAD_VALUE;
            }
            android_ycbcr ycbcr = android_ycbcr();
@@ -269,7 +274,7 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
        }
        case HAL_PIXEL_FORMAT_BLOB: {
            if (bufSize != width || height != 1) {
                ALOGE("%s: Incorrect pixelBuffer size: %lld", __FUNCTION__, bufSize);
                ALOGE("%s: Incorrect pixelBuffer size: %" PRId32, __FUNCTION__, bufSize);
                return BAD_VALUE;
            }
            int8_t* img = NULL;
@@ -316,20 +321,39 @@ static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
    if (surface) {
        anw = android_view_Surface_getNativeWindow(env, surface);
        if (env->ExceptionCheck()) {
            return anw;
            return NULL;
        }
    } else {
        jniThrowNullPointerException(env, "surface");
        return anw;
        return NULL;
    }
    if (anw == NULL) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                "Surface had no valid native window.");
        return anw;
        return NULL;
    }
    return anw;
}

static sp<Surface> getSurface(JNIEnv* env, jobject surface) {
    sp<Surface> s;
    if (surface) {
        s = android_view_Surface_getSurface(env, surface);
        if (env->ExceptionCheck()) {
            return NULL;
        }
    } else {
        jniThrowNullPointerException(env, "surface");
        return NULL;
    }
    if (s == NULL) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                "Surface had no valid native Surface.");
        return NULL;
    }
    return s;
}

extern "C" {

static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
@@ -456,6 +480,30 @@ static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz,
    return NO_ERROR;
}

static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
    ALOGV("nativeGetSurfaceId");
    sp<Surface> s;
    if ((s = getSurface(env, surface)) == NULL) {
        ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
        return 0;
    }
    sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
    if (gbp == NULL) {
        ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
        return 0;
    }
    sp<IBinder> b = gbp->asBinder();
    if (b == NULL) {
        ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
        return 0;
    }
    /*
     * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
     * service (CameraDeviceClient.h).
     */
    return reinterpret_cast<jlong>(b.get());
}

} // extern "C"

static JNINativeMethod gCameraDeviceMethods[] = {
@@ -477,6 +525,9 @@ static JNINativeMethod gCameraDeviceMethods[] = {
    { "nativeSetSurfaceDimens",
    "(Landroid/view/Surface;II)I",
    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
    { "nativeGetSurfaceId",
    "(Landroid/view/Surface;)J",
    (void *)LegacyCameraDevice_nativeGetSurfaceId },
};

// Get all the required offsets in java class and register native functions