Merge the 2021-09-05 SPL branch from AOSP-Partner

* security-aosp-pi-release:
  Only treat PNG_COLOR_TYPE_RGB as 565

Change-Id: I205e28262c888b81014fb6f09097dbbf3b7e25f2
diff --git a/include/android/SkAndroidFrameworkUtils.h b/include/android/SkAndroidFrameworkUtils.h
index 46d2516..3554b88 100644
--- a/include/android/SkAndroidFrameworkUtils.h
+++ b/include/android/SkAndroidFrameworkUtils.h
@@ -9,10 +9,12 @@
 #define SkAndroidFrameworkUtils_DEFINED
 
 #include "SkTypes.h"
+#include "SkRefCnt.h"
 
 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
 
 class SkCanvas;
+class SkSurface;
 
 /**
  *  SkAndroidFrameworkUtils expose private APIs used only by Android framework.
@@ -32,6 +34,8 @@
     static bool clipWithStencil(SkCanvas* canvas);
 #endif //SK_SUPPORT_GPU
 
+    static sk_sp<SkSurface> getSurfaceFromCanvas(SkCanvas* canvas);
+
     static void SafetyNetLog(const char*);
 };
 
diff --git a/include/config/SkUserConfigManual.h b/include/config/SkUserConfigManual.h
index 69b2d17..58e4eb3 100644
--- a/include/config/SkUserConfigManual.h
+++ b/include/config/SkUserConfigManual.h
@@ -7,7 +7,6 @@
 
 #ifndef SkUserConfigManual_DEFINED
 #define SkUserConfigManual_DEFINED
-  #define GR_GL_CUSTOM_SETUP_HEADER "gl/GrGLConfig_chrome.h"
   #define GR_TEST_UTILS 1
   #define SK_BUILD_FOR_ANDROID_FRAMEWORK
   #define SK_DEFAULT_FONT_CACHE_LIMIT   (768 * 1024)
@@ -17,6 +16,8 @@
   // Disable these Ganesh features
   #define SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
   #define SK_DISABLE_RENDER_TARGET_SORTING
+  // Check error is expensive. HWUI historically also doesn't check its allocations
+  #define GR_GL_CHECK_ALLOC_WITH_GET_ERROR            0
 
   // Legacy flags
   #define SK_IGNORE_GPU_DITHER
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index 5a3887e..944f9dc 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -543,6 +543,17 @@
     */
     sk_sp<SkImage> makeImageSnapshot();
 
