summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/jni/RobolectricNativeRuntime.cpp6
-rw-r--r--core/jni/android_view_Surface.cpp8
-rw-r--r--libs/hostgraphics/ANativeWindow.cpp6
-rw-r--r--libs/hostgraphics/gui/Surface.h5
-rw-r--r--libs/hwui/Android.bp9
-rw-r--r--libs/hwui/RootRenderNode.cpp21
-rw-r--r--libs/hwui/RootRenderNode.h2
-rw-r--r--libs/hwui/apex/android_bitmap.cpp6
-rw-r--r--libs/hwui/apex/android_canvas.cpp2
-rw-r--r--libs/hwui/jni/BitmapFactory.cpp2
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp16
-rw-r--r--libs/hwui/jni/text/LineBreaker.cpp2
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp43
-rw-r--r--libs/hwui/renderthread/RenderThread.h6
-rw-r--r--libs/hwui/utils/Color.cpp4
-rw-r--r--libs/hwui/utils/Color.h2
-rw-r--r--media/jni/android_media_ImageReader.cpp32
17 files changed, 100 insertions, 72 deletions
diff --git a/core/jni/RobolectricNativeRuntime.cpp b/core/jni/RobolectricNativeRuntime.cpp
index d11a4b71ecef..fcbc89e788fb 100644
--- a/core/jni/RobolectricNativeRuntime.cpp
+++ b/core/jni/RobolectricNativeRuntime.cpp
@@ -4,6 +4,7 @@
#include <vector>
#include <android/graphics/jni_runtime.h>
+#include <locale.h>
#include <sys/stat.h>
#include <unicode/putil.h>
#include <unicode/udata.h>
@@ -214,5 +215,10 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
}
env->ReleaseStringUTFChars(stringPath, icuPath);
env->ReleaseStringUTFChars(stringLanguageTag, languageTag);
+
+ // Use minimal "C" locale for number format to ensure correct parsing of floats when using
+ // strtof (e.g. in PathParser).
+ setlocale(LC_NUMERIC, "C");
+
return JNI_VERSION_1_6;
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 7c78f7b09937..0190f9ecc0bf 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -60,9 +60,7 @@ namespace android {
static const char* const IllegalArgumentException = "java/lang/IllegalArgumentException";
-#ifdef __ANDROID__
static const char* const OutOfResourcesException = "android/view/Surface$OutOfResourcesException";
-#endif
static struct {
jclass clazz;
@@ -204,7 +202,6 @@ static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong n
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
-#ifdef __ANDROID__ // host does not support locking Canvas
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
@@ -256,14 +253,10 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
sp<Surface> lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (jlong) lockedSurface.get();
-#else
- return (jlong)nativeObject;
-#endif
}
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj) {
-#ifdef __ANDROID__ // host does not support locking Canvas
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
return;
@@ -278,7 +271,6 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
if (err < 0) {
jniThrowException(env, IllegalArgumentException, NULL);
}
-#endif
}
static void nativeAllocateBuffers(JNIEnv* /* env */ , jclass /* clazz */,
diff --git a/libs/hostgraphics/ANativeWindow.cpp b/libs/hostgraphics/ANativeWindow.cpp
index b7b8732b3f0d..442a49ae48dd 100644
--- a/libs/hostgraphics/ANativeWindow.cpp
+++ b/libs/hostgraphics/ANativeWindow.cpp
@@ -92,6 +92,10 @@ int32_t ANativeWindow_getHeight(ANativeWindow* window) {
return query(window, NATIVE_WINDOW_HEIGHT);
}
+int32_t ANativeWindow_getFormat(ANativeWindow* window) {
+ return query(window, NATIVE_WINDOW_FORMAT);
+}
+
void ANativeWindow_acquire(ANativeWindow* window) {
// incStrong/decStrong token must be the same, doesn't matter what it is
window->incStrong((void*)ANativeWindow_acquire);
@@ -100,4 +104,4 @@ void ANativeWindow_acquire(ANativeWindow* window) {
void ANativeWindow_release(ANativeWindow* window) {
// incStrong/decStrong token must be the same, doesn't matter what it is
window->decStrong((void*)ANativeWindow_acquire);
-} \ No newline at end of file
+}
diff --git a/libs/hostgraphics/gui/Surface.h b/libs/hostgraphics/gui/Surface.h
index 664657bff92d..170b3eeac779 100644
--- a/libs/hostgraphics/gui/Surface.h
+++ b/libs/hostgraphics/gui/Surface.h
@@ -61,6 +61,11 @@ public:
status_t setDequeueTimeout(nsecs_t timeout) { return OK; }
nsecs_t getLastDequeueStartTime() const { return 0; }
+
+ int getBuffersDataSpace() {
+ return 0;
+ }
+
protected:
virtual ~Surface() {}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index e1c200562b49..a22c477a5ae0 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -265,6 +265,8 @@ cc_defaults {
cppflags: ["-Wno-conversion-null"],
srcs: [
+ "apex/android_bitmap.cpp",
+ "apex/android_canvas.cpp",
"apex/android_matrix.cpp",
"apex/android_paint.cpp",
"apex/android_region.cpp",
@@ -275,8 +277,6 @@ cc_defaults {
target: {
android: {
srcs: [ // sources that depend on android only libraries
- "apex/android_bitmap.cpp",
- "apex/android_canvas.cpp",
"apex/jni_runtime.cpp",
"apex/renderthread.cpp",
],
@@ -402,7 +402,6 @@ cc_defaults {
],
static_libs: [
- "libnativehelper_lazy",
"libziparchive_for_incfs",
],
@@ -431,6 +430,7 @@ cc_defaults {
],
static_libs: [
"libgif",
+ "libnativehelper_lazy",
"libstatslog_hwui",
"libstatspull_lazy",
"libstatssocket_lazy",
@@ -443,6 +443,7 @@ cc_defaults {
],
static_libs: [
"libandroidfw",
+ "libnativehelper",
],
},
},
@@ -514,6 +515,7 @@ cc_defaults {
"pipeline/skia/RenderNodeDrawable.cpp",
"pipeline/skia/ReorderBarrierDrawables.cpp",
"pipeline/skia/TransformCanvas.cpp",
+ "renderstate/RenderState.cpp",
"renderthread/CanvasContext.cpp",
"renderthread/DrawFrameTask.cpp",
"renderthread/Frame.cpp",
@@ -579,7 +581,6 @@ cc_defaults {
"pipeline/skia/SkiaVulkanPipeline.cpp",
"pipeline/skia/VkFunctorDrawable.cpp",
"pipeline/skia/VkInteropFunctorDrawable.cpp",
- "renderstate/RenderState.cpp",
"renderthread/CacheManager.cpp",
"renderthread/EglManager.cpp",
"renderthread/VulkanManager.cpp",
diff --git a/libs/hwui/RootRenderNode.cpp b/libs/hwui/RootRenderNode.cpp
index ddbbf58b3071..cc1c2df0040d 100644
--- a/libs/hwui/RootRenderNode.cpp
+++ b/libs/hwui/RootRenderNode.cpp
@@ -48,6 +48,8 @@ private:
uint32_t mRequestId;
};
+#endif
+
void RootRenderNode::prepareTree(TreeInfo& info) {
info.errorHandler = mErrorHandler.get();
@@ -236,10 +238,12 @@ void RootRenderNode::detachVectorDrawableAnimator(PropertyValuesAnimatorSet* ani
// removal is necessary: the end time of animation will not change unless triggered by
// user events, in which case the already posted listener's id will become stale, and
// the onFinished callback will then be ignored.
+#ifdef __ANDROID__ // Layoutlib does not support Looper
sp<FinishAndInvokeListener> message = new FinishAndInvokeListener(anim);
auto looper = Looper::getForThread();
LOG_ALWAYS_FATAL_IF(looper == nullptr, "Not on a looper thread?");
looper->sendMessageDelayed(ms2ns(remainingTimeInMs), message, 0);
+#endif
anim->clearOneShotListener();
}
}
@@ -285,22 +289,5 @@ private:
AnimationContext* ContextFactoryImpl::createAnimationContext(renderthread::TimeLord& clock) {
return new AnimationContextBridge(clock, mRootNode);
}
-#else
-
-void RootRenderNode::prepareTree(TreeInfo& info) {
- info.errorHandler = mErrorHandler.get();
- info.updateWindowPositions = true;
- RenderNode::prepareTree(info);
- info.updateWindowPositions = false;
- info.errorHandler = nullptr;
-}
-
-void RootRenderNode::attachAnimatingNode(RenderNode* animatingNode) { }
-
-void RootRenderNode::destroy() { }
-
-void RootRenderNode::addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { }
-
-#endif
} // namespace android::uirenderer
diff --git a/libs/hwui/RootRenderNode.h b/libs/hwui/RootRenderNode.h
index 1d3f5a8a51e0..7a5cda7041ed 100644
--- a/libs/hwui/RootRenderNode.h
+++ b/libs/hwui/RootRenderNode.h
@@ -74,7 +74,6 @@ private:
void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim);
};
-#ifdef __ANDROID__ // Layoutlib does not support Animations
class ContextFactoryImpl : public IContextFactory {
public:
explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
@@ -84,6 +83,5 @@ public:
private:
RootRenderNode* mRootNode;
};
-#endif
} // namespace android::uirenderer
diff --git a/libs/hwui/apex/android_bitmap.cpp b/libs/hwui/apex/android_bitmap.cpp
index 3780ba072308..861189470189 100644
--- a/libs/hwui/apex/android_bitmap.cpp
+++ b/libs/hwui/apex/android_bitmap.cpp
@@ -83,7 +83,7 @@ static uint32_t getAlphaFlags(const SkImageInfo& info) {
switch (info.alphaType()) {
case kUnknown_SkAlphaType:
LOG_ALWAYS_FATAL("Bitmap has no alpha type");
- break;
+ return 0;
case kOpaque_SkAlphaType:
return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
case kPremul_SkAlphaType:
@@ -296,9 +296,13 @@ int ABitmap_compress(const AndroidBitmapInfo* info, ADataSpace dataSpace, const
AHardwareBuffer* ABitmap_getHardwareBuffer(ABitmap* bitmapHandle) {
Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+#ifdef __ANDROID__
AHardwareBuffer* buffer = bitmap->hardwareBuffer();
if (buffer) {
AHardwareBuffer_acquire(buffer);
}
return buffer;
+#else
+ return nullptr;
+#endif
}
diff --git a/libs/hwui/apex/android_canvas.cpp b/libs/hwui/apex/android_canvas.cpp
index 2a939efed9bb..6d726f09f62f 100644
--- a/libs/hwui/apex/android_canvas.cpp
+++ b/libs/hwui/apex/android_canvas.cpp
@@ -39,6 +39,7 @@ static bool convert(const ANativeWindow_Buffer* buffer,
return false;
}
+#ifdef __ANDROID__
sk_sp<SkColorSpace> cs(uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace));
SkImageInfo imageInfo = uirenderer::ANativeWindowToImageInfo(*buffer, cs);
size_t rowBytes = buffer->stride * imageInfo.bytesPerPixel();
@@ -53,6 +54,7 @@ static bool convert(const ANativeWindow_Buffer* buffer,
}
return true;
}
+#endif
return false;
}
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index dca865d2971c..73b5c19f369e 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -529,11 +529,13 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
// Gets the 'handle' field from a FileDescriptor object. This field is only
// populated in Windows.
+#ifdef _WIN32
static jlong jniGetHandleFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
jclass fileDescriptorClass = android::FindClassOrDie(env, "java/io/FileDescriptor");
jfieldID handleField = android::GetFieldIDOrDie(env, fileDescriptorClass, "handle", "J");
return env->GetLongField(fileDescriptor, handleField);
}
+#endif
static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor,
jobject padding, jobject bitmapFactoryOptions, jlong inBitmapHandle, jlong colorSpaceHandle) {
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 759ef52f9b6d..07e20b569a3e 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -190,13 +190,9 @@ static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, job
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
jboolean translucent, jlong rootRenderNodePtr) {
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
-#ifdef __ANDROID__ // Layoutlib does not support Animation
ContextFactoryImpl factory(rootRenderNode);
RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
return (jlong) proxy;
-#else
- return (jlong) new RenderProxy(translucent, rootRenderNode, nullptr);
-#endif
}
static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
@@ -293,9 +289,15 @@ static void android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv* env, jobject c
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
- LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
+ size_t expectedFrameInfoSize = UI_THREAD_FRAME_INFO_SIZE;
+ int robolectricApiLevel = GetRobolectricApiLevel(env);
+ // In Q and R (SDK 29 and 30), FrameInfo has size 9.
+ if (robolectricApiLevel == 29 || robolectricApiLevel == 30) {
+ expectedFrameInfoSize = 9; // From FrameInfo.h in Android Q
+ }
+ LOG_ALWAYS_FATAL_IF(frameInfoSize != expectedFrameInfoSize,
"Mismatched size expectations, given %d expected %zu", frameInfoSize,
- UI_THREAD_FRAME_INFO_SIZE);
+ expectedFrameInfoSize);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
return proxy->syncAndDrawFrame();
@@ -697,14 +699,12 @@ static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
return result;
}
-#ifdef __ANDROID__ // Layoutlib does not support Animation
class ContextFactory : public IContextFactory {
public:
virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
return new AnimationContext(clock);
}
};
-#endif
static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
diff --git a/libs/hwui/jni/text/LineBreaker.cpp b/libs/hwui/jni/text/LineBreaker.cpp
index 279cecb88527..68e47ff02aa9 100644
--- a/libs/hwui/jni/text/LineBreaker.cpp
+++ b/libs/hwui/jni/text/LineBreaker.cpp
@@ -83,7 +83,7 @@ static jlong nGetReleaseFunc(CRITICAL_JNI_PARAMS) {
return reinterpret_cast<jlong>(nFinish);
}
-static void nFinishP(CRITICAL_JNI_PARAMS, jlong nativePtr) {
+static void nFinishP(CRITICAL_JNI_PARAMS_COMMA jlong nativePtr) {
nFinish(nativePtr);
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 54ba6ac9638d..7df18d5cc691 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -96,7 +96,7 @@ CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
}
return nullptr;
#else
- return new CanvasContext(thread, translucent, rootRenderNode, nullptr,
+ return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
std::make_unique<skiapipeline::SkiaHostPipeline>(thread));
#endif
}
@@ -129,8 +129,8 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode*
: mRenderThread(thread)
, mGenerationID(0)
, mOpaque(!translucent)
-#ifdef __ANDROID__ // Layoutlib does not support Animations, Profiling, DeviceInfo
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
+#ifdef __ANDROID__ // Layoutlib does not support Profiling, DeviceInfo
, mJankTracker(&thread.globalProfileData())
, mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
#endif
@@ -169,9 +169,7 @@ void CanvasContext::destroy() {
setSurfaceControl(nullptr);
freePrefetchedLayers();
destroyHardwareResources();
-#ifdef __ANDROID__ // Layoutlib does not support Animations
mAnimationContext->destroy();
-#endif
}
static void setBufferCount(ANativeWindow* window) {
@@ -215,6 +213,7 @@ void CanvasContext::setSurfaceControl(ASurfaceControl* surfaceControl) {
setASurfaceTransactionCallback(nullptr);
setPrepareSurfaceControlForWebviewCallback(nullptr);
}
+
if (mSurfaceControl != nullptr) {
funcs.unregisterListenerFunc(this, &onSurfaceStatsAvailable);
funcs.releaseFunc(mSurfaceControl);
@@ -388,9 +387,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
info.damageGenerationId = mDamageId++;
info.out.canDrawThisFrame = true;
-#ifdef __ANDROID__ // Layoutlib does not support Animation
mAnimationContext->startFrame(info.mode);
-#endif
for (const sp<RenderNode>& node : mRenderNodes) {
// Only the primary target node will be drawn full - all other nodes would get drawn in
// real time mode. In case of a window, the primary node is the window content and the other
@@ -401,8 +398,8 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
GL_CHECKPOINT(MODERATE);
#endif
}
-#ifdef __ANDROID__ // Layoutlib does not support Animation, GPU
mAnimationContext->runRemainingAnimations(info);
+#ifdef __ANDROID__ // Layoutlib does not support GPU
GL_CHECKPOINT(MODERATE);
freePrefetchedLayers();
@@ -440,7 +437,6 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
info.out.canDrawThisFrame = false;
}
-#ifdef __ANDROID__ // Layoutlib does not support Frame Callbacks
if (info.out.canDrawThisFrame) {
int err = mNativeSurface->reserveNext();
if (err != OK) {
@@ -486,15 +482,12 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
});
}
}
-#endif
}
void CanvasContext::stopDrawing() {
cleanupResources();
mRenderThread.removeFrameCallback(this);
-#ifdef __ANDROID__ // Layoutlib does not support Animation
mAnimationContext->pauseAnimators();
-#endif
mGenerationID++;
}
@@ -695,9 +688,12 @@ void CanvasContext::cleanupResources() {
void CanvasContext::reportMetricsWithPresentTime() {
#ifdef __ANDROID__ // Layoutlib does not support FrameMetrics
- if (mFrameMetricsReporter == nullptr) {
- return;
- }
+ { // acquire lock
+ std::scoped_lock lock(mFrameMetricsReporterMutex);
+ if (mFrameMetricsReporter == nullptr) {
+ return;
+ }
+ } // release lock
if (mNativeSurface == nullptr) {
return;
}
@@ -723,10 +719,27 @@ void CanvasContext::reportMetricsWithPresentTime() {
nullptr /*outReleaseTime*/);
forthBehind->set(FrameInfoIndex::DisplayPresentTime) = presentTime;
- mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/);
+ { // acquire lock
+ std::scoped_lock lock(mFrameMetricsReporterMutex);
+ if (mFrameMetricsReporter != nullptr) {
+ mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/);
+ }
+ } // release lock
#endif
}
+FrameInfo* CanvasContext::getFrameInfoFromLast4(uint64_t frameNumber) {
+#ifdef __ANDROID__ // Layoutlib does not support Profiling
+ std::scoped_lock lock(mLast4FrameInfosMutex);
+ for (size_t i = 0; i < mLast4FrameInfos.size(); i++) {
+ if (mLast4FrameInfos[i].second == frameNumber) {
+ return mLast4FrameInfos[i].first;
+ }
+ }
+#endif
+ return nullptr;
+}
+
void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* control,
ASurfaceControlStats* stats) {
#ifdef __ANDROID__ // Layoutlib does not support surface control
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index b590867b7e57..0f30796d7ae1 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -283,7 +283,6 @@ enum class CopyResult {
class RenderThread {
PREVENT_COPY_AND_ASSIGN(RenderThread);
-
public:
static void setOnStartHook(JVMAttachHook onStartHook) {}
@@ -312,6 +311,11 @@ public:
}
template <class F>
+ void postDelayed(nsecs_t delay, F&& func) {
+ // We cannot do a delayed function call, let it be a noop as for now
+ }
+
+ template <class F>
auto runSync(F&& func) -> decltype(func()) {
return func();
};
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 5d9f2297c15a..35b0967a315c 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -19,10 +19,8 @@
#include <ui/ColorSpace.h>
#include <utils/Log.h>
-#ifdef __ANDROID__ // Layoutlib does not support hardware buffers or native windows
#include <android/hardware_buffer.h>
#include <android/native_window.h>
-#endif
#include <algorithm>
#include <cmath>
@@ -31,7 +29,6 @@
namespace android {
namespace uirenderer {
-#ifdef __ANDROID__ // Layoutlib does not support hardware buffers or native windows
static inline SkImageInfo createImageInfo(int32_t width, int32_t height, int32_t format,
sk_sp<SkColorSpace> colorSpace) {
SkColorType colorType = kUnknown_SkColorType;
@@ -95,7 +92,6 @@ uint32_t ColorTypeToBufferFormat(SkColorType colorType) {
return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
}
}
-#endif
namespace {
static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 1654072fd264..15b4519d1889 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -90,7 +90,6 @@ static constexpr float EOCF_sRGB(float srgb) {
return srgb <= 0.04045f ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
}
-#ifdef __ANDROID__ // Layoutlib does not support hardware buffers or native windows
SkImageInfo ANativeWindowToImageInfo(const ANativeWindow_Buffer& buffer,
sk_sp<SkColorSpace> colorSpace);
@@ -98,7 +97,6 @@ SkImageInfo BufferDescriptionToImageInfo(const AHardwareBuffer_Desc& bufferDesc,
sk_sp<SkColorSpace> colorSpace);
uint32_t ColorTypeToBufferFormat(SkColorType colorType);
-#endif
ANDROID_API sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index b9deafab588b..80b3c719c596 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -306,6 +306,18 @@ static BufferItem* Image_getBufferItem(JNIEnv* env, jobject image)
}
+static inline int GetRobolectricApiLevel(JNIEnv* env) {
+ jclass runtimeEnvironment = env->FindClass("org/robolectric/RuntimeEnvironment");
+ LOG_ALWAYS_FATAL_IF(runtimeEnvironment == NULL,
+ "can't find org/robolectric/RuntimeEnvironment");
+ jmethodID getApiLevelMethod =env->GetStaticMethodID(
+ runtimeEnvironment, "getApiLevel", "()I");
+ LOG_ALWAYS_FATAL_IF(getApiLevelMethod == NULL,
+ "can't find org/robolectric/RuntimeEnvironment.getApiLevel");
+ return (jint)env->CallStaticIntMethod(runtimeEnvironment, getApiLevelMethod);
+}
+
+
// ----------------------------------------------------------------------------
static void ImageReader_classInit(JNIEnv* env, jclass clazz)
@@ -364,14 +376,18 @@ static void ImageReader_classInit(JNIEnv* env, jclass clazz)
LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
"Can not find SurfacePlane constructor");
- planeClazz = env->FindClass("android/media/ImageReader$ImagePlane");
- LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find ImagePlane class");
- // FindClass only gives a local reference of jclass object.
- gImagePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
- gImagePlaneClassInfo.ctor = env->GetMethodID(gImagePlaneClassInfo.clazz, "<init>",
- "(IILjava/nio/ByteBuffer;)V");
- LOG_ALWAYS_FATAL_IF(gImagePlaneClassInfo.ctor == NULL,
- "Can not find ImagePlane constructor");
+ int robolectricApiLevel = GetRobolectricApiLevel(env);
+ // ImageReader$ImagePlane was introduced in Android S (SDK 31).
+ if (robolectricApiLevel >= 31) {
+ planeClazz = env->FindClass("android/media/ImageReader$ImagePlane");
+ LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find ImagePlane class");
+ // FindClass only gives a local reference of jclass object.
+ gImagePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
+ gImagePlaneClassInfo.ctor = env->GetMethodID(gImagePlaneClassInfo.clazz, "<init>",
+ "(IILjava/nio/ByteBuffer;)V");
+ LOG_ALWAYS_FATAL_IF(gImagePlaneClassInfo.ctor == NULL,
+ "Can not find ImagePlane constructor");
+ }
}
static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height,