summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/androidfw/ResourceTypes.cpp7
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h1
-rw-r--r--libs/hwui/BakedOpRenderer.cpp15
-rw-r--r--libs/hwui/Properties.cpp2
-rw-r--r--libs/hwui/RenderNode.cpp19
-rw-r--r--libs/hwui/RenderNode.h21
-rw-r--r--libs/hwui/VectorDrawable.cpp51
-rw-r--r--libs/hwui/VectorDrawable.h15
-rw-r--r--libs/hwui/hwui/MinikinUtils.cpp3
-rw-r--r--libs/hwui/pipeline/skia/RenderNodeDrawable.cpp31
-rw-r--r--libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp22
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp25
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.h1
-rw-r--r--libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp23
-rw-r--r--libs/hwui/pipeline/skia/VectorDrawableAtlas.h21
-rw-r--r--libs/hwui/renderstate/Blend.h8
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp31
-rw-r--r--libs/hwui/renderthread/CacheManager.h8
-rw-r--r--libs/hwui/renderthread/CanvasContext.h4
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp2
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h4
-rw-r--r--libs/hwui/renderthread/EglManager.cpp2
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp26
-rw-r--r--libs/hwui/renderthread/RenderProxy.h2
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp4
-rw-r--r--libs/hwui/renderthread/RenderThread.h8
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp49
-rw-r--r--libs/hwui/tests/common/scenes/TvApp.cpp274
-rw-r--r--libs/hwui/tests/unit/BakedOpRendererTests.cpp51
-rw-r--r--libs/incident/include/android/os/IncidentReportArgs.h6
-rw-r--r--libs/incident/src/IncidentReportArgs.cpp24
-rw-r--r--libs/services/include/android/os/DropBoxManager.h12
-rw-r--r--libs/services/src/os/DropBoxManager.cpp34
-rw-r--r--libs/usb/Android.bp1
-rw-r--r--libs/usb/tests/AccessoryChat/Android.bp1
-rw-r--r--libs/usb/tests/AccessoryChat/accessorychat/Android.bp30
-rw-r--r--libs/usb/tests/AccessoryChat/accessorychat/Android.mk35
-rw-r--r--libs/usb/tests/accessorytest/Android.bp28
-rw-r--r--libs/usb/tests/accessorytest/Android.mk25
-rw-r--r--libs/usb/tests/accessorytest/accessory.h2
-rw-r--r--libs/usb/tests/accessorytest/hid.c2
-rw-r--r--libs/usb/tests/accessorytest/usb.c2
42 files changed, 761 insertions, 171 deletions
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 0782269d7de1..7a0ef2b770ce 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -59,7 +59,6 @@ namespace android {
#endif
#define IDMAP_MAGIC 0x504D4449
-#define IDMAP_CURRENT_VERSION 0x00000001
#define APP_PACKAGE_ID 0x7f
#define SYS_PACKAGE_ID 0x01
@@ -246,11 +245,11 @@ static bool assertIdmapHeader(const void* idmap, size_t size) {
}
const uint32_t version = htodl(*(reinterpret_cast<const uint32_t*>(idmap) + 1));
- if (version != IDMAP_CURRENT_VERSION) {
+ if (version != ResTable::IDMAP_CURRENT_VERSION) {
// We are strict about versions because files with this format are
// auto-generated and don't need backwards compatibility.
ALOGW("idmap: version mismatch in header (is 0x%08x, expected 0x%08x)",
- version, IDMAP_CURRENT_VERSION);
+ version, ResTable::IDMAP_CURRENT_VERSION);
return false;
}
return true;
@@ -6855,7 +6854,7 @@ status_t ResTable::createIdmap(const ResTable& overlay,
uint32_t* data = (uint32_t*)*outData;
*data++ = htodl(IDMAP_MAGIC);
- *data++ = htodl(IDMAP_CURRENT_VERSION);
+ *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION);
*data++ = htodl(targetCrc);
*data++ = htodl(overlayCrc);
const char* paths[] = { targetPath, overlayPath };
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 7a6e37d41b7c..66c66c251d9b 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1933,6 +1933,7 @@ public:
void** outData, size_t* outSize) const;
static const size_t IDMAP_HEADER_SIZE_BYTES = 4 * sizeof(uint32_t) + 2 * 256;
+ static const uint32_t IDMAP_CURRENT_VERSION = 0x00000001;
// Retrieve idmap meta-data.
//
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 4e59baa48983..3c3b3177159b 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -216,10 +216,7 @@ void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* pa
.setTransform(Matrix4::identity(), TransformFlags::None)
.setModelViewIdentityEmptyBounds()
.build();
- // Disable blending if this is the first draw to the main framebuffer, in case app has defined
- // transparency where it doesn't make sense - as first draw in opaque window.
- bool overrideDisableBlending = !mHasDrawn && mOpaque && !mRenderTarget.frameBufferId;
- mRenderState.render(glop, mRenderTarget.orthoMatrix, overrideDisableBlending);
+ mRenderState.render(glop, mRenderTarget.orthoMatrix, false);
mHasDrawn = true;
}
@@ -350,8 +347,14 @@ void BakedOpRenderer::renderGlopImpl(const Rect* dirtyBounds, const ClipBase* cl
const Glop& glop) {
prepareRender(dirtyBounds, clip);
// Disable blending if this is the first draw to the main framebuffer, in case app has defined
- // transparency where it doesn't make sense - as first draw in opaque window.
- bool overrideDisableBlending = !mHasDrawn && mOpaque && !mRenderTarget.frameBufferId;
+ // transparency where it doesn't make sense - as first draw in opaque window. Note that we only
+ // apply this improvement when the blend mode is SRC_OVER - other modes (e.g. CLEAR) can be
+ // valid draws that affect other content (e.g. draw CLEAR, then draw DST_OVER)
+ bool overrideDisableBlending = !mHasDrawn
+ && mOpaque
+ && !mRenderTarget.frameBufferId
+ && glop.blend.src == GL_ONE
+ && glop.blend.dst == GL_ONE_MINUS_SRC_ALPHA;
mRenderState.render(glop, mRenderTarget.orthoMatrix, overrideDisableBlending);
if (!mRenderTarget.frameBufferId) mHasDrawn = true;
}
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index fe291d2a4bfe..3b59bb1a8f02 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -177,7 +177,7 @@ RenderPipelineType Properties::getRenderPipelineType() {
return sRenderPipelineType;
}
char prop[PROPERTY_VALUE_MAX];
- property_get(PROPERTY_RENDERER, prop, "opengl");
+ property_get(PROPERTY_RENDERER, prop, "skiagl");
if (!strcmp(prop, "skiagl") ) {
ALOGD("Skia GL Pipeline");
sRenderPipelineType = RenderPipelineType::SkiaGL;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 61b3876cd095..36a747519c37 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -32,6 +32,7 @@
#include "protos/hwui.pb.h"
#include "protos/ProtoHelpers.h"
+#include <SkPathOps.h>
#include <algorithm>
#include <sstream>
#include <string>
@@ -555,5 +556,23 @@ void RenderNode::computeOrderingImpl(
}
}
+const SkPath* RenderNode::getClippedOutline(const SkRect& clipRect) const {
+ const SkPath* outlinePath = properties().getOutline().getPath();
+ const uint32_t outlineID = outlinePath->getGenerationID();
+
+ if (outlineID != mClippedOutlineCache.outlineID || clipRect != mClippedOutlineCache.clipRect) {
+ // update the cache keys
+ mClippedOutlineCache.outlineID = outlineID;
+ mClippedOutlineCache.clipRect = clipRect;
+
+ // update the cache value by recomputing a new path
+ SkPath clipPath;
+ clipPath.addRect(clipRect);
+ Op(*outlinePath, clipPath, kIntersect_SkPathOp, &mClippedOutlineCache.clippedOutline);
+
+ }
+ return &mClippedOutlineCache.clippedOutline;
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index c4ae82af430c..89e022f5e68d 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -365,6 +365,17 @@ public:
return mSkiaLayer.get();
}
+ /**
+ * Returns the path that represents the outline of RenderNode intersected with
+ * the provided rect. This call will internally cache the resulting path in
+ * order to potentially return that path for subsequent calls to this method.
+ * By reusing the same path we get better performance on the GPU backends since
+ * those resources are cached in the hardware based on the path's genID.
+ *
+ * The returned path is only guaranteed to be valid until this function is called
+ * again or the RenderNode's outline is mutated.
+ */
+ const SkPath* getClippedOutline(const SkRect& clipRect) const;
private:
/**
* If this RenderNode has been used in a previous frame then the SkiaDisplayList
@@ -380,6 +391,16 @@ private:
* when it has been set to draw as a LayerType::RenderLayer.
*/
std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
+
+ struct ClippedOutlineCache {
+ // keys
+ uint32_t outlineID = 0;
+ SkRect clipRect;
+
+ // value
+ SkPath clippedOutline;
+ };
+ mutable ClippedOutlineCache mClippedOutlineCache;
}; // class RenderNode
class MarkAndSweepRemoved : public TreeObserver {
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f4ce864e83e1..376371de80dc 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -22,6 +22,7 @@
#include "SkShader.h"
#include <utils/Log.h>
#include "utils/Macros.h"
+#include "utils/TraceUtils.h"
#include "utils/VectorDrawableUtils.h"
#include <math.h>
@@ -511,25 +512,19 @@ void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext*
}
}
if (!canReuseSurface || mCache.dirty) {
- draw(surface.get(), dst);
+ if (surface) {
+ Bitmap& bitmap = getBitmapUpdateIfDirty();
+ SkBitmap skiaBitmap;
+ bitmap.getSkBitmap(&skiaBitmap);
+ if (!surface->getCanvas()->writePixels(skiaBitmap, dst.fLeft, dst.fTop)) {
+ ALOGD("VectorDrawable caching failed to efficiently upload");
+ surface->getCanvas()->drawBitmap(skiaBitmap, dst.fLeft, dst.fTop);
+ }
+ }
mCache.dirty = false;
}
}
-void Tree::draw(SkSurface* surface, const SkRect& dst) {
- if (surface) {
- SkCanvas* canvas = surface->getCanvas();
- float scaleX = dst.width() / mProperties.getViewportWidth();
- float scaleY = dst.height() / mProperties.getViewportHeight();
- SkAutoCanvasRestore acr(canvas, true);
- canvas->translate(dst.fLeft, dst.fTop);
- canvas->clipRect(SkRect::MakeWH(dst.width(), dst.height()));
- canvas->clear(SK_ColorTRANSPARENT);
- canvas->scale(scaleX, scaleY);
- mRootNode->draw(canvas, false);
- }
-}
-
void Tree::Cache::setAtlas(sp<skiapipeline::VectorDrawableAtlas> newAtlas,
skiapipeline::AtlasKey newAtlasKey) {
LOG_ALWAYS_FATAL_IF(newAtlasKey == INVALID_ATLAS_KEY);
@@ -570,22 +565,15 @@ void Tree::draw(SkCanvas* canvas) {
// Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure.
// We render the VD into a temporary standalone buffer and mark the frame as dirty. Next
// frame will be cached into the atlas.
+ Bitmap& bitmap = getBitmapUpdateIfDirty();
+ SkBitmap skiaBitmap;
+ bitmap.getSkBitmap(&skiaBitmap);
+
int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
- SkRect src = SkRect::MakeWH(scaledWidth, scaledHeight);
-#ifndef ANDROID_ENABLE_LINEAR_BLENDING
- sk_sp<SkColorSpace> colorSpace = nullptr;
-#else
- sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
-#endif
- SkImageInfo info = SkImageInfo::MakeN32(scaledWidth, scaledHeight, kPremul_SkAlphaType,
- colorSpace);
- sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(canvas->getGrContext(),
- SkBudgeted::kYes, info);
- draw(surface.get(), src);
+ canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight),
+ mutateProperties()->getBounds(), getPaint(), SkCanvas::kFast_SrcRectConstraint);
mCache.clear();
- canvas->drawImageRect(surface->makeImageSnapshot().get(), mutateProperties()->getBounds(),
- getPaint(), SkCanvas::kFast_SrcRectConstraint);
markDirty();
}
}
@@ -593,14 +581,17 @@ void Tree::draw(SkCanvas* canvas) {
void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) {
SkBitmap outCache;
bitmap.getSkBitmap(&outCache);
+ int cacheWidth = outCache.width();
+ int cacheHeight = outCache.height();
+ ATRACE_FORMAT("VectorDrawable repaint %dx%d", cacheWidth, cacheHeight);
outCache.eraseColor(SK_ColorTRANSPARENT);
SkCanvas outCanvas(outCache);
float viewportWidth = useStagingData ?
mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
float viewportHeight = useStagingData ?
mStagingProperties.getViewportHeight() : mProperties.getViewportHeight();
- float scaleX = outCache.width() / viewportWidth;
- float scaleY = outCache.height() / viewportHeight;
+ float scaleX = cacheWidth / viewportWidth;
+ float scaleY = cacheHeight / viewportHeight;
outCanvas.scale(scaleX, scaleY);
mRootNode->draw(&outCanvas, useStagingData);
}
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index efbb695a14dd..4b80542ad0d0 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -558,6 +558,16 @@ public:
SkPaint* getPaint();
void syncProperties() {
if (mStagingProperties.mNonAnimatablePropertiesDirty) {
+ mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth
+ != mStagingProperties.mNonAnimatableProperties.viewportWidth)
+ || (mProperties.mNonAnimatableProperties.viewportHeight
+ != mStagingProperties.mNonAnimatableProperties.viewportHeight)
+ || (mProperties.mNonAnimatableProperties.scaledWidth
+ != mStagingProperties.mNonAnimatableProperties.scaledWidth)
+ || (mProperties.mNonAnimatableProperties.scaledHeight
+ != mStagingProperties.mNonAnimatableProperties.scaledHeight)
+ || (mProperties.mNonAnimatableProperties.bounds
+ != mStagingProperties.mNonAnimatableProperties.bounds);
mProperties.syncNonAnimatableProperties(mStagingProperties);
mStagingProperties.mNonAnimatablePropertiesDirty = false;
}
@@ -738,11 +748,6 @@ private:
bool canReuseBitmap(Bitmap*, int width, int height);
void updateBitmapCache(Bitmap& outCache, bool useStagingData);
- /**
- * Draws the root node into "surface" at a given "dst" position.
- */
- void draw(SkSurface* surface, const SkRect& dst);
-
// Cap the bitmap size, such that it won't hurt the performance too much
// and it won't crash due to a very large scale.
// The drawable will look blurry above this size.
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 5577bbf2bfc9..7da7f3876a3d 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -68,7 +68,8 @@ float MinikinUtils::measureText(const Paint* paint, int bidiFlags, const Typefac
minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle,
- minikinPaint, resolvedTypeface->fFontCollection, advances, nullptr /* extent */);
+ minikinPaint, resolvedTypeface->fFontCollection, advances, nullptr /* extent */,
+ nullptr /* overhangs */);
}
bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) {
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 4ee47afe87fd..47dee9d4e9d8 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -19,6 +19,7 @@
#include "SkiaDisplayList.h"
#include "SkiaPipeline.h"
#include "utils/TraceUtils.h"
+#include <SkPaintFilterCanvas.h>
namespace android {
namespace uirenderer {
@@ -151,6 +152,27 @@ static bool layerNeedsPaint(const LayerProperties& properties,
return false;
}
+class AlphaFilterCanvas : public SkPaintFilterCanvas {
+public:
+ AlphaFilterCanvas(SkCanvas* canvas, float alpha) : SkPaintFilterCanvas(canvas), mAlpha(alpha) {}
+protected:
+ bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override {
+ SkTLazy<SkPaint> defaultPaint;
+ if (!*paint) {
+ paint->init(*defaultPaint.init());
+ }
+ paint->writable()->setAlpha((uint8_t)(*paint)->getAlpha()*mAlpha);
+ return true;
+ }
+ void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
+ // We unroll the drawable using "this" canvas, so that draw calls contained inside will
+ // get their alpha applied. THe default SkPaintFilterCanvas::onDrawDrawable does not unroll.
+ drawable->draw(this, matrix);
+ }
+private:
+ float mAlpha;
+};
+
void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
RenderNode* renderNode = mRenderNode.get();
float alphaMultiplier = 1.0f;
@@ -211,7 +233,14 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
canvas->restore();
}
} else {
- displayList->draw(canvas);
+ if (alphaMultiplier < 1.0f) {
+ // Non-layer draw for a view with getHasOverlappingRendering=false, will apply
+ // the alpha to the paint of each nested draw.
+ AlphaFilterCanvas alphaCanvas(canvas, alphaMultiplier);
+ displayList->draw(&alphaCanvas);
+ } else {
+ displayList->draw(canvas);
+ }
}
}
}
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 374d364787de..c8207bc70dd4 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -163,28 +163,22 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
hwuiMatrix.copyTo(shadowMatrix);
canvas->concat(shadowMatrix);
- const SkPath* casterOutlinePath = casterProperties.getOutline().getPath();
- // holds temporary SkPath to store the result of intersections
- SkPath tmpPath;
- const SkPath* casterPath = casterOutlinePath;
+ // default the shadow-casting path to the outline of the caster
+ const SkPath* casterPath = casterProperties.getOutline().getPath();
+
+ // intersect the shadow-casting path with the clipBounds, if present
+ if (clippedToBounds && !casterClipRect.contains(casterPath->getBounds())) {
+ casterPath = caster->getRenderNode()->getClippedOutline(casterClipRect);
+ }
- // TODO: In to following course of code that calculates the final shape, is there an optimal
- // of doing the Op calculations?
// intersect the shadow-casting path with the reveal, if present
+ SkPath tmpPath; // holds temporary SkPath to store the result of intersections
if (revealClipPath) {
Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, &tmpPath);
tmpPath.setIsVolatile(true);
casterPath = &tmpPath;
}
- // intersect the shadow-casting path with the clipBounds, if present
- if (clippedToBounds) {
- SkPath clipBoundsPath;
- clipBoundsPath.addRect(casterClipRect);
- Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath);
- tmpPath.setIsVolatile(true);
- casterPath = &tmpPath;
- }
const Vector3 lightPos = SkiaPipeline::getLightCenter();
SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
SkPoint3 zParams;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index a8463ecc44d8..6f117de23864 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -46,7 +46,7 @@ SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) {
}
TaskManager* SkiaPipeline::getTaskManager() {
- return &mTaskManager;
+ return mRenderThread.cacheManager().getTaskManager();
}
void SkiaPipeline::onDestroyHardwareResources() {
@@ -83,7 +83,8 @@ void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry
void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
bool opaque, bool wideColorGamut) {
- // TODO: Handle wide color gamut
+ sk_sp<GrContext> cachedContext;
+
// Render all layers that need to be updated, in order.
for (size_t i = 0; i < layers.entries().size(); i++) {
RenderNode* layerNode = layers.entries()[i].renderNode.get();
@@ -118,16 +119,31 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
return;
}
+ ATRACE_FORMAT("drawLayer [%s] %.1f x %.1f", layerNode->getName(), bounds.width(), bounds.height());
+
layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
layerCanvas->clear(SK_ColorTRANSPARENT);
RenderNodeDrawable root(layerNode, layerCanvas, false);
root.forceDraw(layerCanvas);
layerCanvas->restoreToCount(saveCount);
- layerCanvas->flush();
mLightCenter = savedLightCenter;
+
+ // cache the current context so that we can defer flushing it until
+ // either all the layers have been rendered or the context changes
+ GrContext* currentContext = layerCanvas->getGrContext();
+ if (cachedContext.get() != currentContext) {
+ if (cachedContext.get()) {
+ cachedContext->flush();
+ }
+ cachedContext.reset(SkSafeRef(currentContext));
+ }
}
}
+
+ if (cachedContext.get()) {
+ cachedContext->flush();
+ }
}
bool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
@@ -143,7 +159,6 @@ bool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
}
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkASSERT(mRenderThread.getGrContext() != nullptr);
- // TODO: Handle wide color gamut requests
node->setLayerSurface(
SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
info, 0, &props));
@@ -194,10 +209,10 @@ void SkiaPipeline::renderVectorDrawableCache() {
sp<VectorDrawableAtlas> atlas = mRenderThread.cacheManager().acquireVectorDrawableAtlas();
auto grContext = mRenderThread.getGrContext();
atlas->prepareForDraw(grContext);
+ ATRACE_NAME("Update VectorDrawables");
for (auto vd : mVectorDrawables) {
vd->updateCache(atlas, grContext);
}
- grContext->flush();
mVectorDrawables.clear();
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 19ffc463c121..2b0c419aa1a1 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -126,7 +126,6 @@ private:
*/
void renderVectorDrawableCache();
- TaskManager mTaskManager;
std::vector<sk_sp<SkImage>> mPinnedImages;
/**
diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp b/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp
index 437653a8dfa8..9c9e17d600bf 100644
--- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp
+++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp
@@ -21,6 +21,7 @@
#include <cmath>
#include "utils/TraceUtils.h"
#include "renderthread/RenderProxy.h"
+#include "renderthread/RenderThread.h"
namespace android {
namespace uirenderer {
@@ -228,6 +229,15 @@ AtlasEntry VectorDrawableAtlas::getEntry(AtlasKey atlasKey) {
void VectorDrawableAtlas::releaseEntry(AtlasKey atlasKey) {
if (INVALID_ATLAS_KEY != atlasKey) {
+ if (!renderthread::RenderThread::isCurrent()) {
+ {
+ AutoMutex _lock(mReleaseKeyLock);
+ mKeysForRelease.push_back(atlasKey);
+ }
+ // invoke releaseEntry on the renderthread
+ renderthread::RenderProxy::releaseVDAtlasEntries();
+ return;
+ }
CacheEntry* entry = reinterpret_cast<CacheEntry*>(atlasKey);
if (!entry->surface) {
// Store freed atlas rectangles in "mFreeRects" and try to reuse them later, when atlas
@@ -245,6 +255,14 @@ void VectorDrawableAtlas::releaseEntry(AtlasKey atlasKey) {
}
}
+void VectorDrawableAtlas::delayedReleaseEntries() {
+ AutoMutex _lock(mReleaseKeyLock);
+ for (auto key : mKeysForRelease) {
+ releaseEntry(key);
+ }
+ mKeysForRelease.clear();
+}
+
sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrContext* context) {
#ifndef ANDROID_ENABLE_LINEAR_BLENDING
sk_sp<SkColorSpace> colorSpace = nullptr;
@@ -252,7 +270,10 @@ sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrCon
sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
#endif
SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace);
- return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info);
+ // This must have a top-left origin so that calls to surface->canvas->writePixels
+ // performs a basic texture upload instead of a more complex drawing operation
+ return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
+ kTopLeft_GrSurfaceOrigin, nullptr);
}
void VectorDrawableAtlas::setStorageMode(StorageMode mode) {
diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
index 496c55742748..0683b3915850 100644
--- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
+++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
@@ -20,6 +20,7 @@
#include <SkSurface.h>
#include <utils/FatVector.h>
#include <utils/RefBase.h>
+#include <utils/Thread.h>
#include <list>
class GrRectanizer;
@@ -103,12 +104,19 @@ public:
/**
* "releaseEntry" is invoked when a VectorDrawable is deleted. Passing a non-existing "atlasKey"
- * is causing an undefined behaviour.
+ * is causing an undefined behaviour. This is the only function in the class that can be
+ * invoked from any thread. It will marshal internally to render thread if needed.
*/
void releaseEntry(AtlasKey atlasKey);
void setStorageMode(StorageMode mode);
+ /**
+ * "delayedReleaseEntries" is indirectly invoked by "releaseEntry", when "releaseEntry" is
+ * invoked from a non render thread.
+ */
+ void delayedReleaseEntries();
+
private:
struct CacheEntry {
CacheEntry(const SkRect& newVDrect, const SkRect& newRect,
@@ -182,6 +190,17 @@ private:
*/
StorageMode mStorageMode;
+ /**
+ * mKeysForRelease is used by releaseEntry implementation to pass atlas keys from an arbitrary
+ * calling thread to the render thread.
+ */
+ std::vector<AtlasKey> mKeysForRelease;
+
+ /**
+ * A lock used to protect access to mKeysForRelease.
+ */
+ Mutex mReleaseKeyLock;
+
sk_sp<SkSurface> createSurface(int width, int height, GrContext* context);
inline bool fitInAtlas(int width, int height) {
diff --git a/libs/hwui/renderstate/Blend.h b/libs/hwui/renderstate/Blend.h
index ec0e114c998f..a9de24631340 100644
--- a/libs/hwui/renderstate/Blend.h
+++ b/libs/hwui/renderstate/Blend.h
@@ -40,6 +40,14 @@ public:
GLenum* outSrc, GLenum* outDst);
void setFactors(GLenum src, GLenum dst);
+ bool getEnabled() {
+ return mEnabled;
+ }
+ void getFactors(GLenum* src, GLenum* dst) {
+ *src = mSrcMode;
+ *dst = mDstMode;
+ }
+
void dump();
private:
Blend();
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index f6b23e1a0723..0572a8d0afac 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -22,6 +22,7 @@
#include <gui/Surface.h>
#include <GrContextOptions.h>
+#include <SkExecutor.h>
#include <math.h>
#include <set>
@@ -73,6 +74,29 @@ void CacheManager::updateContextCacheSizes() {
mGrContext->setResourceCacheLimits(mMaxResources, mMaxResourceBytes);
}
+class CacheManager::SkiaTaskProcessor : public TaskProcessor<bool>, public SkExecutor {
+public:
+ explicit SkiaTaskProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}
+
+ // This is really a Task<void> but that doesn't really work when Future<>
+ // expects to be able to get/set a value
+ struct SkiaTask : public Task<bool> {
+ std::function<void()> func;
+ };
+
+ virtual void add(std::function<void(void)> func) override {
+ sp<SkiaTask> task(new SkiaTask());
+ task->func = func;
+ TaskProcessor<bool>::add(task);
+ }
+
+ virtual void onProcess(const sp<Task<bool> >& task) override {
+ SkiaTask* t = static_cast<SkiaTask*>(task.get());
+ t->func();
+ task->setResult(true);
+ }
+};
+
void CacheManager::configureContext(GrContextOptions* contextOptions) {
contextOptions->fAllowPathMaskCaching = true;
@@ -95,6 +119,13 @@ void CacheManager::configureContext(GrContextOptions* contextOptions) {
// Skia's implementation doesn't provide a mechanism to resize the font cache due to
// the potential cost of recreating the glyphs.
contextOptions->fGlyphCacheTextureMaximumBytes = fontCacheMB * 1024 * 1024;
+
+ if (mTaskManager.canRunTasks()) {
+ if (!mTaskProcessor.get()) {
+ mTaskProcessor = new SkiaTaskProcessor(&mTaskManager);
+ }
+ contextOptions->fExecutor = mTaskProcessor.get();
+ }
}
void CacheManager::trimMemory(TrimMemoryMode mode) {
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 90362f33358d..3ba2690caf31 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -22,7 +22,10 @@
#include <ui/DisplayInfo.h>
#include <utils/String8.h>
#include <vector>
+
#include "pipeline/skia/VectorDrawableAtlas.h"
+#include "thread/TaskManager.h"
+#include "thread/TaskProcessor.h"
namespace android {
@@ -54,6 +57,7 @@ public:
size_t getCacheSize() const { return mMaxResourceBytes; }
size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; }
+ TaskManager* getTaskManager() { return &mTaskManager; }
private:
friend class RenderThread;
@@ -77,6 +81,10 @@ private:
};
sp<skiapipeline::VectorDrawableAtlas> mVectorDrawableAtlas;
+
+ class SkiaTaskProcessor;
+ sp<SkiaTaskProcessor> mTaskProcessor;
+ TaskManager mTaskManager;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index aa6d2f3513d7..4a5b2c72b02a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -162,8 +162,8 @@ public:
void addRenderNode(RenderNode* node, bool placeFront);
void removeRenderNode(RenderNode* node);
- void setContentDrawBounds(int left, int top, int right, int bottom) {
- mContentDrawBounds.set(left, top, right, bottom);
+ void setContentDrawBounds(const Rect& bounds) {
+ mContentDrawBounds = bounds;
}
RenderState& getRenderState() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 7d641d3ac7c7..a097272df359 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -32,6 +32,7 @@ namespace renderthread {
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
+ , mContentDrawBounds(0, 0, 0, 0)
, mSyncResult(SyncResult::OK) {
}
@@ -123,6 +124,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mLayers[i]->apply();
}
mLayers.clear();
+ mContext->setContentDrawBounds(mContentDrawBounds);
mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
// This is after the prepareTree so that any pending operations
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index fb480626d421..83ecb98f548f 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -61,6 +61,9 @@ public:
virtual ~DrawFrameTask();
void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
+ void setContentDrawBounds(int left, int top, int right, int bottom) {
+ mContentDrawBounds.set(left, top, right, bottom);
+ }
void pushLayerUpdate(DeferredLayerUpdater* layer);
void removeLayerUpdate(DeferredLayerUpdater* layer);
@@ -82,6 +85,7 @@ private:
RenderThread* mRenderThread;
CanvasContext* mContext;
RenderNode* mTargetNode = nullptr;
+ Rect mContentDrawBounds;
/*********************************************
* Single frame data
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 16d77364942e..87e5bfdc8ca5 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -138,7 +138,7 @@ void EglManager::initialize() {
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
- options.fGpuPathRenderers &= ~GrContextOptions::GpuPathRenderers::kDistanceField;
+ options.fDisableDistanceFieldPaths = true;
mRenderThread.cacheManager().configureContext(&options);
mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend,
(GrBackendContext)glInterface.get(), options));
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 7fe966dde316..a6aa301021e2 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -551,20 +551,8 @@ void RenderProxy::drawRenderNode(RenderNode* node) {
staticPostAndWait(task);
}
-CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
- int right, int bottom) {
- args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
- return nullptr;
-}
-
void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
- SETUP_TASK(setContentDrawBounds);
- args->context = mContext;
- args->left = left;
- args->top = top;
- args->right = right;
- args->bottom = bottom;
- staticPostAndWait(task);
+ mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
}
CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
@@ -732,6 +720,18 @@ void RenderProxy::repackVectorDrawableAtlas() {
thread.queue(task);
}
+CREATE_BRIDGE1(releaseVDAtlasEntries, RenderThread* thread) {
+ args->thread->cacheManager().acquireVectorDrawableAtlas()->delayedReleaseEntries();
+ return nullptr;
+}
+
+void RenderProxy::releaseVDAtlasEntries() {
+ RenderThread& thread = RenderThread::getInstance();
+ SETUP_TASK(releaseVDAtlasEntries);
+ args->thread = &thread;
+ thread.queue(task);
+}
+
void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
void* retval;
task->setReturnPtr(&retval);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 06eaebd066ee..9440b15f6062 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -143,6 +143,8 @@ public:
static void repackVectorDrawableAtlas();
+ static void releaseVDAtlasEntries();
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 72a428f1c70c..51e937485fab 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -499,6 +499,10 @@ sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
return nullptr;
}
+bool RenderThread::isCurrent() {
+ return gettid() == getInstance().getTid();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index bef47b3e27c5..30884b571b94 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -111,6 +111,14 @@ public:
sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap);
void dumpGraphicsMemory(int fd);
+ /**
+ * isCurrent provides a way to query, if the caller is running on
+ * the render thread.
+ *
+ * @return true only if isCurrent is invoked from the render thread.
+ */
+ static bool isCurrent();
+
protected:
virtual bool threadLoop() override;
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 3a77195824ad..afb1193657e1 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -40,7 +40,7 @@ static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong"
constexpr int sHistogramSize = ProfileData::HistogramSize();
-static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
+static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
const std::string& package, int versionCode, int64_t startTime, int64_t endTime,
const ProfileData* data);
static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
@@ -159,7 +159,7 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, service::Graph
return success;
}
-void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
+bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
proto->set_stats_start(startTime);
@@ -188,23 +188,31 @@ void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st
proto->mutable_histogram()->Reserve(sHistogramSize);
creatingHistogram = true;
} else if (proto->histogram_size() != sHistogramSize) {
- LOG_ALWAYS_FATAL("Histogram size mismatch, proto is %d expected %d",
+ ALOGE("Histogram size mismatch, proto is %d expected %d",
proto->histogram_size(), sHistogramSize);
+ return false;
}
int index = 0;
+ bool hitMergeError = false;
data->histogramForEach([&](ProfileData::HistogramEntry entry) {
+ if (hitMergeError) return;
+
service::GraphicsStatsHistogramBucketProto* bucket;
if (creatingHistogram) {
bucket = proto->add_histogram();
bucket->set_render_millis(entry.renderTimeMs);
} else {
bucket = proto->mutable_histogram(index);
- LOG_ALWAYS_FATAL_IF(bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs),
- "Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+ if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
+ ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+ hitMergeError = true;
+ return;
+ }
}
bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
index++;
});
+ return !hitMergeError;
}
static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
@@ -221,9 +229,11 @@ static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile
void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
// This isn't a full validation, just enough that we can deref at will
- LOG_ALWAYS_FATAL_IF(proto->package_name().empty()
- || !proto->has_summary(), "package_name() '%s' summary %d",
- proto->package_name().c_str(), proto->has_summary());
+ if (proto->package_name().empty() || !proto->has_summary()) {
+ ALOGW("Skipping dump, invalid package_name() '%s' or summary %d",
+ proto->package_name().c_str(), proto->has_summary());
+ return;
+ }
dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
dprintf(fd, "\nVersion: %d", proto->version_code());
dprintf(fd, "\nStats since: %lldns", proto->stats_start());
@@ -254,14 +264,20 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string
if (!parseFromFile(path, &statsProto)) {
statsProto.Clear();
}
- mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+ if (!mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) {
+ return;
+ }
// Although we might not have read any data from the file, merging the existing data
// should always fully-initialize the proto
- LOG_ALWAYS_FATAL_IF(!statsProto.IsInitialized(), "%s",
- statsProto.InitializationErrorString().c_str());
- LOG_ALWAYS_FATAL_IF(statsProto.package_name().empty()
- || !statsProto.has_summary(), "package_name() '%s' summary %d",
- statsProto.package_name().c_str(), statsProto.has_summary());
+ if (!statsProto.IsInitialized()) {
+ ALOGE("proto initialization error %s", statsProto.InitializationErrorString().c_str());
+ return;
+ }
+ if (statsProto.package_name().empty() || !statsProto.has_summary()) {
+ ALOGE("missing package_name() '%s' summary %d",
+ statsProto.package_name().c_str(), statsProto.has_summary());
+ return;
+ }
int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660);
if (outFd <= 0) {
int err = errno;
@@ -312,8 +328,9 @@ void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, const
if (!path.empty() && !parseFromFile(path, &statsProto)) {
statsProto.Clear();
}
- if (data) {
- mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+ if (data && !mergeProfileDataIntoProto(
+ &statsProto, package, versionCode, startTime, endTime, data)) {
+ return;
}
if (!statsProto.IsInitialized()) {
ALOGW("Failed to load profile data from path '%s' and data %p",
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp
new file mode 100644
index 000000000000..04fc2d46f946
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/TvApp.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2017 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 "TestSceneBase.h"
+#include "tests/common/BitmapAllocationTestUtils.h"
+#include "SkBlendMode.h"
+
+class TvApp;
+class TvAppNoRoundedCorner;
+class TvAppColorFilter;
+class TvAppNoRoundedCornerColorFilter;
+
+static bool _TvApp(
+ BitmapAllocationTestUtils::registerBitmapAllocationScene<TvApp>(
+ "tvapp", "A dense grid of cards:"
+ "with rounded corner, using overlay RenderNode for dimming."));
+
+static bool _TvAppNoRoundedCorner(
+ BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCorner>(
+ "tvapp_norc", "A dense grid of cards:"
+ "no rounded corner, using overlay RenderNode for dimming"));
+
+static bool _TvAppColorFilter(
+ BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppColorFilter>(
+ "tvapp_cf", "A dense grid of cards:"
+ "with rounded corner, using ColorFilter for dimming"));
+
+static bool _TvAppNoRoundedCornerColorFilter(
+ BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCornerColorFilter>(
+ "tvapp_norc_cf", "A dense grid of cards:"
+ "no rounded corner, using ColorFilter for dimming"));
+
+class TvApp : public TestScene {
+public:
+ TvApp(BitmapAllocationTestUtils::BitmapAllocator allocator)
+ : TestScene()
+ , mAllocator(allocator) { }
+
+ sp<RenderNode> mBg;
+ std::vector<sp<RenderNode>> mCards;
+ std::vector<sp<RenderNode>> mInfoAreas;
+ std::vector<sp<RenderNode>> mImages;
+ std::vector<sp<RenderNode>> mOverlays;
+ std::vector<sk_sp<Bitmap>> mCachedBitmaps;
+ BitmapAllocationTestUtils::BitmapAllocator mAllocator;
+ sk_sp<Bitmap> mSingleBitmap;
+ int mSeed = 0;
+ int mSeed2 = 0;
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ mBg = createBitmapNode(canvas, 0xFF9C27B0, 0, 0, width, height);
+ canvas.drawRenderNode(mBg.get());
+
+ canvas.insertReorderBarrier(true);
+ mSingleBitmap = mAllocator(dp(160), dp(120), kRGBA_8888_SkColorType,
+ [](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(0xFF0000FF);
+ });
+
+ for (int y = dp(18) - dp(178); y < height - dp(18); y += dp(178)) {
+ bool isFirstCard = true;
+ for (int x = dp(18); x < width - dp(18); x += dp(178)) {
+ sp<RenderNode> card = createCard(x, y, dp(160), dp(160), isFirstCard);
+ isFirstCard = false;
+ canvas.drawRenderNode(card.get());
+ mCards.push_back(card);
+ }
+ }
+ canvas.insertReorderBarrier(false);
+ }
+
+ void doFrame(int frameNr) override {
+ size_t numCards = mCards.size();
+ for (size_t ci = 0; ci < numCards; ci++) {
+ updateCard(ci, frameNr);
+ }
+ }
+
+private:
+ sp<RenderNode> createBitmapNode(Canvas& canvas, SkColor color, int left, int top,
+ int width, int height) {
+ return TestUtils::createNode(left, top, left + width , top + height,
+ [this, width, height, color](RenderProperties& props, Canvas& canvas) {
+ sk_sp<Bitmap> bitmap = mAllocator(width, height, kRGBA_8888_SkColorType,
+ [color](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(color);
+ });
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
+ }
+
+ sp<RenderNode> createSharedBitmapNode(Canvas& canvas, int left, int top,
+ int width, int height, sk_sp<Bitmap>bitmap) {
+ return TestUtils::createNode(left, top, left + width , top + height,
+ [bitmap](RenderProperties& props, Canvas& canvas) {
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
+ }
+
+ sp<RenderNode> createInfoNode(Canvas& canvas, int left, int top,
+ int width, int height, const char* text, const char* text2) {
+ return TestUtils::createNode(left, top, left + width , top + height,
+ [text, text2](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver);
+
+ SkPaint paint;
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setAntiAlias(true);
+ paint.setTextSize(24);
+
+ paint.setColor(Color::Black);
+ TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30);
+ paint.setTextSize(20);
+ TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54);
+
+ });
+ }
+
+ sp<RenderNode> createColorNode(Canvas& canvas, int left, int top,
+ int width, int height, SkColor color) {
+ return TestUtils::createNode(left, top, left + width , top + height,
+ [color](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(color, SkBlendMode::kSrcOver);
+ });
+ }
+
+ virtual bool useSingleBitmap() {
+ return false;
+ }
+
+ virtual float roundedCornerRadius() {
+ return dp(2);
+ }
+
+ // when true, use overlay RenderNode for dimming, otherwise apply a ColorFilter to dim image
+ virtual bool useOverlay() {
+ return true;
+ }
+
+ sp<RenderNode> createCard(int x, int y, int width, int height, bool selected) {
+ return TestUtils::createNode(x, y, x + width, y + height,
+ [width, height, selected, this](RenderProperties& props, Canvas& canvas) {
+ if (selected) {
+ props.setElevation(dp(16));
+ props.setScaleX(1.2);
+ props.setScaleY(1.2);
+ }
+ props.mutableOutline().setRoundRect(0, 0, width, height, roundedCornerRadius(), 1);
+ props.mutableOutline().setShouldClip(true);
+
+ sk_sp<Bitmap> bitmap = useSingleBitmap() ? mSingleBitmap
+ : mAllocator(width, dp(120), kRGBA_8888_SkColorType, [this](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(0xFF000000 | ((mSeed << 3) & 0xFF));
+ });
+ sp<RenderNode> cardImage = createSharedBitmapNode(canvas, 0, 0, width, dp(120),
+ bitmap);
+ canvas.drawRenderNode(cardImage.get());
+ mCachedBitmaps.push_back(bitmap);
+ mImages.push_back(cardImage);
+
+ char buffer[128];
+ sprintf(buffer, "Video %d-%d", mSeed, mSeed + 1);
+ mSeed++;
+ char buffer2[128];
+ sprintf(buffer2, "Studio %d", mSeed2++);
+ sp<RenderNode> infoArea = createInfoNode(canvas, 0, dp(120), width, height, buffer, buffer2);
+ canvas.drawRenderNode(infoArea.get());
+ mInfoAreas.push_back(infoArea);
+
+ if (useOverlay()) {
+ sp<RenderNode> overlayColor = createColorNode(canvas, 0, 0, width, height, 0x00000000);
+ canvas.drawRenderNode(overlayColor.get());
+ mOverlays.push_back(overlayColor);
+ }
+ });
+ }
+
+ void updateCard(int ci, int curFrame) {
+ // updating card's translation Y
+ sp<RenderNode> card = mCards[ci];
+ card->setPropertyFieldsDirty(RenderNode::Y);
+ card->mutateStagingProperties().setTranslationY(curFrame % 150);
+
+ // re-recording card's canvas, not necessary but to add some burden to CPU
+ std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas(
+ card->stagingProperties().getWidth(),
+ card->stagingProperties().getHeight()));
+ sp<RenderNode> image = mImages[ci];
+ sp<RenderNode> infoArea = mInfoAreas[ci];
+ cardcanvas->drawRenderNode(infoArea.get());
+
+ if (useOverlay()) {
+ cardcanvas->drawRenderNode(image.get());
+ // re-recording card overlay's canvas, animating overlay color alpha
+ sp<RenderNode> overlay = mOverlays[ci];
+ std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
+ overlay->stagingProperties().getWidth(),
+ overlay->stagingProperties().getHeight()));
+ canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver);
+ overlay->setStagingDisplayList(canvas->finishRecording());
+ cardcanvas->drawRenderNode(overlay.get());
+ } else {
+ // re-recording image node's canvas, animating ColorFilter
+ std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
+ image->stagingProperties().getWidth(),
+ image->stagingProperties().getHeight()));
+ SkPaint paint;
+ sk_sp<SkColorFilter> filter(SkColorFilter::MakeModeFilter((curFrame % 150) << 24,
+ SkBlendMode::kSrcATop));
+ paint.setColorFilter(filter);
+ sk_sp<Bitmap> bitmap = mCachedBitmaps[ci];
+ canvas->drawBitmap(*bitmap, 0, 0, &paint);
+ image->setStagingDisplayList(canvas->finishRecording());
+ cardcanvas->drawRenderNode(image.get());
+ }
+
+ card->setStagingDisplayList(cardcanvas->finishRecording());
+ }
+};
+
+class TvAppNoRoundedCorner : public TvApp {
+public:
+ TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator)
+ : TvApp(allocator) { }
+
+private:
+
+ virtual float roundedCornerRadius() override {
+ return dp(0);
+ }
+};
+
+class TvAppColorFilter : public TvApp {
+public:
+ TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)
+ : TvApp(allocator) { }
+
+private:
+
+ virtual bool useOverlay() override {
+ return false;
+ }
+};
+
+class TvAppNoRoundedCornerColorFilter : public TvApp {
+public:
+ TvAppNoRoundedCornerColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)
+ : TvApp(allocator) { }
+
+private:
+
+ virtual float roundedCornerRadius() override {
+ return dp(0);
+ }
+
+ virtual bool useOverlay() override {
+ return false;
+ }
+};
+
+
diff --git a/libs/hwui/tests/unit/BakedOpRendererTests.cpp b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
index 603599ceb88a..38e106a8ab77 100644
--- a/libs/hwui/tests/unit/BakedOpRendererTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <BakedOpRenderer.h>
+#include <GlopBuilder.h>
#include <tests/common/TestUtils.h>
using namespace android::uirenderer;
@@ -53,3 +54,53 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpRenderer, startRepaintLayer_clear) {
renderer.endLayer();
}
}
+
+static void drawFirstOp(RenderState& renderState, int color, SkBlendMode mode) {
+ BakedOpRenderer renderer(Caches::getInstance(), renderState, true, false, sLightInfo);
+
+ renderer.startFrame(100, 100, Rect(100, 100));
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setBlendMode(mode);
+
+ Rect dest(0, 0, 100, 100);
+ Glop glop;
+ GlopBuilder(renderState, Caches::getInstance(), &glop)
+ .setRoundRectClipState(nullptr)
+ .setMeshUnitQuad()
+ .setFillPaint(paint, 1.0f)
+ .setTransform(Matrix4::identity(), TransformFlags::None)
+ .setModelViewMapUnitToRectSnap(dest)
+ .build();
+ renderer.renderGlop(nullptr, nullptr, glop);
+ renderer.endFrame(Rect(100, 100));
+}
+
+static void verifyBlend(RenderState& renderState, GLenum expectedSrc, GLenum expectedDst) {
+ EXPECT_TRUE(renderState.blend().getEnabled());
+ GLenum src;
+ GLenum dst;
+ renderState.blend().getFactors(&src, &dst);
+ EXPECT_EQ(expectedSrc, src);
+ EXPECT_EQ(expectedDst, dst);
+}
+
+static void verifyBlendDisabled(RenderState& renderState) {
+ EXPECT_FALSE(renderState.blend().getEnabled());
+}
+
+RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpRenderer, firstDrawBlend_clear) {
+ // initialize blend state to nonsense value
+ renderThread.renderState().blend().setFactors(GL_ONE, GL_ONE);
+
+ drawFirstOp(renderThread.renderState(), 0xfeff0000, SkBlendMode::kClear);
+ verifyBlend(renderThread.renderState(), GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpRenderer, firstDrawBlend_srcover) {
+ // initialize blend state to nonsense value
+ renderThread.renderState().blend().setFactors(GL_ONE, GL_ONE);
+
+ drawFirstOp(renderThread.renderState(), 0xfeff0000, SkBlendMode::kSrcOver);
+ verifyBlendDisabled(renderThread.renderState());
+}
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index 956ef6c39b99..da8098970962 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -39,12 +39,13 @@ public:
virtual status_t readFromParcel(const Parcel* in);
void setAll(bool all);
+ void setDest(int dest);
void addSection(int section);
void addHeader(const vector<int8_t>& header);
- inline bool all() const { return mAll; };
+ inline bool all() const { return mAll; }
bool containsSection(int section) const;
-
+ inline int dest() const { return mDest; }
inline const set<int>& sections() const { return mSections; }
inline const vector<vector<int8_t>>& headers() const { return mHeaders; }
@@ -54,6 +55,7 @@ private:
set<int> mSections;
vector<vector<int8_t>> mHeaders;
bool mAll;
+ int mDest;
};
}
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index f60490911aed..e62872238387 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -25,14 +25,16 @@ namespace os {
IncidentReportArgs::IncidentReportArgs()
:mSections(),
- mAll(false)
+ mAll(false),
+ mDest(-1)
{
}
IncidentReportArgs::IncidentReportArgs(const IncidentReportArgs& that)
:mSections(that.mSections),
mHeaders(that.mHeaders),
- mAll(that.mAll)
+ mAll(that.mAll),
+ mDest(that.mDest)
{
}
@@ -74,6 +76,11 @@ IncidentReportArgs::writeToParcel(Parcel* out) const
}
}
+ err = out->writeInt32(mDest);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
return NO_ERROR;
}
@@ -120,6 +127,13 @@ IncidentReportArgs::readFromParcel(const Parcel* in)
}
}
+ int32_t dest;
+ err = in->readInt32(&dest);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ mDest = dest;
+
return OK;
}
@@ -133,6 +147,12 @@ IncidentReportArgs::setAll(bool all)
}
void
+IncidentReportArgs::setDest(int dest)
+{
+ mDest = dest;
+}
+
+void
IncidentReportArgs::addSection(int section)
{
if (!mAll) {
diff --git a/libs/services/include/android/os/DropBoxManager.h b/libs/services/include/android/os/DropBoxManager.h
index 8717178bb7d6..2ed203d9f865 100644
--- a/libs/services/include/android/os/DropBoxManager.h
+++ b/libs/services/include/android/os/DropBoxManager.h
@@ -57,7 +57,7 @@ public:
// and a handle will be passed to the system process, so no additional permissions
// are required from the system process. Returns NULL if the file can't be opened.
Status addFile(const String16& tag, const string& filename, int flags);
-
+
class Entry : public virtual RefBase, public Parcelable {
public:
Entry();
@@ -65,7 +65,12 @@ public:
virtual status_t writeToParcel(Parcel* out) const;
virtual status_t readFromParcel(const Parcel* in);
-
+
+ const vector<uint8_t>& getData() const;
+ const unique_fd& getFd() const;
+ int32_t getFlags() const;
+ int64_t getTimestamp() const;
+
private:
Entry(const String16& tag, int32_t flags);
Entry(const String16& tag, int32_t flags, int fd);
@@ -80,6 +85,9 @@ public:
friend class DropBoxManager;
};
+ // Get the next entry from the drop box after the specified time.
+ Status getNextEntry(const String16& tag, long msec, Entry* entry);
+
private:
enum {
HAS_BYTE_ARRAY = 8
diff --git a/libs/services/src/os/DropBoxManager.cpp b/libs/services/src/os/DropBoxManager.cpp
index bbb45f022a87..1c760e850e4f 100644
--- a/libs/services/src/os/DropBoxManager.cpp
+++ b/libs/services/src/os/DropBoxManager.cpp
@@ -143,6 +143,29 @@ DropBoxManager::Entry::readFromParcel(const Parcel* in)
return NO_ERROR;
}
+const vector<uint8_t>&
+DropBoxManager::Entry::getData() const
+{
+ return mData;
+}
+
+const unique_fd&
+DropBoxManager::Entry::getFd() const
+{
+ return mFd;
+}
+
+int32_t
+DropBoxManager::Entry::getFlags() const
+{
+ return mFlags;
+}
+
+int64_t
+DropBoxManager::Entry::getTimestamp() const
+{
+ return mTimeMillis;
+}
DropBoxManager::DropBoxManager()
{
@@ -195,5 +218,16 @@ DropBoxManager::add(const Entry& entry)
return service->add(entry);
}
+Status
+DropBoxManager::getNextEntry(const String16& tag, long msec, Entry* entry)
+{
+ sp<IDropBoxManagerService> service = interface_cast<IDropBoxManagerService>(
+ defaultServiceManager()->getService(android::String16("dropbox")));
+ if (service == NULL) {
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER, "can't find dropbox service");
+ }
+ return service->getNextEntry(tag, msec, entry);
+}
+
}} // namespace android::os
diff --git a/libs/usb/Android.bp b/libs/usb/Android.bp
new file mode 100644
index 000000000000..b8f29043e597
--- /dev/null
+++ b/libs/usb/Android.bp
@@ -0,0 +1 @@
+subdirs = ["tests/*"]
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
new file mode 100644
index 000000000000..4af6274b7ece
--- /dev/null
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -0,0 +1 @@
+subdirs = ["accessorychat"]
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.bp b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
new file mode 100644
index 000000000000..5613745e966b
--- /dev/null
+++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
@@ -0,0 +1,30 @@
+cc_binary {
+ name: "accessorychat",
+ host_supported: true,
+
+ srcs: ["accessorychat.c"],
+ cflags: [
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+
+ target: {
+ android: {
+ shared_libs: [
+ "libusbhost",
+ "libcutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libusbhost",
+ "libcutils",
+ ],
+
+ cflags: ["-O0"],
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
deleted file mode 100644
index 51f2111f1e0b..000000000000
--- a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Build for Linux (desktop) host
-ifeq ($(HOST_OS),linux)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := accessorychat.c
-
-LOCAL_MODULE := accessorychat
-
-LOCAL_STATIC_LIBRARIES := libusbhost libcutils
-LOCAL_LDLIBS += -lpthread
-LOCAL_CFLAGS := -g -O0
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif
-
-# Build for device
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := accessorychat.c
-
-LOCAL_MODULE := accessorychat
-
-LOCAL_SHARED_LIBRARIES := libusbhost libcutils
-
-include $(BUILD_EXECUTABLE)
diff --git a/libs/usb/tests/accessorytest/Android.bp b/libs/usb/tests/accessorytest/Android.bp
new file mode 100644
index 000000000000..c6340e32e60c
--- /dev/null
+++ b/libs/usb/tests/accessorytest/Android.bp
@@ -0,0 +1,28 @@
+cc_binary_host {
+ name: "accessorytest",
+
+ srcs: [
+ "accessory.c",
+ "audio.c",
+ "hid.c",
+ "usb.c",
+ ],
+
+ static_libs: [
+ "libusbhost",
+ "libcutils",
+ "libtinyalsa",
+ ],
+ cflags: [
+ "-O0",
+ "-Wno-unused-parameter",
+ "-Werror",
+ ],
+
+ target: {
+ darwin: {
+ // Build for Linux host only
+ enabled: false,
+ },
+ },
+}
diff --git a/libs/usb/tests/accessorytest/Android.mk b/libs/usb/tests/accessorytest/Android.mk
deleted file mode 100644
index 6d9a9460c675..000000000000
--- a/libs/usb/tests/accessorytest/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Build for Linux host only
-ifeq ($(HOST_OS),linux)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := accessory.c \
- audio.c \
- hid.c \
- usb.c
-
-LOCAL_C_INCLUDES += external/tinyalsa/include
-
-LOCAL_MODULE := accessorytest
-
-LOCAL_STATIC_LIBRARIES := libusbhost libcutils libtinyalsa
-LOCAL_LDLIBS += -lpthread
-LOCAL_CFLAGS := -g -O0
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif
diff --git a/libs/usb/tests/accessorytest/accessory.h b/libs/usb/tests/accessorytest/accessory.h
index 55c4550f79e0..e86986eb403f 100644
--- a/libs/usb/tests/accessorytest/accessory.h
+++ b/libs/usb/tests/accessorytest/accessory.h
@@ -19,7 +19,7 @@
int init_audio(unsigned int ic, unsigned int id, unsigned int oc, unsigned int od);
void init_hid();
-void usb_run(int enable_accessory);
+void usb_run(uintptr_t enable_accessory);
struct usb_device* usb_wait_for_device();
diff --git a/libs/usb/tests/accessorytest/hid.c b/libs/usb/tests/accessorytest/hid.c
index b70d678543ca..283755dbf215 100644
--- a/libs/usb/tests/accessorytest/hid.c
+++ b/libs/usb/tests/accessorytest/hid.c
@@ -139,7 +139,7 @@ static void open_hid(const char* name)
fprintf(stderr, "opened /dev/%s\n", name);
pthread_t th;
- pthread_create(&th, NULL, hid_thread, (void *)fd);
+ pthread_create(&th, NULL, hid_thread, (void *)(uintptr_t)fd);
}
static void* inotify_thread(void* arg)
diff --git a/libs/usb/tests/accessorytest/usb.c b/libs/usb/tests/accessorytest/usb.c
index ac72b35b908e..1a161adf8ac2 100644
--- a/libs/usb/tests/accessorytest/usb.c
+++ b/libs/usb/tests/accessorytest/usb.c
@@ -219,7 +219,7 @@ struct usb_device* usb_wait_for_device() {
return device;
}
-void usb_run(int enable_accessory) {
+void usb_run(uintptr_t enable_accessory) {
struct usb_host_context* context = usb_host_init();
usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)enable_accessory);