+    /**
+     *  Like the no-parameter version, this returns an image of the current surface contents.
+     *  This variant takes a rectangle specifying the subset of the surface that is of interest.
+     *  These bounds will be sanitized before being used.
+     *  - If bounds extends beyond the surface, it will be trimmed to just the intersection of
+     *    it and the surface.
+     *  - If bounds does not intersect the surface, then this returns nullptr.
+     *  - If bounds == the surface, then this is the same as calling the no-parameter variant.
+     */
+    sk_sp<SkImage> makeImageSnapshot(const SkIRect& bounds);
+
     /** Draws SkSurface contents to canvas, with its top-left corner at (x, y).
 
         If SkPaint paint is not nullptr, apply SkColorFilter, color alpha, SkImageFilter,
diff --git a/src/android/SkAndroidFrameworkUtils.cpp b/src/android/SkAndroidFrameworkUtils.cpp
index f0a7b8a..3fa43d2 100644
--- a/src/android/SkAndroidFrameworkUtils.cpp
+++ b/src/android/SkAndroidFrameworkUtils.cpp
@@ -8,6 +8,7 @@
 #include "SkAndroidFrameworkUtils.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
+#include "SkSurface_Base.h"
 
 #if SK_SUPPORT_GPU
 #include "GrStyle.h"
@@ -54,9 +55,13 @@
 }
 #endif //SK_SUPPORT_GPU
 
+sk_sp<SkSurface> SkAndroidFrameworkUtils::getSurfaceFromCanvas(SkCanvas* canvas) {
+    sk_sp<SkSurface> surface(SkSafeRef(canvas->getSurfaceBase()));
+    return surface;
+}
+
 void SkAndroidFrameworkUtils::SafetyNetLog(const char* bugNumber) {
     android_errorWriteLog(0x534e4554, bugNumber);
 }
 
 #endif // SK_BUILD_FOR_ANDROID_FRAMEWORK
-
diff --git a/src/codec/SkWbmpCodec.cpp b/src/codec/SkWbmpCodec.cpp
index 171ae52..350be5c 100644
--- a/src/codec/SkWbmpCodec.cpp
+++ b/src/codec/SkWbmpCodec.cpp
@@ -184,6 +184,13 @@
         return kUnimplemented;
     }
 
+    if (!valid_color_type(dstInfo) ||
+        !valid_alpha(dstInfo.alphaType(), this->getInfo().alphaType()))
+    {
+        return kInvalidConversion;
+    }
+
+    // Initialize the swizzler
     fSwizzler = SkSwizzler::Make(this->getEncodedInfo(), nullptr, dstInfo, options);
     SkASSERT(fSwizzler);
 
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index 085d27a..ec06dcb 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -29,6 +29,14 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <cutils/properties.h>
+
+// Direct access to private framework and HAL data to workaround Adreno 330 driver bugs.
+// DO NOT actually call anything from these headers; they are included only to access private
+// structs.
+#include "../../../../frameworks/native/libs/nativebase/include/nativebase/nativebase.h"
+#include "../../../../hardware/qcom/display/libgralloc/gralloc_priv.h"
+
 class BufferCleanupHelper {
 public:
     BufferCleanupHelper(EGLImageKHR image, EGLDisplay display)
@@ -146,21 +154,118 @@
 }
 #endif
 
-sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
-    if (context->abandoned() || kOpenGL_GrBackend != context->contextPriv().getBackend()) {
-        // Check if GrContext is not abandoned and the backend is GL.
+namespace {
+
+sk_sp<GrTexture> createGLTextureFromPrivateHandle(GrContext* context,
+    const SkImageInfo& info, const AHardwareBuffer* hardware_buffer) {
+
+    if (!hardware_buffer) {
+        SkDebugf("createGLTextureFromPrivateHandle: Cannot work without AHardwareBuffer");
         return nullptr;
     }
 
-    auto proxyProvider = context->contextPriv().proxyProvider();
-
-    // return a cached GrTexture if invoked with the same context
-    if (fOriginalTexture && fOwningContextID == context->uniqueID()) {
-        return proxyProvider->createWrapped(sk_ref_sp(fOriginalTexture),
-                                            kTopLeft_GrSurfaceOrigin);
+    GrPixelConfig pixelConfig = kUnknown_GrPixelConfig;
+    size_t bytesPerPixel = 0;
+    GrGLenum format = GL_INVALID_ENUM;
+    GrGLenum type = GL_INVALID_ENUM;
+    switch (info.colorType()) {
+    case kRGBA_8888_SkColorType:
+        pixelConfig = kRGBA_8888_GrPixelConfig;
+        bytesPerPixel = 4;
+        format = GL_RGBA;
+        type = GL_UNSIGNED_BYTE;
+        break;
+    case kRGB_565_SkColorType:
+        pixelConfig = kRGB_565_GrPixelConfig;
+        bytesPerPixel = 2;
+        format = GL_RGB;
+        type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    default:
+        SkDebugf("createGLTextureFromPrivateHandle: Unsupported color type %i", int(info.colorType()));
+        return nullptr;
     }
 
-    while (GL_NO_ERROR != glGetError()) {} //clear GL errors
+    EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardware_buffer);
+    const native_handle_t* native_handle = reinterpret_cast<const ANativeWindowBuffer*>(clientBuffer)->handle;
+    const bool handleIsAsExpected = private_handle_t::validate(native_handle) == 0;
+    if (!handleIsAsExpected) {
+        SkDebugf("createGLTextureFromPrivateHandle: GraphicBuffer doesn't seem to map to gralloc private handle.");
+        return nullptr;
+    }
+    const private_handle_t* hnd = static_cast<const private_handle_t*>(native_handle);
+
+    const int imageWidth = info.width();
+    const int imageHeight = info.height();
+    const int bufferWidth = hnd->width; // May be aligned and be larger than the actual image.
+    const int bufferHeight = hnd->height;
+    if (imageWidth > bufferWidth || imageHeight > bufferHeight) {
+        SkDebugf("createGLTextureFromPrivateHandle: image is larger than the buffer. This is not supposed to happen.");
+        return nullptr;
+    }
+    const size_t bufferRowBytes = bufferWidth * bytesPerPixel;
+    // We access as many rows as the image has, aligned to the width of the buffer.
+    const size_t minBufferSize = bufferRowBytes * imageHeight;
+    if (hnd->size < 0 || static_cast<size_t>(hnd->size) < minBufferSize) {
+        SkDebugf("createGLTextureFromPrivateHandle: buffer is smaller than expected or invalid.");
+        return nullptr;
+    }
+
+    const char* bufferData = reinterpret_cast<const char*>(hnd->base);
+
+    GrGLuint texID;
+    glGenTextures(1, &texID);
+    glBindTexture(GL_TEXTURE_2D, texID);
+
+    if (imageWidth == bufferWidth) {
+        // Take the quick path if possible
+        glTexImage2D(GL_TEXTURE_2D, 0, format, imageWidth, imageHeight, 0, format, type, bufferData);
+    } else {
+        // The buffer has some extra space for alignment. Copy row by row.
+        // First allocate the texture storage without filling it.
+        glTexImage2D(GL_TEXTURE_2D, 0, format, imageWidth, imageHeight, 0, format, type, 0);
+        for (int y = 0; y < imageHeight; ++y) {
+            const void* bufferRowAddr = bufferData + static_cast<size_t>(y) * bufferRowBytes;
+            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, imageWidth, 1, format, type, bufferRowAddr);
+        }
+    }
+    int gl_error;
+    bool has_gl_error = false;
+    while (GL_NO_ERROR != (gl_error = glGetError())) {
+        SkDebugf("createGLTextureFromPrivateHandle: glGetError reports %i", gl_error);
+        has_gl_error = true;
+    }
+    if (has_gl_error) {
+        SkDebugf("createGLTextureFromPrivateHandle: discarding results, because we had GL errors.");
+        glDeleteTextures(1, &texID);
+        return nullptr;
+    }
+
+    GrGLTextureInfo textureInfo;
+    textureInfo.fTarget = GL_TEXTURE_2D;
+    textureInfo.fID = texID;
+
+    GrBackendTexture backendTex(imageWidth, imageHeight, pixelConfig, textureInfo);
+    if (backendTex.width() <= 0 || backendTex.height() <= 0) {
+        SkDebugf("createGLTextureFromPrivateHandle: Failed at GrBackendTexture initialization.");
+        glDeleteTextures(1, &texID);
+        return nullptr;
+    }
+    sk_sp<GrTexture> tex = context->contextPriv().resourceProvider()->wrapBackendTexture(
+                                                        backendTex, kAdopt_GrWrapOwnership);
+    if (!tex) {
+        SkDebugf("createGLTextureFromPrivateHandle: Failed at wrapBackendTexture()");
+        glDeleteTextures(1, &texID);
+        return nullptr;
+    }
+    // Compared to the regular code, we don't need a release helper: We gave up ownership of the GL
+    // texture and don't create any other resources (like the EGLImage).
+
+    return tex;
+}
+
+sk_sp<GrTexture> createNativeBufferTexture(GrContext* context, const SkImageInfo& info,
+    const AHardwareBuffer* fGraphicBuffer, void(*deleteImageTexture)(void*)) {
 
     EGLClientBuffer  clientBuffer = eglGetNativeClientBufferANDROID(fGraphicBuffer);
     EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
@@ -200,7 +305,7 @@
     textureInfo.fID = texID;
 
     GrPixelConfig pixelConfig;
-    switch (getInfo().colorType()) {
+    switch (info.colorType()) {
     case kRGBA_8888_SkColorType:
         pixelConfig = kRGBA_8888_GrPixelConfig;
         break;
@@ -216,7 +321,7 @@
         return nullptr;
     }
 
-    GrBackendTexture backendTex(getInfo().width(), getInfo().height(), pixelConfig, textureInfo);
+    GrBackendTexture backendTex(info.width(), info.height(), pixelConfig, textureInfo);
     if (backendTex.width() <= 0 || backendTex.height() <= 0) {
         glDeleteTextures(1, &texID);
         eglDestroyImageKHR(display, image);
@@ -234,6 +339,50 @@
 
     tex->setRelease(std::move(releaseHelper));
 
+    return tex;
+}
+
+} // anonymous namespace
+
+sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
+    if (context->abandoned() || kOpenGL_GrBackend != context->contextPriv().getBackend()) {
+        // Check if GrContext is not abandoned and the backend is GL.
+        return nullptr;
+    }
+
+    auto proxyProvider = context->contextPriv().proxyProvider();
+
+    // return a cached GrTexture if invoked with the same context
+    if (fOriginalTexture && fOwningContextID == context->uniqueID()) {
+        return proxyProvider->createWrapped(sk_ref_sp(fOriginalTexture),
+                                            kTopLeft_GrSurfaceOrigin);
+    }
+
+    while (GL_NO_ERROR != glGetError()) {} //clear GL errors
+
+    // On Adreno 330 drivers sampling from EGLImage bound to GL_TEXTURE_EXTERNAL_OES texture targets
+    // leads to artifacts. Copy image data into a regular GL texture instead.
+    static const bool gl_tex_workaround_enabled =
+        [] () -> bool {
+            const int value = property_get_bool("skia.force_gl_texture", 0);
+            SkDebugf("GrAHardwareBufferImageGenerator::makeProxy skia.force_gl_texture=%i", value);
+            return bool(value);
+        }();
+
+    sk_sp<GrTexture> tex;
+    if (gl_tex_workaround_enabled) {
+        tex = createGLTextureFromPrivateHandle(context, getInfo(), fGraphicBuffer);
+    }
+
+    if (!tex) {
+        // The workaround is disabled or failed. Fall back to regular, native buffer access.
+        tex = createNativeBufferTexture(context, getInfo(), fGraphicBuffer, &deleteImageTexture);
+    }
+
+    if (!tex) {
+        return nullptr;
+    }
+
     // We fail this assert, if the context has changed. This will be fully handled after
     // skbug.com/6812 is ready.
     SkASSERT(!fOriginalTexture);
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 26ee40e..bf8e6d9 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -157,6 +157,20 @@
     return asSB(this)->refCachedImage();
 }
 
+sk_sp<SkImage> SkSurface::makeImageSnapshot(const SkIRect& srcBounds) {
+    const SkIRect surfBounds = { 0, 0, fWidth, fHeight };
+    SkIRect bounds = srcBounds;
+    if (!bounds.intersect(surfBounds)) {
+        return nullptr;
+    }
+    SkASSERT(!bounds.isEmpty());
+    if (bounds == surfBounds) {
+        return this->makeImageSnapshot();
+    } else {
+        return asSB(this)->onNewImageSnapshot(&bounds);
+    }
+}
+
 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
     return asSB(this)->onNewSurface(info);
 }
@@ -255,7 +269,7 @@
     sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override {
         return MakeNull(info.width(), info.height());
     }
-    sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
+    sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
     void onWritePixels(const SkPixmap&, int x, int y) override {}
     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
     void onCopyOnWrite(ContentChangeMode) override {}
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index 56a09cf..1ad2f83 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -42,8 +42,11 @@
      *  This needs to be able to outlive the surface itself (if need be), and
      *  must faithfully represent the current contents, even if the surface
      *  is changed after this called (e.g. it is drawn to via its canvas).
+     *
+     *  If a subset is specified, the the impl must make a copy, rather than try to wait
+     *  on copy-on-write.
      */
