diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/gui/Android.mk | 7 | ||||
| -rw-r--r-- | libs/gui/DisplayEventReceiver.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
| -rw-r--r-- | libs/hwui/Caches.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/Caches.h | 8 | ||||
| -rw-r--r-- | libs/hwui/Debug.h | 3 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 13 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.h | 10 | ||||
| -rw-r--r-- | libs/hwui/Extensions.h | 3 | ||||
| -rw-r--r-- | libs/hwui/FontRenderer.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 72 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 5 | ||||
| -rw-r--r-- | libs/hwui/Properties.h | 5 | ||||
| -rw-r--r-- | libs/hwui/Snapshot.cpp | 154 | ||||
| -rw-r--r-- | libs/hwui/Snapshot.h | 138 | ||||
| -rw-r--r-- | libs/rs/driver/rsdGL.cpp | 4 | ||||
| -rw-r--r-- | libs/rs/driver/rsdGL.h | 4 | ||||
| -rw-r--r-- | libs/rs/driver/rsdShader.cpp | 4 | ||||
| -rw-r--r-- | libs/rs/rs.spec | 4 | ||||
| -rw-r--r-- | libs/rs/rsAllocation.cpp | 43 | ||||
| -rw-r--r-- | libs/rs/rsAllocation.h | 14 | ||||
| -rw-r--r-- | libs/rs/rsScriptC.cpp | 3 | ||||
| -rw-r--r-- | libs/rs/rsThreadIO.cpp | 9 | ||||
| -rw-r--r-- | libs/utils/Android.mk | 8 | ||||
| -rw-r--r-- | libs/utils/ResourceTypes.cpp | 1145 | ||||
| -rw-r--r-- | libs/utils/Threads.cpp | 38 |
26 files changed, 1293 insertions, 424 deletions
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index b8be67d..b6f5b9e 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -34,6 +34,13 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE:= libgui +ifeq ($(TARGET_BOARD_PLATFORM), omap4) + LOCAL_CFLAGS += -DUSE_FENCE_SYNC +endif +ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) + LOCAL_CFLAGS += -DUSE_FENCE_SYNC +endif + ifeq ($(TARGET_BOARD_PLATFORM), tegra) LOCAL_CFLAGS += -DALLOW_DEQUEUE_CURRENT_BUFFER endif diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index 3b3ccaa..6a4763d 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -80,7 +80,13 @@ status_t DisplayEventReceiver::requestNextVsync() { ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, size_t count) { - ssize_t size = mDataChannel->read(events, sizeof(events[0])*count); + return DisplayEventReceiver::getEvents(mDataChannel, events, count); +} + +ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel, + Event* events, size_t count) +{ + ssize_t size = dataChannel->read(events, sizeof(events[0])*count); ALOGE_IF(size<0, "DisplayEventReceiver::getEvents error (%s)", strerror(-size)); diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 95e0a18..5ec3983 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -26,6 +26,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) ShapeCache.cpp \ SkiaColorFilter.cpp \ SkiaShader.cpp \ + Snapshot.cpp \ TextureCache.cpp \ TextDropShadowCache.cpp diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index d1af1a3..0ef8469 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -55,6 +55,16 @@ Caches::Caches(): Singleton<Caches>(), mInitialized(false) { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + if (extensions.hasDebugMarker()) { + eventMark = glInsertEventMarkerEXT; + startMark = glPushGroupMarkerEXT; + endMark = glPopGroupMarkerEXT; + } else { + eventMark = eventMarkNull; + startMark = startMarkNull; + endMark = endMarkNull; + } + init(); mDebugLevel = readDebugLevel(); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 409584f..f8c7bcc 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -240,7 +240,15 @@ public: GammaFontRenderer fontRenderer; ResourceCache resourceCache; + PFNGLINSERTEVENTMARKEREXTPROC eventMark; + PFNGLPUSHGROUPMARKEREXTPROC startMark; + PFNGLPOPGROUPMARKEREXTPROC endMark; + private: + static void eventMarkNull(GLsizei length, const GLchar *marker) { } + static void startMarkNull(GLsizei length, const GLchar *marker) { } + static void endMarkNull() { } + GLuint mCurrentBuffer; GLuint mCurrentIndicesBuffer; void* mCurrentPositionPointer; diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h index 0ad0c2a..16a3d73 100644 --- a/libs/hwui/Debug.h +++ b/libs/hwui/Debug.h @@ -62,6 +62,9 @@ // Turn on to display debug info about the layer renderer #define DEBUG_LAYER_RENDERER 0 +// Turn on to enable additional debugging in the font renderers +#define DEBUG_FONT_RENDERER 0 + // Turn on to dump display list state #define DEBUG_DISPLAY_LIST 0 diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index ee935e4..1a11fbc 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -19,9 +19,10 @@ #include "DisplayListLogBuffer.h" #include "DisplayListRenderer.h" -#include <utils/String8.h> #include "Caches.h" +#include <utils/String8.h> + namespace android { namespace uirenderer { @@ -217,7 +218,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { indent[i] = ' '; } indent[count] = '\0'; - ALOGD("%sStart display list (%p)", (char*) indent + 2, this); + ALOGD("%sStart display list (%p, %s)", (char*) indent + 2, this, mName.string()); int saveCount = renderer.getSaveCount() - 1; @@ -562,9 +563,11 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) indent[i] = ' '; } indent[count] = '\0'; - DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this); + DISPLAY_LIST_LOGD("%sStart display list (%p, %s)", (char*) indent + 2, this, mName.string()); #endif + renderer.startMark(mName.string()); + DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); int saveCount = renderer.getSaveCount() - 1; while (!mReader.eof()) { @@ -575,7 +578,9 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) case DrawGLFunction: { Functor *functor = (Functor *) getInt(); DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor); + renderer.startMark("GL functor"); needsInvalidate |= renderer.callDrawGLFunction(functor, dirty); + renderer.endMark(); } break; case Save: { @@ -934,6 +939,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) } } + renderer.endMark(); + DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate); return needsInvalidate; } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 6fe4205..46506e4 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -28,6 +28,8 @@ #include <cutils/compiler.h> +#include <utils/String8.h> + #include "DisplayListLogBuffer.h" #include "OpenGLRenderer.h" #include "utils/Functor.h" @@ -128,6 +130,12 @@ public: return mIsRenderable; } + void setName(const char* name) { + if (name) { + mName.setTo(name); + } + } + private: void init(); @@ -224,6 +232,8 @@ private: size_t mSize; bool mIsRenderable; + + String8 mName; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index 1069e3f..f11fecc 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -67,6 +67,7 @@ public: mHasNPot = hasExtension("GL_OES_texture_npot"); mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch"); mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer"); + mHasDebugMarker = hasExtension("GL_EXT_debug_marker"); const char* vendor = (const char*) glGetString(GL_VENDOR); EXT_LOGD("Vendor: %s", vendor); @@ -82,6 +83,7 @@ public: inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; } inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; } inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; } + inline bool hasDebugMarker() const { return mHasDebugMarker; } bool hasExtension(const char* extension) const { const String8 s(extension); @@ -101,6 +103,7 @@ private: bool mNeedsHighpTexCoords; bool mHasFramebufferFetch; bool mHasDiscardFramebuffer; + bool mHasDebugMarker; }; // class Extensions }; // namespace uirenderer diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 74efda2..3df105b 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -151,10 +151,12 @@ void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, int32_t bX = 0, bY = 0; for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) { for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) { +#if DEBUG_FONT_RENDERER if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { ALOGE("Skipping invalid index"); continue; } +#endif uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; bitmap[bY * bitmapW + bX] = tempCol; } @@ -226,7 +228,7 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len }; RenderGlyph render = gRenderGlyph[mode]; - if (positions == NULL) { + if (CC_LIKELY(positions == NULL)) { SkFixed prevRsbDelta = 0; float penX = x; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index cc0e05e..afae70f 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -124,9 +124,25 @@ OpenGLRenderer::~OpenGLRenderer() { } /////////////////////////////////////////////////////////////////////////////// +// Debug +/////////////////////////////////////////////////////////////////////////////// + +void OpenGLRenderer::startMark(const char* name) const { + mCaches.startMark(0, name); +} + +void OpenGLRenderer::endMark() const { + mCaches.endMark(); +} + +/////////////////////////////////////////////////////////////////////////////// // Setup /////////////////////////////////////////////////////////////////////////////// +uint32_t OpenGLRenderer::getStencilSize() { + return STENCIL_BUFFER_SIZE; +} + void OpenGLRenderer::setViewport(int width, int height) { mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); @@ -738,7 +754,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { // TODO: See LayerRenderer.cpp::generateMesh() for important // information about this implementation - if (!layer->region.isEmpty()) { + if (CC_LIKELY(!layer->region.isEmpty())) { size_t count; const android::Rect* rects = layer->region.getArray(&count); @@ -1382,7 +1398,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint if (!texture) return; const AutoTexture autoCleanup(texture); - if (bitmap->getConfig() == SkBitmap::kA8_Config) { + if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) { drawAlphaBitmap(texture, left, top, paint); } else { drawTextureRect(left, top, right, bottom, texture, paint); @@ -1438,9 +1454,9 @@ void OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHei float bottom = FLT_MIN; #if RENDER_LAYERS_AS_REGIONS - bool hasActiveLayer = hasLayer(); + const bool hasActiveLayer = hasLayer(); #else - bool hasActiveLayer = false; + const bool hasActiveLayer = false; #endif // TODO: Support the colors array @@ -1525,7 +1541,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, texture->setWrap(GL_CLAMP_TO_EDGE, true); - if (mSnapshot->transform->isPureTranslate()) { + if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) { const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f); @@ -1571,7 +1587,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int const Patch* mesh = mCaches.patchCache.get(bitmap->width(), bitmap->height(), right - left, bottom - top, xDivs, yDivs, colors, width, height, numColors); - if (mesh && mesh->verticesCount > 0) { + if (CC_LIKELY(mesh && mesh->verticesCount > 0)) { const bool pureTranslate = mSnapshot->transform->isPureTranslate(); #if RENDER_LAYERS_AS_REGIONS // Mark the current layer dirty where we are going to draw the patch @@ -1581,7 +1597,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int const size_t count = mesh->quads.size(); for (size_t i = 0; i < count; i++) { const Rect& bounds = mesh->quads.itemAt(i); - if (pureTranslate) { + if (CC_LIKELY(pureTranslate)) { const float x = (int) floorf(bounds.left + offsetX + 0.5f); const float y = (int) floorf(bounds.top + offsetY + 0.5f); dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight()); @@ -1593,7 +1609,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int } #endif - if (pureTranslate) { + if (CC_LIKELY(pureTranslate)) { const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); @@ -1621,7 +1637,7 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom float inverseScaleX = 1.0f; float inverseScaleY = 1.0f; // The quad that we use needs to account for scaling. - if (!mSnapshot->transform->isPureTranslate()) { + if (CC_UNLIKELY(!mSnapshot->transform->isPureTranslate())) { Matrix4 *mat = mSnapshot->transform; float m00 = mat->data[Matrix4::kScaleX]; float m01 = mat->data[Matrix4::kSkewY]; @@ -1727,7 +1743,7 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { // The quad that we use for AA and hairlines needs to account for scaling. For hairlines // the line on the screen should always be one pixel wide regardless of scale. For // AA lines, we only want one pixel of translucent boundary around the quad. - if (!mSnapshot->transform->isPureTranslate()) { + if (CC_UNLIKELY(!mSnapshot->transform->isPureTranslate())) { Matrix4 *mat = mSnapshot->transform; float m00 = mat->data[Matrix4::kScaleX]; float m01 = mat->data[Matrix4::kSkewY]; @@ -1735,8 +1751,8 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { float m10 = mat->data[Matrix4::kSkewX]; float m11 = mat->data[Matrix4::kScaleX]; float m12 = mat->data[6]; - float scaleX = sqrt(m00*m00 + m01*m01); - float scaleY = sqrt(m10*m10 + m11*m11); + float scaleX = sqrtf(m00 * m00 + m01 * m01); + float scaleY = sqrtf(m10 * m10 + m11 * m11); inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0; inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0; if (inverseScaleX != 1.0f || inverseScaleY != 1.0f) { @@ -1754,11 +1770,7 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { setupDrawColor(paint->getColor(), alpha); setupDrawColorFilter(); setupDrawShader(); - if (isAA) { - setupDrawBlending(true, mode); - } else { - setupDrawBlending(mode); - } + setupDrawBlending(isAA, mode); setupDrawProgram(); setupDrawModelViewIdentity(true); setupDrawColorUniforms(); @@ -1776,7 +1788,7 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { Vertex* vertices = &lines[0]; AAVertex wLines[verticesCount]; AAVertex* aaVertices = &wLines[0]; - if (!isAA) { + if (CC_UNLIKELY(!isAA)) { setupDrawVertices(vertices); } else { void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset; @@ -2136,9 +2148,9 @@ void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); #if RENDER_LAYERS_AS_REGIONS - bool hasActiveLayer = hasLayer(); + const bool hasActiveLayer = hasLayer(); #else - bool hasActiveLayer = false; + const bool hasActiveLayer = false; #endif if (fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y, @@ -2185,7 +2197,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const float oldX = x; const float oldY = y; const bool pureTranslate = mSnapshot->transform->isPureTranslate(); - if (pureTranslate) { + if (CC_LIKELY(pureTranslate)) { x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f); y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); } @@ -2202,7 +2214,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - if (mHasShadow) { + if (CC_UNLIKELY(mHasShadow)) { mCaches.activeTexture(0); mCaches.dropShadowCache.setFontRenderer(fontRenderer); @@ -2261,9 +2273,9 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); #if RENDER_LAYERS_AS_REGIONS - bool hasActiveLayer = hasLayer(); + const bool hasActiveLayer = hasLayer(); #else - bool hasActiveLayer = false; + const bool hasActiveLayer = false; #endif if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y, @@ -2310,7 +2322,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { layer->setAlpha(alpha, mode); #if RENDER_LAYERS_AS_REGIONS - if (!layer->region.isEmpty()) { + if (CC_LIKELY(!layer->region.isEmpty())) { if (layer->region.isRect()) { composeLayerRect(layer, layer->regionRect); } else if (layer->mesh) { @@ -2326,7 +2338,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); setupDrawTexture(layer->getTexture()); - if (mSnapshot->transform->isPureTranslate()) { + if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) { x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f); y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); @@ -2486,7 +2498,7 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float break; } - if (underlineWidth > 0.0f) { + if (CC_LIKELY(underlineWidth > 0.0f)) { const float textSize = paintCopy.getTextSize(); const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f); @@ -2555,7 +2567,7 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b texture->setWrap(GL_CLAMP_TO_EDGE, true); - if (mSnapshot->transform->isPureTranslate()) { + if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) { const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); @@ -2615,8 +2627,8 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, // the blending, turn blending off here // If the blend mode cannot be implemented using shaders, fall // back to the default SrcOver blend mode instead - if (mode > SkXfermode::kScreen_Mode) { - if (mCaches.extensions.hasFramebufferFetch()) { + if CC_UNLIKELY((mode > SkXfermode::kScreen_Mode)) { + if (CC_UNLIKELY(mCaches.extensions.hasFramebufferFetch())) { description.framebufferMode = mode; description.swapSrcDst = swapSrcDst; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index ae355bb..3c2d09e 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -141,6 +141,11 @@ public: SkPaint* filterPaint(SkPaint* paint); + ANDROID_API static uint32_t getStencilSize(); + + void startMark(const char* name) const; + void endMark() const; + protected: /** * Compose the layer defined in the current snapshot with the layer diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 2eae0f1..7854729 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -37,6 +37,11 @@ // Textures used by layers must have dimensions multiples of this number #define LAYER_SIZE 64 +// Defines the size in bits of the stencil buffer +// Note: Only 1 bit is required for clipping but more bits are required +// to properly implement the winding fill rule when rasterizing paths +#define STENCIL_BUFFER_SIZE 0 + /** * Debug level for app developers. */ diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp new file mode 100644 index 0000000..a85362d --- /dev/null +++ b/libs/hwui/Snapshot.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2012 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 "Snapshot.h" + +#include <SkCanvas.h> + +namespace android { +namespace uirenderer { + +/////////////////////////////////////////////////////////////////////////////// +// Constructors +/////////////////////////////////////////////////////////////////////////////// + +Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), + invisible(false), empty(false) { + + transform = &mTransformRoot; + clipRect = &mClipRectRoot; + region = NULL; +} + +/** + * Copies the specified snapshot/ The specified snapshot is stored as + * the previous snapshot. + */ +Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags): + flags(0), previous(s), layer(NULL), fbo(s->fbo), + invisible(s->invisible), empty(false), + viewport(s->viewport), height(s->height) { + + if (saveFlags & SkCanvas::kMatrix_SaveFlag) { + mTransformRoot.load(*s->transform); + transform = &mTransformRoot; + } else { + transform = s->transform; + } + + if (saveFlags & SkCanvas::kClip_SaveFlag) { + mClipRectRoot.set(*s->clipRect); + clipRect = &mClipRectRoot; + } else { + clipRect = s->clipRect; + } + + if (s->flags & Snapshot::kFlagFboTarget) { + flags |= Snapshot::kFlagFboTarget; + region = s->region; + } else { + region = NULL; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Clipping +/////////////////////////////////////////////////////////////////////////////// + +bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) { + Rect r(left, top, right, bottom); + transform->mapRect(r); + return clipTransformed(r, op); +} + +bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) { + bool clipped = false; + + // NOTE: The unimplemented operations require support for regions + // Supporting regions would require using a stencil buffer instead + // of the scissor. The stencil buffer itself is not too expensive + // (memory cost excluded) but on fillrate limited devices, managing + // the stencil might have a negative impact on the framerate. + switch (op) { + case SkRegion::kDifference_Op: + break; + case SkRegion::kIntersect_Op: + clipped = clipRect->intersect(r); + if (!clipped) { + clipRect->setEmpty(); + clipped = true; + } + break; + case SkRegion::kUnion_Op: + clipped = clipRect->unionWith(r); + break; + case SkRegion::kXOR_Op: + break; + case SkRegion::kReverseDifference_Op: + break; + case SkRegion::kReplace_Op: + clipRect->set(r); + clipped = true; + break; + } + + if (clipped) { + flags |= Snapshot::kFlagClipSet; + } + + return clipped; +} + +void Snapshot::setClip(float left, float top, float right, float bottom) { + clipRect->set(left, top, right, bottom); + flags |= Snapshot::kFlagClipSet; +} + +const Rect& Snapshot::getLocalClip() { + mat4 inverse; + inverse.loadInverse(*transform); + + mLocalClip.set(*clipRect); + inverse.mapRect(mLocalClip); + + return mLocalClip; +} + +void Snapshot::resetClip(float left, float top, float right, float bottom) { + clipRect = &mClipRectRoot; + clipRect->set(left, top, right, bottom); + flags |= Snapshot::kFlagClipSet; +} + +/////////////////////////////////////////////////////////////////////////////// +// Transforms +/////////////////////////////////////////////////////////////////////////////// + +void Snapshot::resetTransform(float x, float y, float z) { + transform = &mTransformRoot; + transform->loadTranslate(x, y, z); +} + +/////////////////////////////////////////////////////////////////////////////// +// Queries +/////////////////////////////////////////////////////////////////////////////// + +bool Snapshot::isIgnored() const { + return invisible || empty; +} + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index aff7b93..c94af7e 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -23,7 +23,7 @@ #include <utils/RefBase.h> #include <ui/Region.h> -#include <SkCanvas.h> +#include <SkRegion.h> #include "Layer.h" #include "Matrix.h" @@ -43,43 +43,12 @@ namespace uirenderer { */ class Snapshot: public LightRefBase<Snapshot> { public: - Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false), empty(false) { - transform = &mTransformRoot; - clipRect = &mClipRectRoot; - region = NULL; - } - /** - * Copies the specified snapshot/ The specified snapshot is stored as - * the previous snapshot. - */ - Snapshot(const sp<Snapshot>& s, int saveFlags): - flags(0), previous(s), layer(NULL), fbo(s->fbo), - invisible(s->invisible), empty(false), viewport(s->viewport), height(s->height) { - if (saveFlags & SkCanvas::kMatrix_SaveFlag) { - mTransformRoot.load(*s->transform); - transform = &mTransformRoot; - } else { - transform = s->transform; - } - - if (saveFlags & SkCanvas::kClip_SaveFlag) { - mClipRectRoot.set(*s->clipRect); - clipRect = &mClipRectRoot; - } else { - clipRect = s->clipRect; - } - - if (s->flags & Snapshot::kFlagFboTarget) { - flags |= Snapshot::kFlagFboTarget; - region = s->region; - } else { - region = NULL; - } - } + Snapshot(); + Snapshot(const sp<Snapshot>& s, int saveFlags); /** - * Various flags set on #flags. + * Various flags set on ::flags. */ enum Flags { /** @@ -115,87 +84,41 @@ public: * by this snapshot's trasnformation. */ bool clip(float left, float top, float right, float bottom, - SkRegion::Op op = SkRegion::kIntersect_Op) { - Rect r(left, top, right, bottom); - transform->mapRect(r); - return clipTransformed(r, op); - } + SkRegion::Op op = SkRegion::kIntersect_Op); /** * Modifies the current clip with the new clip rectangle and * the specified operation. The specified rectangle is considered * already transformed. */ - bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) { - bool clipped = false; - - // NOTE: The unimplemented operations require support for regions - // Supporting regions would require using a stencil buffer instead - // of the scissor. The stencil buffer itself is not too expensive - // (memory cost excluded) but on fillrate limited devices, managing - // the stencil might have a negative impact on the framerate. - switch (op) { - case SkRegion::kDifference_Op: - break; - case SkRegion::kIntersect_Op: - clipped = clipRect->intersect(r); - if (!clipped) { - clipRect->setEmpty(); - clipped = true; - } - break; - case SkRegion::kUnion_Op: - clipped = clipRect->unionWith(r); - break; - case SkRegion::kXOR_Op: - break; - case SkRegion::kReverseDifference_Op: - break; - case SkRegion::kReplace_Op: - clipRect->set(r); - clipped = true; - break; - } - - if (clipped) { - flags |= Snapshot::kFlagClipSet; - } - - return clipped; - } + bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op); /** * Sets the current clip. */ - void setClip(float left, float top, float right, float bottom) { - clipRect->set(left, top, right, bottom); - flags |= Snapshot::kFlagClipSet; - } - - const Rect& getLocalClip() { - mat4 inverse; - inverse.loadInverse(*transform); + void setClip(float left, float top, float right, float bottom); - mLocalClip.set(*clipRect); - inverse.mapRect(mLocalClip); - - return mLocalClip; - } + /** + * Returns the current clip in local coordinates. The clip rect is + * transformed by the inverse transform matrix. + */ + const Rect& getLocalClip(); - void resetTransform(float x, float y, float z) { - transform = &mTransformRoot; - transform->loadTranslate(x, y, z); - } + /** + * Resets the clip to the specified rect. + */ + void resetClip(float left, float top, float right, float bottom); - void resetClip(float left, float top, float right, float bottom) { - clipRect = &mClipRectRoot; - clipRect->set(left, top, right, bottom); - flags |= Snapshot::kFlagClipSet; - } + /** + * Resets the current transform to a pure 3D translation. + */ + void resetTransform(float x, float y, float z); - bool isIgnored() const { - return invisible || empty; - } + /** + * Indicates whether this snapshot should be ignored. A snapshot + * is typicalled ignored if its layer is invisible or empty. + */ + bool isIgnored() const; /** * Dirty flags. @@ -209,6 +132,8 @@ public: /** * Only set when the flag kFlagIsLayer is set. + * + * This snapshot does not own the layer, this pointer must not be freed. */ Layer* layer; @@ -249,17 +174,26 @@ public: /** * Local transformation. Holds the current translation, scale and * rotation values. + * + * This is a reference to a matrix owned by this snapshot or another + * snapshot. This pointer must not be freed. See ::mTransformRoot. */ mat4* transform; /** * Current clip region. The clip is stored in canvas-space coordinates, * (screen-space coordinates in the regular case.) + * + * This is a reference to a rect owned by this snapshot or another + * snapshot. This pointer must not be freed. See ::mClipRectRoot. */ Rect* clipRect; /** * The ancestor layer's dirty region. + * + * This is a reference to a region owned by a layer. This pointer must + * not be freed. */ Region* region; diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp index b53a68c..7acc054 100644 --- a/libs/rs/driver/rsdGL.cpp +++ b/libs/rs/driver/rsdGL.cpp @@ -340,9 +340,9 @@ bool rsdGLInit(const Context *rsc) { dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, "GL_OES_texture_npot"); - dc->gl.gl.GL_IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, + dc->gl.gl.IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions, "GL_IMG_texture_npot"); - dc->gl.gl.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, + dc->gl.gl.NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions, "GL_NV_texture_npot_2D_mipmap"); dc->gl.gl.EXT_texture_max_aniso = 1.0f; bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions, diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h index fc33885..51893c3 100644 --- a/libs/rs/driver/rsdGL.h +++ b/libs/rs/driver/rsdGL.h @@ -61,8 +61,8 @@ typedef struct RsdGLRec { int32_t maxVertexTextureUnits; bool OES_texture_npot; - bool GL_IMG_texture_npot; - bool GL_NV_texture_npot_2D_mipmap; + bool IMG_texture_npot; + bool NV_texture_npot_2D_mipmap; float EXT_texture_max_aniso; } gl; diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp index a10deb4..c70193a 100644 --- a/libs/rs/driver/rsdShader.cpp +++ b/libs/rs/driver/rsdShader.cpp @@ -349,8 +349,8 @@ void RsdShader::setupSampler(const Context *rsc, const Sampler *s, const Allocat if (!dc->gl.gl.OES_texture_npot && tex->getType()->getIsNp2()) { if (tex->getHasGraphicsMipmaps() && - (dc->gl.gl.GL_NV_texture_npot_2D_mipmap || dc->gl.gl.GL_IMG_texture_npot)) { - if (dc->gl.gl.GL_NV_texture_npot_2D_mipmap) { + (dc->gl.gl.NV_texture_npot_2D_mipmap || dc->gl.gl.IMG_texture_npot)) { + if (dc->gl.gl.NV_texture_npot_2D_mipmap) { RSD_CALL_GL(glTexParameteri, target, GL_TEXTURE_MIN_FILTER, trans[s->mHal.state.minFilter]); } else { diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 20b1f52..6887b22 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -162,7 +162,7 @@ Allocation1DElementData { param uint32_t x param uint32_t lod param const void *data - param uint32_t comp_offset + param size_t comp_offset } Allocation2DData { @@ -183,7 +183,7 @@ Allocation2DElementData { param uint32_t lod param RsAllocationCubemapFace face param const void *data - param uint32_t element_offset + param size_t element_offset } AllocationGenerateMipmaps { diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index 2773d5c..fd85b07 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2009-2012 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. @@ -71,11 +71,11 @@ void Allocation::read(void *data) { } void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod, - uint32_t count, const void *data, uint32_t sizeBytes) { - const uint32_t eSize = mHal.state.type->getElementSizeBytes(); + uint32_t count, const void *data, size_t sizeBytes) { + const size_t eSize = mHal.state.type->getElementSizeBytes(); if ((count * eSize) != sizeBytes) { - ALOGE("Allocation::subData called with mismatched size expected %i, got %i", + ALOGE("Allocation::subData called with mismatched size expected %zu, got %zu", (count * eSize), sizeBytes); mHal.state.type->dumpLOGV("type info"); return; @@ -86,14 +86,14 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod, } void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, - uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) { - const uint32_t eSize = mHal.state.elementSizeBytes; - const uint32_t lineSize = eSize * w; + uint32_t w, uint32_t h, const void *data, size_t sizeBytes) { + const size_t eSize = mHal.state.elementSizeBytes; + const size_t lineSize = eSize * w; //ALOGE("data2d %p, %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes); if ((lineSize * h) != sizeBytes) { - ALOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes); + ALOGE("Allocation size mismatch, expected %zu, got %zu", (lineSize * h), sizeBytes); rsAssert(!"Allocation::subData called with mismatched size"); return; } @@ -104,12 +104,12 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face, - uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { + uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes) { } void Allocation::elementData(Context *rsc, uint32_t x, const void *data, - uint32_t cIdx, uint32_t sizeBytes) { - uint32_t eSize = mHal.state.elementSizeBytes; + uint32_t cIdx, size_t sizeBytes) { + size_t eSize = mHal.state.elementSizeBytes; if (cIdx >= mHal.state.type->getElement()->getFieldCount()) { ALOGE("Error Allocation::subElementData component %i out of range.", cIdx); @@ -124,8 +124,9 @@ void Allocation::elementData(Context *rsc, uint32_t x, const void *data, } const Element * e = mHal.state.type->getElement()->getField(cIdx); - if (sizeBytes != e->getSizeBytes()) { - ALOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes()); + uint32_t elemArraySize = mHal.state.type->getElement()->getFieldArraySize(cIdx); + if (sizeBytes != e->getSizeBytes() * elemArraySize) { + ALOGE("Error Allocation::subElementData data size %zu does not match field size %zu.", sizeBytes, e->getSizeBytes()); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size."); return; } @@ -135,8 +136,8 @@ void Allocation::elementData(Context *rsc, uint32_t x, const void *data, } void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y, - const void *data, uint32_t cIdx, uint32_t sizeBytes) { - uint32_t eSize = mHal.state.elementSizeBytes; + const void *data, uint32_t cIdx, size_t sizeBytes) { + size_t eSize = mHal.state.elementSizeBytes; if (x >= mHal.state.dimensionX) { ALOGE("Error Allocation::subElementData X offset %i out of range.", x); @@ -157,9 +158,9 @@ void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y, } const Element * e = mHal.state.type->getElement()->getField(cIdx); - - if (sizeBytes != e->getSizeBytes()) { - ALOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes()); + uint32_t elemArraySize = mHal.state.type->getElement()->getFieldArraySize(cIdx); + if (sizeBytes != e->getSizeBytes() * elemArraySize) { + ALOGE("Error Allocation::subElementData data size %zu does not match field size %zu.", sizeBytes, e->getSizeBytes()); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size."); return; } @@ -249,7 +250,7 @@ void Allocation::writePackedData(const Type *type, delete[] sizeUnpadded; } -void Allocation::unpackVec3Allocation(const void *data, uint32_t dataSize) { +void Allocation::unpackVec3Allocation(const void *data, size_t dataSize) { const uint8_t *src = (const uint8_t*)data; uint8_t *dst = (uint8_t*)getPtr(); @@ -519,13 +520,13 @@ void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t } void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face, - const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped + const void *data, size_t sizeBytes, size_t eoff) { Allocation *a = static_cast<Allocation *>(va); a->elementData(rsc, x, y, data, eoff, sizeBytes); } void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod, - const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped + const void *data, size_t sizeBytes, size_t eoff) { Allocation *a = static_cast<Allocation *>(va); a->elementData(rsc, x, data, eoff, sizeBytes); } diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h index 4ce863a..20201ca 100644 --- a/libs/rs/rsAllocation.h +++ b/libs/rs/rsAllocation.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2009-2012 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. @@ -80,16 +80,16 @@ public: void resize1D(Context *rsc, uint32_t dimX); void resize2D(Context *rsc, uint32_t dimX, uint32_t dimY); - void data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, uint32_t sizeBytes); + void data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, size_t sizeBytes); void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, - uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes); + uint32_t w, uint32_t h, const void *data, size_t sizeBytes); void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face, - uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes); + uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes); void elementData(Context *rsc, uint32_t x, - const void *data, uint32_t elementOff, uint32_t sizeBytes); + const void *data, uint32_t elementOff, size_t sizeBytes); void elementData(Context *rsc, uint32_t x, uint32_t y, - const void *data, uint32_t elementOff, uint32_t sizeBytes); + const void *data, uint32_t elementOff, size_t sizeBytes); void read(void *data); @@ -138,7 +138,7 @@ private: uint32_t getPackedSize() const; static void writePackedData(const Type *type, uint8_t *dst, const uint8_t *src, bool dstPadded); - void unpackVec3Allocation(const void *data, uint32_t dataSize); + void unpackVec3Allocation(const void *data, size_t dataSize); void packVec3Allocation(OStream *stream) const; }; diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index afc8ba0..b4eb995 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -206,7 +206,6 @@ bool ScriptC::runCompiler(Context *rsc, return false; } - rsAssert(bcWrapper.getHeaderVersion() == 0); if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) { sdkVersion = bcWrapper.getTargetAPI(); } @@ -323,7 +322,7 @@ RsScript rsi_ScriptCCreate(Context *rsc, if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) { // Error during compile, destroy s and return null. - delete s; + ObjectBase::checkDelete(s); return NULL; } diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp index 8ba1a0e..1917774 100644 --- a/libs/rs/rsThreadIO.cpp +++ b/libs/rs/rsThreadIO.cpp @@ -124,7 +124,6 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t time while (!mToCore.isEmpty() || waitForCommand) { uint32_t cmdID = 0; uint32_t cmdSize = 0; - ret = true; if (con->props.mLogTimes) { con->timerSet(Context::RS_TIMER_IDLE); } @@ -136,11 +135,17 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t time delay = 0; } } + + if (delay == 0 && timeToWait != 0 && mToCore.isEmpty()) { + break; + } + const void * data = mToCore.get(&cmdID, &cmdSize, delay); if (!cmdSize) { // exception or timeout occurred. - return false; + break; } + ret = true; if (con->props.mLogTimes) { con->timerSet(Context::RS_TIMER_INTERNAL); } diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index 544ab74..24cf504 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -98,7 +98,8 @@ endif LOCAL_C_INCLUDES += \ external/zlib \ - external/icu4c/common + external/icu4c/common \ + bionic/libc/private LOCAL_LDLIBS += -lpthread @@ -114,7 +115,10 @@ include $(BUILD_SHARED_LIBRARY) ifeq ($(TARGET_OS),linux) include $(CLEAR_VARS) -LOCAL_C_INCLUDES += external/zlib external/icu4c/common +LOCAL_C_INCLUDES += \ + external/zlib \ + external/icu4c/common \ + bionic/libc/private LOCAL_LDLIBS := -lrt -ldl -lpthread LOCAL_MODULE := libutils LOCAL_SRC_FILES := $(commonSources) BackupData.cpp BackupHelpers.cpp diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 15b83bb..3fa562e 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -221,7 +221,7 @@ static void deserializeInternal(const void* inData, Res_png_9patch* outData) { static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes) { if (sizeBytes < ResTable::IDMAP_HEADER_SIZE_BYTES) { - ALOGW("idmap assertion failed: size=%d bytes\n", sizeBytes); + ALOGW("idmap assertion failed: size=%d bytes\n", (int)sizeBytes); return false; } if (*map != htodl(IDMAP_MAGIC)) { // htodl: map data expected to be in correct endianess @@ -250,7 +250,7 @@ static status_t idmapLookup(const uint32_t* map, size_t sizeBytes, uint32_t key, return UNKNOWN_ERROR; } if (typeCount > size) { - ALOGW("Resource ID map: number of types=%d exceeds size of map=%d\n", typeCount, size); + ALOGW("Resource ID map: number of types=%d exceeds size of map=%d\n", typeCount, (int)size); return UNKNOWN_ERROR; } const uint32_t typeOffset = map[type]; @@ -260,7 +260,7 @@ static status_t idmapLookup(const uint32_t* map, size_t sizeBytes, uint32_t key, } if (typeOffset + 1 > size) { ALOGW("Resource ID map: type offset=%d exceeds reasonable value, size of map=%d\n", - typeOffset, size); + typeOffset, (int)size); return UNKNOWN_ERROR; } const uint32_t entryCount = map[typeOffset]; @@ -271,7 +271,7 @@ static status_t idmapLookup(const uint32_t* map, size_t sizeBytes, uint32_t key, } const uint32_t index = typeOffset + 2 + entry - entryOffset; if (index > size) { - ALOGW("Resource ID map: entry index=%d exceeds size of map=%d\n", index, size); + ALOGW("Resource ID map: entry index=%d exceeds size of map=%d\n", index, (int)size); *outValue = 0; return NO_ERROR; } @@ -659,6 +659,16 @@ const char* ResStringPool::string8At(size_t idx, size_t* outLen) const return NULL; } +const String8 ResStringPool::string8ObjectAt(size_t idx) const +{ + size_t len; + const char *str = (const char*)string8At(idx, &len); + if (str != NULL) { + return String8(str); + } + return String8(stringAt(idx, &len)); +} + const ResStringPool_span* ResStringPool::styleAt(const ResStringPool_ref& ref) const { return styleAt(ref.index); @@ -738,12 +748,25 @@ size_t ResStringPool::size() const return (mError == NO_ERROR) ? mHeader->stringCount : 0; } -#ifndef HAVE_ANDROID_OS +size_t ResStringPool::styleCount() const +{ + return (mError == NO_ERROR) ? mHeader->styleCount : 0; +} + +size_t ResStringPool::bytes() const +{ + return (mError == NO_ERROR) ? mHeader->header.size : 0; +} + +bool ResStringPool::isSorted() const +{ + return (mHeader->flags&ResStringPool_header::SORTED_FLAG)!=0; +} + bool ResStringPool::isUTF8() const { return (mHeader->flags&ResStringPool_header::UTF8_FLAG)!=0; } -#endif // -------------------------------------------------------------------- // -------------------------------------------------------------------- @@ -1367,6 +1390,873 @@ status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const // -------------------------------------------------------------------- // -------------------------------------------------------------------- +void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) { + const size_t size = dtohl(o.size); + if (size >= sizeof(ResTable_config)) { + *this = o; + } else { + memcpy(this, &o, size); + memset(((uint8_t*)this)+size, 0, sizeof(ResTable_config)-size); + } +} + +void ResTable_config::copyFromDtoH(const ResTable_config& o) { + copyFromDeviceNoSwap(o); + size = sizeof(ResTable_config); + mcc = dtohs(mcc); + mnc = dtohs(mnc); + density = dtohs(density); + screenWidth = dtohs(screenWidth); + screenHeight = dtohs(screenHeight); + sdkVersion = dtohs(sdkVersion); + minorVersion = dtohs(minorVersion); + smallestScreenWidthDp = dtohs(smallestScreenWidthDp); + screenWidthDp = dtohs(screenWidthDp); + screenHeightDp = dtohs(screenHeightDp); +} + +void ResTable_config::swapHtoD() { + size = htodl(size); + mcc = htods(mcc); + mnc = htods(mnc); + density = htods(density); + screenWidth = htods(screenWidth); + screenHeight = htods(screenHeight); + sdkVersion = htods(sdkVersion); + minorVersion = htods(minorVersion); + smallestScreenWidthDp = htods(smallestScreenWidthDp); + screenWidthDp = htods(screenWidthDp); + screenHeightDp = htods(screenHeightDp); +} + +int ResTable_config::compare(const ResTable_config& o) const { + int32_t diff = (int32_t)(imsi - o.imsi); + if (diff != 0) return diff; + diff = (int32_t)(locale - o.locale); + if (diff != 0) return diff; + diff = (int32_t)(screenType - o.screenType); + if (diff != 0) return diff; + diff = (int32_t)(input - o.input); + if (diff != 0) return diff; + diff = (int32_t)(screenSize - o.screenSize); + if (diff != 0) return diff; + diff = (int32_t)(version - o.version); + if (diff != 0) return diff; + diff = (int32_t)(screenLayout - o.screenLayout); + if (diff != 0) return diff; + diff = (int32_t)(uiMode - o.uiMode); + if (diff != 0) return diff; + diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp); + if (diff != 0) return diff; + diff = (int32_t)(screenSizeDp - o.screenSizeDp); + return (int)diff; +} + +int ResTable_config::compareLogical(const ResTable_config& o) const { + if (mcc != o.mcc) { + return mcc < o.mcc ? -1 : 1; + } + if (mnc != o.mnc) { + return mnc < o.mnc ? -1 : 1; + } + if (language[0] != o.language[0]) { + return language[0] < o.language[0] ? -1 : 1; + } + if (language[1] != o.language[1]) { + return language[1] < o.language[1] ? -1 : 1; + } + if (country[0] != o.country[0]) { + return country[0] < o.country[0] ? -1 : 1; + } + if (country[1] != o.country[1]) { + return country[1] < o.country[1] ? -1 : 1; + } + if (smallestScreenWidthDp != o.smallestScreenWidthDp) { + return smallestScreenWidthDp < o.smallestScreenWidthDp ? -1 : 1; + } + if (screenWidthDp != o.screenWidthDp) { + return screenWidthDp < o.screenWidthDp ? -1 : 1; + } + if (screenHeightDp != o.screenHeightDp) { + return screenHeightDp < o.screenHeightDp ? -1 : 1; + } + if (screenWidth != o.screenWidth) { + return screenWidth < o.screenWidth ? -1 : 1; + } + if (screenHeight != o.screenHeight) { + return screenHeight < o.screenHeight ? -1 : 1; + } + if (density != o.density) { + return density < o.density ? -1 : 1; + } + if (orientation != o.orientation) { + return orientation < o.orientation ? -1 : 1; + } + if (touchscreen != o.touchscreen) { + return touchscreen < o.touchscreen ? -1 : 1; + } + if (input != o.input) { + return input < o.input ? -1 : 1; + } + if (screenLayout != o.screenLayout) { + return screenLayout < o.screenLayout ? -1 : 1; + } + if (uiMode != o.uiMode) { + return uiMode < o.uiMode ? -1 : 1; + } + if (version != o.version) { + return version < o.version ? -1 : 1; + } + return 0; +} + +int ResTable_config::diff(const ResTable_config& o) const { + int diffs = 0; + if (mcc != o.mcc) diffs |= CONFIG_MCC; + if (mnc != o.mnc) diffs |= CONFIG_MNC; + if (locale != o.locale) diffs |= CONFIG_LOCALE; + if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION; + if (density != o.density) diffs |= CONFIG_DENSITY; + if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN; + if (((inputFlags^o.inputFlags)&(MASK_KEYSHIDDEN|MASK_NAVHIDDEN)) != 0) + diffs |= CONFIG_KEYBOARD_HIDDEN; + if (keyboard != o.keyboard) diffs |= CONFIG_KEYBOARD; + if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION; + if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE; + if (version != o.version) diffs |= CONFIG_VERSION; + if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT; + if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE; + if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE; + if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE; + return diffs; +} + +bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const { + // The order of the following tests defines the importance of one + // configuration parameter over another. Those tests first are more + // important, trumping any values in those following them. + if (imsi || o.imsi) { + if (mcc != o.mcc) { + if (!mcc) return false; + if (!o.mcc) return true; + } + + if (mnc != o.mnc) { + if (!mnc) return false; + if (!o.mnc) return true; + } + } + + if (locale || o.locale) { + if (language[0] != o.language[0]) { + if (!language[0]) return false; + if (!o.language[0]) return true; + } + + if (country[0] != o.country[0]) { + if (!country[0]) return false; + if (!o.country[0]) return true; + } + } + + if (smallestScreenWidthDp || o.smallestScreenWidthDp) { + if (smallestScreenWidthDp != o.smallestScreenWidthDp) { + if (!smallestScreenWidthDp) return false; + if (!o.smallestScreenWidthDp) return true; + } + } + + if (screenSizeDp || o.screenSizeDp) { + if (screenWidthDp != o.screenWidthDp) { + if (!screenWidthDp) return false; + if (!o.screenWidthDp) return true; + } + + if (screenHeightDp != o.screenHeightDp) { + if (!screenHeightDp) return false; + if (!o.screenHeightDp) return true; + } + } + + if (screenLayout || o.screenLayout) { + if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0) { + if (!(screenLayout & MASK_SCREENSIZE)) return false; + if (!(o.screenLayout & MASK_SCREENSIZE)) return true; + } + if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0) { + if (!(screenLayout & MASK_SCREENLONG)) return false; + if (!(o.screenLayout & MASK_SCREENLONG)) return true; + } + } + + if (orientation != o.orientation) { + if (!orientation) return false; + if (!o.orientation) return true; + } + + if (uiMode || o.uiMode) { + if (((uiMode^o.uiMode) & MASK_UI_MODE_TYPE) != 0) { + if (!(uiMode & MASK_UI_MODE_TYPE)) return false; + if (!(o.uiMode & MASK_UI_MODE_TYPE)) return true; + } + if (((uiMode^o.uiMode) & MASK_UI_MODE_NIGHT) != 0) { + if (!(uiMode & MASK_UI_MODE_NIGHT)) return false; + if (!(o.uiMode & MASK_UI_MODE_NIGHT)) return true; + } + } + + // density is never 'more specific' + // as the default just equals 160 + + if (touchscreen != o.touchscreen) { + if (!touchscreen) return false; + if (!o.touchscreen) return true; + } + + if (input || o.input) { + if (((inputFlags^o.inputFlags) & MASK_KEYSHIDDEN) != 0) { + if (!(inputFlags & MASK_KEYSHIDDEN)) return false; + if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true; + } + + if (((inputFlags^o.inputFlags) & MASK_NAVHIDDEN) != 0) { + if (!(inputFlags & MASK_NAVHIDDEN)) return false; + if (!(o.inputFlags & MASK_NAVHIDDEN)) return true; + } + + if (keyboard != o.keyboard) { + if (!keyboard) return false; + if (!o.keyboard) return true; + } + + if (navigation != o.navigation) { + if (!navigation) return false; + if (!o.navigation) return true; + } + } + + if (screenSize || o.screenSize) { + if (screenWidth != o.screenWidth) { + if (!screenWidth) return false; + if (!o.screenWidth) return true; + } + + if (screenHeight != o.screenHeight) { + if (!screenHeight) return false; + if (!o.screenHeight) return true; + } + } + + if (version || o.version) { + if (sdkVersion != o.sdkVersion) { + if (!sdkVersion) return false; + if (!o.sdkVersion) return true; + } + + if (minorVersion != o.minorVersion) { + if (!minorVersion) return false; + if (!o.minorVersion) return true; + } + } + return false; +} + +bool ResTable_config::isBetterThan(const ResTable_config& o, + const ResTable_config* requested) const { + if (requested) { + if (imsi || o.imsi) { + if ((mcc != o.mcc) && requested->mcc) { + return (mcc); + } + + if ((mnc != o.mnc) && requested->mnc) { + return (mnc); + } + } + + if (locale || o.locale) { + if ((language[0] != o.language[0]) && requested->language[0]) { + return (language[0]); + } + + if ((country[0] != o.country[0]) && requested->country[0]) { + return (country[0]); + } + } + + if (smallestScreenWidthDp || o.smallestScreenWidthDp) { + // The configuration closest to the actual size is best. + // We assume that larger configs have already been filtered + // out at this point. That means we just want the largest one. + return smallestScreenWidthDp >= o.smallestScreenWidthDp; + } + + if (screenSizeDp || o.screenSizeDp) { + // "Better" is based on the sum of the difference between both + // width and height from the requested dimensions. We are + // assuming the invalid configs (with smaller dimens) have + // already been filtered. Note that if a particular dimension + // is unspecified, we will end up with a large value (the + // difference between 0 and the requested dimension), which is + // good since we will prefer a config that has specified a + // dimension value. + int myDelta = 0, otherDelta = 0; + if (requested->screenWidthDp) { + myDelta += requested->screenWidthDp - screenWidthDp; + otherDelta += requested->screenWidthDp - o.screenWidthDp; + } + if (requested->screenHeightDp) { + myDelta += requested->screenHeightDp - screenHeightDp; + otherDelta += requested->screenHeightDp - o.screenHeightDp; + } + //ALOGI("Comparing this %dx%d to other %dx%d in %dx%d: myDelta=%d otherDelta=%d", + // screenWidthDp, screenHeightDp, o.screenWidthDp, o.screenHeightDp, + // requested->screenWidthDp, requested->screenHeightDp, myDelta, otherDelta); + return (myDelta <= otherDelta); + } + + if (screenLayout || o.screenLayout) { + if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0 + && (requested->screenLayout & MASK_SCREENSIZE)) { + // A little backwards compatibility here: undefined is + // considered equivalent to normal. But only if the + // requested size is at least normal; otherwise, small + // is better than the default. + int mySL = (screenLayout & MASK_SCREENSIZE); + int oSL = (o.screenLayout & MASK_SCREENSIZE); + int fixedMySL = mySL; + int fixedOSL = oSL; + if ((requested->screenLayout & MASK_SCREENSIZE) >= SCREENSIZE_NORMAL) { + if (fixedMySL == 0) fixedMySL = SCREENSIZE_NORMAL; + if (fixedOSL == 0) fixedOSL = SCREENSIZE_NORMAL; + } + // For screen size, the best match is the one that is + // closest to the requested screen size, but not over + // (the not over part is dealt with in match() below). + if (fixedMySL == fixedOSL) { + // If the two are the same, but 'this' is actually + // undefined, then the other is really a better match. + if (mySL == 0) return false; + return true; + } + return fixedMySL >= fixedOSL; + } + if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0 + && (requested->screenLayout & MASK_SCREENLONG)) { + return (screenLayout & MASK_SCREENLONG); + } + } + + if ((orientation != o.orientation) && requested->orientation) { + return (orientation); + } + + if (uiMode || o.uiMode) { + if (((uiMode^o.uiMode) & MASK_UI_MODE_TYPE) != 0 + && (requested->uiMode & MASK_UI_MODE_TYPE)) { + return (uiMode & MASK_UI_MODE_TYPE); + } + if (((uiMode^o.uiMode) & MASK_UI_MODE_NIGHT) != 0 + && (requested->uiMode & MASK_UI_MODE_NIGHT)) { + return (uiMode & MASK_UI_MODE_NIGHT); + } + } + + if (screenType || o.screenType) { + if (density != o.density) { + // density is tough. Any density is potentially useful + // because the system will scale it. Scaling down + // is generally better than scaling up. + // Default density counts as 160dpi (the system default) + // TODO - remove 160 constants + int h = (density?density:160); + int l = (o.density?o.density:160); + bool bImBigger = true; + if (l > h) { + int t = h; + h = l; + l = t; + bImBigger = false; + } + + int reqValue = (requested->density?requested->density:160); + if (reqValue >= h) { + // requested value higher than both l and h, give h + return bImBigger; + } + if (l >= reqValue) { + // requested value lower than both l and h, give l + return !bImBigger; + } + // saying that scaling down is 2x better than up + if (((2 * l) - reqValue) * h > reqValue * reqValue) { + return !bImBigger; + } else { + return bImBigger; + } + } + + if ((touchscreen != o.touchscreen) && requested->touchscreen) { + return (touchscreen); + } + } + + if (input || o.input) { + const int keysHidden = inputFlags & MASK_KEYSHIDDEN; + const int oKeysHidden = o.inputFlags & MASK_KEYSHIDDEN; + if (keysHidden != oKeysHidden) { + const int reqKeysHidden = + requested->inputFlags & MASK_KEYSHIDDEN; + if (reqKeysHidden) { + + if (!keysHidden) return false; + if (!oKeysHidden) return true; + // For compatibility, we count KEYSHIDDEN_NO as being + // the same as KEYSHIDDEN_SOFT. Here we disambiguate + // these by making an exact match more specific. + if (reqKeysHidden == keysHidden) return true; + if (reqKeysHidden == oKeysHidden) return false; + } + } + + const int navHidden = inputFlags & MASK_NAVHIDDEN; + const int oNavHidden = o.inputFlags & MASK_NAVHIDDEN; + if (navHidden != oNavHidden) { + const int reqNavHidden = + requested->inputFlags & MASK_NAVHIDDEN; + if (reqNavHidden) { + + if (!navHidden) return false; + if (!oNavHidden) return true; + } + } + + if ((keyboard != o.keyboard) && requested->keyboard) { + return (keyboard); + } + + if ((navigation != o.navigation) && requested->navigation) { + return (navigation); + } + } + + if (screenSize || o.screenSize) { + // "Better" is based on the sum of the difference between both + // width and height from the requested dimensions. We are + // assuming the invalid configs (with smaller sizes) have + // already been filtered. Note that if a particular dimension + // is unspecified, we will end up with a large value (the + // difference between 0 and the requested dimension), which is + // good since we will prefer a config that has specified a + // size value. + int myDelta = 0, otherDelta = 0; + if (requested->screenWidth) { + myDelta += requested->screenWidth - screenWidth; + otherDelta += requested->screenWidth - o.screenWidth; + } + if (requested->screenHeight) { + myDelta += requested->screenHeight - screenHeight; + otherDelta += requested->screenHeight - o.screenHeight; + } + return (myDelta <= otherDelta); + } + + if (version || o.version) { + if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) { + return (sdkVersion > o.sdkVersion); + } + + if ((minorVersion != o.minorVersion) && + requested->minorVersion) { + return (minorVersion); + } + } + + return false; + } + return isMoreSpecificThan(o); +} + +bool ResTable_config::match(const ResTable_config& settings) const { + if (imsi != 0) { + if (mcc != 0 && mcc != settings.mcc) { + return false; + } + if (mnc != 0 && mnc != settings.mnc) { + return false; + } + } + if (locale != 0) { + if (language[0] != 0 + && (language[0] != settings.language[0] + || language[1] != settings.language[1])) { + return false; + } + if (country[0] != 0 + && (country[0] != settings.country[0] + || country[1] != settings.country[1])) { + return false; + } + } + if (screenConfig != 0) { + const int screenSize = screenLayout&MASK_SCREENSIZE; + const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE; + // Any screen sizes for larger screens than the setting do not + // match. + if (screenSize != 0 && screenSize > setScreenSize) { + return false; + } + + const int screenLong = screenLayout&MASK_SCREENLONG; + const int setScreenLong = settings.screenLayout&MASK_SCREENLONG; + if (screenLong != 0 && screenLong != setScreenLong) { + return false; + } + + const int uiModeType = uiMode&MASK_UI_MODE_TYPE; + const int setUiModeType = settings.uiMode&MASK_UI_MODE_TYPE; + if (uiModeType != 0 && uiModeType != setUiModeType) { + return false; + } + + const int uiModeNight = uiMode&MASK_UI_MODE_NIGHT; + const int setUiModeNight = settings.uiMode&MASK_UI_MODE_NIGHT; + if (uiModeNight != 0 && uiModeNight != setUiModeNight) { + return false; + } + + if (smallestScreenWidthDp != 0 + && smallestScreenWidthDp > settings.smallestScreenWidthDp) { + return false; + } + } + if (screenSizeDp != 0) { + if (screenWidthDp != 0 && screenWidthDp > settings.screenWidthDp) { + //ALOGI("Filtering out width %d in requested %d", screenWidthDp, settings.screenWidthDp); + return false; + } + if (screenHeightDp != 0 && screenHeightDp > settings.screenHeightDp) { + //ALOGI("Filtering out height %d in requested %d", screenHeightDp, settings.screenHeightDp); + return false; + } + } + if (screenType != 0) { + if (orientation != 0 && orientation != settings.orientation) { + return false; + } + // density always matches - we can scale it. See isBetterThan + if (touchscreen != 0 && touchscreen != settings.touchscreen) { + return false; + } + } + if (input != 0) { + const int keysHidden = inputFlags&MASK_KEYSHIDDEN; + const int setKeysHidden = settings.inputFlags&MASK_KEYSHIDDEN; + if (keysHidden != 0 && keysHidden != setKeysHidden) { + // For compatibility, we count a request for KEYSHIDDEN_NO as also + // matching the more recent KEYSHIDDEN_SOFT. Basically + // KEYSHIDDEN_NO means there is some kind of keyboard available. + //ALOGI("Matching keysHidden: have=%d, config=%d\n", keysHidden, setKeysHidden); + if (keysHidden != KEYSHIDDEN_NO || setKeysHidden != KEYSHIDDEN_SOFT) { + //ALOGI("No match!"); + return false; + } + } + const int navHidden = inputFlags&MASK_NAVHIDDEN; + const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN; + if (navHidden != 0 && navHidden != setNavHidden) { + return false; + } + if (keyboard != 0 && keyboard != settings.keyboard) { + return false; + } + if (navigation != 0 && navigation != settings.navigation) { + return false; + } + } + if (screenSize != 0) { + if (screenWidth != 0 && screenWidth > settings.screenWidth) { + return false; + } + if (screenHeight != 0 && screenHeight > settings.screenHeight) { + return false; + } + } + if (version != 0) { + if (sdkVersion != 0 && sdkVersion > settings.sdkVersion) { + return false; + } + if (minorVersion != 0 && minorVersion != settings.minorVersion) { + return false; + } + } + return true; +} + +void ResTable_config::getLocale(char str[6]) const { + memset(str, 0, 6); + if (language[0]) { + str[0] = language[0]; + str[1] = language[1]; + if (country[0]) { + str[2] = '_'; + str[3] = country[0]; + str[4] = country[1]; + } + } +} + +String8 ResTable_config::toString() const { + String8 res; + + if (mcc != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("%dmcc", dtohs(mcc)); + } + if (mnc != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("%dmnc", dtohs(mnc)); + } + if (language[0] != 0) { + if (res.size() > 0) res.append("-"); + res.append(language, 2); + } + if (country[0] != 0) { + if (res.size() > 0) res.append("-"); + res.append(country, 2); + } + if (smallestScreenWidthDp != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("sw%ddp", dtohs(smallestScreenWidthDp)); + } + if (screenWidthDp != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("w%ddp", dtohs(screenWidthDp)); + } + if (screenHeightDp != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("h%ddp", dtohs(screenHeightDp)); + } + if ((screenLayout&MASK_SCREENSIZE) != SCREENSIZE_ANY) { + if (res.size() > 0) res.append("-"); + switch (screenLayout&ResTable_config::MASK_SCREENSIZE) { + case ResTable_config::SCREENSIZE_SMALL: + res.append("small"); + break; + case ResTable_config::SCREENSIZE_NORMAL: + res.append("normal"); + break; + case ResTable_config::SCREENSIZE_LARGE: + res.append("large"); + break; + case ResTable_config::SCREENSIZE_XLARGE: + res.append("xlarge"); + break; + default: + res.appendFormat("screenLayoutSize=%d", + dtohs(screenLayout&ResTable_config::MASK_SCREENSIZE)); + break; + } + } + if ((screenLayout&MASK_SCREENLONG) != 0) { + if (res.size() > 0) res.append("-"); + switch (screenLayout&ResTable_config::MASK_SCREENLONG) { + case ResTable_config::SCREENLONG_NO: + res.append("notlong"); + break; + case ResTable_config::SCREENLONG_YES: + res.append("long"); + break; + default: + res.appendFormat("screenLayoutLong=%d", + dtohs(screenLayout&ResTable_config::MASK_SCREENLONG)); + break; + } + } + if (orientation != ORIENTATION_ANY) { + if (res.size() > 0) res.append("-"); + switch (orientation) { + case ResTable_config::ORIENTATION_PORT: + res.append("port"); + break; + case ResTable_config::ORIENTATION_LAND: + res.append("land"); + break; + case ResTable_config::ORIENTATION_SQUARE: + res.append("square"); + break; + default: + res.appendFormat("orientation=%d", dtohs(orientation)); + break; + } + } + if ((uiMode&MASK_UI_MODE_TYPE) != UI_MODE_TYPE_ANY) { + if (res.size() > 0) res.append("-"); + switch (uiMode&ResTable_config::MASK_UI_MODE_TYPE) { + case ResTable_config::UI_MODE_TYPE_DESK: + res.append("desk"); + break; + case ResTable_config::UI_MODE_TYPE_CAR: + res.append("car"); + break; + case ResTable_config::UI_MODE_TYPE_TELEVISION: + res.append("television"); + break; + case ResTable_config::UI_MODE_TYPE_APPLIANCE: + res.append("appliance"); + break; + default: + res.appendFormat("uiModeType=%d", + dtohs(screenLayout&ResTable_config::MASK_UI_MODE_TYPE)); + break; + } + } + if ((uiMode&MASK_UI_MODE_NIGHT) != 0) { + if (res.size() > 0) res.append("-"); + switch (uiMode&ResTable_config::MASK_UI_MODE_NIGHT) { + case ResTable_config::UI_MODE_NIGHT_NO: + res.append("notnight"); + break; + case ResTable_config::UI_MODE_NIGHT_YES: + res.append("night"); + break; + default: + res.appendFormat("uiModeNight=%d", + dtohs(uiMode&MASK_UI_MODE_NIGHT)); + break; + } + } + if (density != DENSITY_DEFAULT) { + if (res.size() > 0) res.append("-"); + switch (density) { + case ResTable_config::DENSITY_LOW: + res.append("ldpi"); + break; + case ResTable_config::DENSITY_MEDIUM: + res.append("mdpi"); + break; + case ResTable_config::DENSITY_TV: + res.append("tvdpi"); + break; + case ResTable_config::DENSITY_HIGH: + res.append("hdpi"); + break; + case ResTable_config::DENSITY_XHIGH: + res.append("xhdpi"); + break; + case ResTable_config::DENSITY_XXHIGH: + res.append("xxhdpi"); + break; + case ResTable_config::DENSITY_NONE: + res.append("nodpi"); + break; + default: + res.appendFormat("density=%d", dtohs(density)); + break; + } + } + if (touchscreen != TOUCHSCREEN_ANY) { + if (res.size() > 0) res.append("-"); + switch (touchscreen) { + case ResTable_config::TOUCHSCREEN_NOTOUCH: + res.append("notouch"); + break; + case ResTable_config::TOUCHSCREEN_FINGER: + res.append("finger"); + break; + case ResTable_config::TOUCHSCREEN_STYLUS: + res.append("stylus"); + break; + default: + res.appendFormat("touchscreen=%d", dtohs(touchscreen)); + break; + } + } + if (keyboard != KEYBOARD_ANY) { + if (res.size() > 0) res.append("-"); + switch (keyboard) { + case ResTable_config::KEYBOARD_NOKEYS: + res.append("nokeys"); + break; + case ResTable_config::KEYBOARD_QWERTY: + res.append("qwerty"); + break; + case ResTable_config::KEYBOARD_12KEY: + res.append("12key"); + break; + default: + res.appendFormat("keyboard=%d", dtohs(keyboard)); + break; + } + } + if ((inputFlags&MASK_KEYSHIDDEN) != 0) { + if (res.size() > 0) res.append("-"); + switch (inputFlags&MASK_KEYSHIDDEN) { + case ResTable_config::KEYSHIDDEN_NO: + res.append("keysexposed"); + break; + case ResTable_config::KEYSHIDDEN_YES: + res.append("keyshidden"); + break; + case ResTable_config::KEYSHIDDEN_SOFT: + res.append("keyssoft"); + break; + } + } + if (navigation != NAVIGATION_ANY) { + if (res.size() > 0) res.append("-"); + switch (navigation) { + case ResTable_config::NAVIGATION_NONAV: + res.append("nonav"); + break; + case ResTable_config::NAVIGATION_DPAD: + res.append("dpad"); + break; + case ResTable_config::NAVIGATION_TRACKBALL: + res.append("trackball"); + break; + case ResTable_config::NAVIGATION_WHEEL: + res.append("wheel"); + break; + default: + res.appendFormat("navigation=%d", dtohs(navigation)); + break; + } + } + if ((inputFlags&MASK_NAVHIDDEN) != 0) { + if (res.size() > 0) res.append("-"); + switch (inputFlags&MASK_NAVHIDDEN) { + case ResTable_config::NAVHIDDEN_NO: + res.append("navsexposed"); + break; + case ResTable_config::NAVHIDDEN_YES: + res.append("navhidden"); + break; + default: + res.appendFormat("inputFlagsNavHidden=%d", + dtohs(inputFlags&MASK_NAVHIDDEN)); + break; + } + } + if (screenSize != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("%dx%d", dtohs(screenWidth), dtohs(screenHeight)); + } + if (version != 0) { + if (res.size() > 0) res.append("-"); + res.appendFormat("v%d", dtohs(sdkVersion)); + if (minorVersion != 0) { + res.appendFormat(".%d", dtohs(minorVersion)); + } + } + + return res; +} + +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- +// -------------------------------------------------------------------- + struct ResTable::Header { Header(ResTable* _owner) : owner(_owner), ownedData(NULL), header(NULL), @@ -3953,43 +4843,9 @@ ssize_t ResTable::getEntry( ResTable_config thisConfig; thisConfig.copyFromDtoH(thisType->config); - TABLE_GETENTRY(LOGI("Match entry 0x%x in type 0x%x (sz 0x%x): imsi:%d/%d=%d/%d " - "lang:%c%c=%c%c cnt:%c%c=%c%c orien:%d=%d touch:%d=%d " - "density:%d=%d key:%d=%d inp:%d=%d nav:%d=%d w:%d=%d h:%d=%d " - "swdp:%d=%d wdp:%d=%d hdp:%d=%d\n", + TABLE_GETENTRY(LOGI("Match entry 0x%x in type 0x%x (sz 0x%x): %s\n", entryIndex, typeIndex+1, dtohl(thisType->config.size), - thisConfig.mcc, thisConfig.mnc, - config ? config->mcc : 0, config ? config->mnc : 0, - thisConfig.language[0] ? thisConfig.language[0] : '-', - thisConfig.language[1] ? thisConfig.language[1] : '-', - config && config->language[0] ? config->language[0] : '-', - config && config->language[1] ? config->language[1] : '-', - thisConfig.country[0] ? thisConfig.country[0] : '-', - thisConfig.country[1] ? thisConfig.country[1] : '-', - config && config->country[0] ? config->country[0] : '-', - config && config->country[1] ? config->country[1] : '-', - thisConfig.orientation, - config ? config->orientation : 0, - thisConfig.touchscreen, - config ? config->touchscreen : 0, - thisConfig.density, - config ? config->density : 0, - thisConfig.keyboard, - config ? config->keyboard : 0, - thisConfig.inputFlags, - config ? config->inputFlags : 0, - thisConfig.navigation, - config ? config->navigation : 0, - thisConfig.screenWidth, - config ? config->screenWidth : 0, - thisConfig.screenHeight, - config ? config->screenHeight : 0, - thisConfig.smallestScreenWidthDp, - config ? config->smallestScreenWidthDp : 0, - thisConfig.screenWidthDp, - config ? config->screenWidthDp : 0, - thisConfig.screenHeightDp, - config ? config->screenHeightDp : 0)); + thisConfig.toString().string())); // Check to make sure this one is valid for the current parameters. if (config && !thisConfig.match(*config)) { @@ -4273,26 +5129,8 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, TABLE_GETENTRY( ResTable_config thisConfig; thisConfig.copyFromDtoH(type->config); - ALOGI("Adding config to type %d: imsi:%d/%d lang:%c%c cnt:%c%c " - "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d " - "swdp:%d wdp:%d hdp:%d\n", - type->id, - thisConfig.mcc, thisConfig.mnc, - thisConfig.language[0] ? thisConfig.language[0] : '-', - thisConfig.language[1] ? thisConfig.language[1] : '-', - thisConfig.country[0] ? thisConfig.country[0] : '-', - thisConfig.country[1] ? thisConfig.country[1] : '-', - thisConfig.orientation, - thisConfig.touchscreen, - thisConfig.density, - thisConfig.keyboard, - thisConfig.inputFlags, - thisConfig.navigation, - thisConfig.screenWidth, - thisConfig.screenHeight, - thisConfig.smallestScreenWidthDp, - thisConfig.screenWidthDp, - thisConfig.screenHeightDp)); + ALOGI("Adding config to type %d: %s\n", + type->id, thisConfig.toString().string())); t->configs.add(type); } else { status_t err = validate_chunk(chunk, sizeof(ResChunk_header), @@ -4622,186 +5460,9 @@ void ResTable::print(bool inclValues) const printf(" NON-INTEGER ResTable_type ADDRESS: %p\n", type); continue; } - char density[16]; - uint16_t dval = dtohs(type->config.density); - if (dval == ResTable_config::DENSITY_DEFAULT) { - strcpy(density, "def"); - } else if (dval == ResTable_config::DENSITY_NONE) { - strcpy(density, "no"); - } else { - sprintf(density, "%d", (int)dval); - } - printf(" config %d", (int)configIndex); - if (type->config.mcc != 0) { - printf(" mcc=%d", dtohs(type->config.mcc)); - } - if (type->config.mnc != 0) { - printf(" mnc=%d", dtohs(type->config.mnc)); - } - if (type->config.locale != 0) { - printf(" lang=%c%c cnt=%c%c", - type->config.language[0] ? type->config.language[0] : '-', - type->config.language[1] ? type->config.language[1] : '-', - type->config.country[0] ? type->config.country[0] : '-', - type->config.country[1] ? type->config.country[1] : '-'); - } - if (type->config.screenLayout != 0) { - printf(" sz=%d", - type->config.screenLayout&ResTable_config::MASK_SCREENSIZE); - switch (type->config.screenLayout&ResTable_config::MASK_SCREENSIZE) { - case ResTable_config::SCREENSIZE_SMALL: - printf(" (small)"); - break; - case ResTable_config::SCREENSIZE_NORMAL: - printf(" (normal)"); - break; - case ResTable_config::SCREENSIZE_LARGE: - printf(" (large)"); - break; - case ResTable_config::SCREENSIZE_XLARGE: - printf(" (xlarge)"); - break; - } - printf(" lng=%d", - type->config.screenLayout&ResTable_config::MASK_SCREENLONG); - switch (type->config.screenLayout&ResTable_config::MASK_SCREENLONG) { - case ResTable_config::SCREENLONG_NO: - printf(" (notlong)"); - break; - case ResTable_config::SCREENLONG_YES: - printf(" (long)"); - break; - } - } - if (type->config.orientation != 0) { - printf(" orient=%d", type->config.orientation); - switch (type->config.orientation) { - case ResTable_config::ORIENTATION_PORT: - printf(" (port)"); - break; - case ResTable_config::ORIENTATION_LAND: - printf(" (land)"); - break; - case ResTable_config::ORIENTATION_SQUARE: - printf(" (square)"); - break; - } - } - if (type->config.uiMode != 0) { - printf(" type=%d", - type->config.uiMode&ResTable_config::MASK_UI_MODE_TYPE); - switch (type->config.uiMode&ResTable_config::MASK_UI_MODE_TYPE) { - case ResTable_config::UI_MODE_TYPE_NORMAL: - printf(" (normal)"); - break; - case ResTable_config::UI_MODE_TYPE_CAR: - printf(" (car)"); - break; - } - printf(" night=%d", - type->config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT); - switch (type->config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT) { - case ResTable_config::UI_MODE_NIGHT_NO: - printf(" (no)"); - break; - case ResTable_config::UI_MODE_NIGHT_YES: - printf(" (yes)"); - break; - } - } - if (dval != 0) { - printf(" density=%s", density); - } - if (type->config.touchscreen != 0) { - printf(" touch=%d", type->config.touchscreen); - switch (type->config.touchscreen) { - case ResTable_config::TOUCHSCREEN_NOTOUCH: - printf(" (notouch)"); - break; - case ResTable_config::TOUCHSCREEN_STYLUS: - printf(" (stylus)"); - break; - case ResTable_config::TOUCHSCREEN_FINGER: - printf(" (finger)"); - break; - } - } - if (type->config.inputFlags != 0) { - printf(" keyhid=%d", type->config.inputFlags&ResTable_config::MASK_KEYSHIDDEN); - switch (type->config.inputFlags&ResTable_config::MASK_KEYSHIDDEN) { - case ResTable_config::KEYSHIDDEN_NO: - printf(" (no)"); - break; - case ResTable_config::KEYSHIDDEN_YES: - printf(" (yes)"); - break; - case ResTable_config::KEYSHIDDEN_SOFT: - printf(" (soft)"); - break; - } - printf(" navhid=%d", type->config.inputFlags&ResTable_config::MASK_NAVHIDDEN); - switch (type->config.inputFlags&ResTable_config::MASK_NAVHIDDEN) { - case ResTable_config::NAVHIDDEN_NO: - printf(" (no)"); - break; - case ResTable_config::NAVHIDDEN_YES: - printf(" (yes)"); - break; - } - } - if (type->config.keyboard != 0) { - printf(" kbd=%d", type->config.keyboard); - switch (type->config.keyboard) { - case ResTable_config::KEYBOARD_NOKEYS: - printf(" (nokeys)"); - break; - case ResTable_config::KEYBOARD_QWERTY: - printf(" (qwerty)"); - break; - case ResTable_config::KEYBOARD_12KEY: - printf(" (12key)"); - break; - } - } - if (type->config.navigation != 0) { - printf(" nav=%d", type->config.navigation); - switch (type->config.navigation) { - case ResTable_config::NAVIGATION_NONAV: - printf(" (nonav)"); - break; - case ResTable_config::NAVIGATION_DPAD: - printf(" (dpad)"); - break; - case ResTable_config::NAVIGATION_TRACKBALL: - printf(" (trackball)"); - break; - case ResTable_config::NAVIGATION_WHEEL: - printf(" (wheel)"); - break; - } - } - if (type->config.screenWidth != 0) { - printf(" w=%d", dtohs(type->config.screenWidth)); - } - if (type->config.screenHeight != 0) { - printf(" h=%d", dtohs(type->config.screenHeight)); - } - if (type->config.smallestScreenWidthDp != 0) { - printf(" swdp=%d", dtohs(type->config.smallestScreenWidthDp)); - } - if (type->config.screenWidthDp != 0) { - printf(" wdp=%d", dtohs(type->config.screenWidthDp)); - } - if (type->config.screenHeightDp != 0) { - printf(" hdp=%d", dtohs(type->config.screenHeightDp)); - } - if (type->config.sdkVersion != 0) { - printf(" sdk=%d", dtohs(type->config.sdkVersion)); - } - if (type->config.minorVersion != 0) { - printf(" mver=%d", dtohs(type->config.minorVersion)); - } - printf("\n"); + String8 configStr = type->config.toString(); + printf(" config %s:\n", configStr.size() > 0 + ? configStr.string() : "(default)"); size_t entryCount = dtohl(type->entryCount); uint32_t entriesStart = dtohl(type->entriesStart); if ((entriesStart&0x3) != 0) { diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp index e343c62..ab207f5 100644 --- a/libs/utils/Threads.cpp +++ b/libs/utils/Threads.cpp @@ -34,6 +34,9 @@ # include <pthread.h> # include <sched.h> # include <sys/resource.h> +#ifdef HAVE_ANDROID_OS +# include <bionic_pthread.h> +#endif #elif defined(HAVE_WIN32_THREADS) # include <windows.h> # include <stdint.h> @@ -86,7 +89,7 @@ struct thread_data_t { char * threadName; // we use this trampoline when we need to set the priority with - // nice/setpriority. + // nice/setpriority, and name with prctl. static int trampoline(const thread_data_t* t) { thread_func_t f = t->entryFunction; void* u = t->userData; @@ -141,8 +144,13 @@ int androidCreateRawThreadEtc(android_thread_func_t entryFunction, #ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */ if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) { - // We could avoid the trampoline if there was a way to get to the - // android_thread_id_t (pid) from pthread_t + // Now that the pthread_t has a method to find the associated + // android_thread_id_t (pid) from pthread_t, it would be possible to avoid + // this trampoline in some cases as the parent could set the properties + // for the child. However, there would be a race condition because the + // child becomes ready immediately, and it doesn't work for the name. + // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was + // proposed but not yet accepted. thread_data_t* t = new thread_data_t; t->priority = threadPriority; t->threadName = threadName ? strdup(threadName) : NULL; @@ -178,6 +186,13 @@ int androidCreateRawThreadEtc(android_thread_func_t entryFunction, return 1; } +#ifdef HAVE_ANDROID_OS +static pthread_t android_thread_id_t_to_pthread(android_thread_id_t thread) +{ + return (pthread_t) thread; +} +#endif + android_thread_id_t androidGetThreadId() { return (android_thread_id_t)pthread_self(); @@ -909,6 +924,23 @@ status_t Thread::join() return mStatus; } +#ifdef HAVE_ANDROID_OS +pid_t Thread::getTid() const +{ + // mTid is not defined until the child initializes it, and the caller may need it earlier + Mutex::Autolock _l(mLock); + pid_t tid; + if (mRunning) { + pthread_t pthread = android_thread_id_t_to_pthread(mThread); + tid = __pthread_gettid(pthread); + } else { + ALOGW("Thread (this=%p): getTid() is undefined before run()", this); + tid = -1; + } + return tid; +} +#endif + bool Thread::exitPending() const { Mutex::Autolock _l(mLock); |