-    virtual sk_sp<SkImage> onNewImageSnapshot() = 0;
+    virtual sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset = nullptr) = 0;
 
     virtual void onWritePixels(const SkPixmap&, int x, int y) = 0;
 
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 78dcd59..5276d1f 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -88,7 +88,7 @@
                                        origin, &this->props());
 }
 
-sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot() {
+sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(const SkIRect* subset) {
     GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
     if (!rtc) {
         return nullptr;
@@ -103,10 +103,14 @@
     SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted();
 
     sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
-    // If the original render target is a buffer originally created by the client, then we don't
-    // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
-    // copy-on-write.
-    if (!srcProxy || rtc->priv().refsWrappedObjects()) {
+
+    if (subset) {
+        srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), *subset,
+                                        budgeted);
+    } else if (!srcProxy || rtc->priv().refsWrappedObjects()) {
+        // If the original render target is a buffer originally created by the client, then we don't
+        // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
+        // copy-on-write.
         SkASSERT(rtc->origin() == rtc->asSurfaceProxy()->origin());
 
         srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), budgeted);
diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h
index 9699b01..5254007 100644
--- a/src/image/SkSurface_Gpu.h
+++ b/src/image/SkSurface_Gpu.h
@@ -26,7 +26,7 @@
     bool onGetRenderTargetHandle(GrBackendObject*, BackendHandleAccess) override;
     SkCanvas* onNewCanvas() override;
     sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
-    sk_sp<SkImage> onNewImageSnapshot() override;
+    sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset) override;
     void onWritePixels(const SkPixmap&, int x, int y) override;
     void onCopyOnWrite(ContentChangeMode) override;
     void onDiscard() override;
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index 47d5542..bfb5f39 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -21,7 +21,7 @@
 
     SkCanvas* onNewCanvas() override;
     sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
-    sk_sp<SkImage> onNewImageSnapshot() override;
+    sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset) override;
     void onWritePixels(const SkPixmap&, int x, int y) override;
     void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override;
     void onCopyOnWrite(ContentChangeMode) override;
@@ -131,7 +131,16 @@
     canvas->drawBitmap(fBitmap, x, y, paint);
 }
 
-sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot() {
+sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot(const SkIRect* subset) {
+    if (subset) {
+        SkASSERT(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()).contains(*subset));
+        SkBitmap dst;
+        dst.allocPixels(fBitmap.info().makeWH(subset->width(), subset->height()));
+        SkAssertResult(fBitmap.readPixels(dst.pixmap(), subset->left(), subset->top()));
+        dst.setImmutable(); // key, so MakeFromBitmap doesn't make a copy of the buffer
+        return SkImage::MakeFromBitmap(dst);
+    }
+
     SkCopyPixelsMode cpm = kIfMutable_SkCopyPixelsMode;
     if (fWeOwnThePixels) {
         // SkImage_raster requires these pixels are immutable for its full lifetime.