diff options
Diffstat (limited to 'libs')
32 files changed, 686 insertions, 750 deletions
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 629b899..b578a6c 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -371,6 +371,11 @@ int IPCThreadState::getCallingUid() return mCallingUid; } +int IPCThreadState::getOrigCallingUid() +{ + return mOrigCallingUid; +} + int64_t IPCThreadState::clearCallingIdentity() { int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; @@ -641,6 +646,7 @@ IPCThreadState::IPCThreadState() { pthread_setspecific(gTLS, this); clearCaller(); + mOrigCallingUid = mCallingUid; mIn.setDataCapacity(256); mOut.setDataCapacity(256); } @@ -987,6 +993,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; + mOrigCallingUid = tr.sender_euid; int curPrio = getpriority(PRIO_PROCESS, mMyThreadId); if (gDisableBackgroundScheduling) { @@ -1045,6 +1052,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = origPid; mCallingUid = origUid; + mOrigCallingUid = origUid; IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp index 785da39..55f4178 100644 --- a/libs/gui/BitTube.cpp +++ b/libs/gui/BitTube.cpp @@ -17,8 +17,9 @@ #include <stdint.h> #include <sys/types.h> -#include <unistd.h> #include <fcntl.h> +#include <signal.h> +#include <unistd.h> #include <utils/Errors.h> @@ -38,6 +39,8 @@ BitTube::BitTube() mSendFd = fds[1]; fcntl(mReceiveFd, F_SETFL, O_NONBLOCK); fcntl(mSendFd, F_SETFL, O_NONBLOCK); + // ignore SIGPIPE, we handle write errors through EPIPE instead + signal(SIGPIPE, SIG_IGN); } else { mReceiveFd = -errno; ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd)); 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/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/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/Properties.h b/libs/hwui/Properties.h index 71fb8da..7854729 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -38,8 +38,8 @@ #define LAYER_SIZE 64 // Defines the size in bits of the stencil buffer -// Note: We only want 1 bit, but in practice we'll get 8 bits on all GPUs -// for the foreseeable future +// 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 /** diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp new file mode 100644 index 0000000..de2c674 --- /dev/null +++ b/libs/hwui/Snapshot.cpp @@ -0,0 +1,256 @@ +/* + * 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; + clipRegion = 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) { + + clipRegion = NULL; + + 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; +#if STENCIL_BUFFER_SIZE + if (s->clipRegion) { + mClipRegionRoot.merge(*s->clipRegion); + clipRegion = &mClipRegionRoot; + } +#endif + } else { + clipRect = s->clipRect; +#if STENCIL_BUFFER_SIZE + clipRegion = s->clipRegion; +#endif + } + + if (s->flags & Snapshot::kFlagFboTarget) { + flags |= Snapshot::kFlagFboTarget; + region = s->region; + } else { + region = NULL; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Clipping +/////////////////////////////////////////////////////////////////////////////// + +void Snapshot::ensureClipRegion() { +#if STENCIL_BUFFER_SIZE + if (!clipRegion) { + clipRegion = &mClipRegionRoot; + android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); + clipRegion->set(tmp); + } +#endif +} + +void Snapshot::copyClipRectFromRegion() { +#if STENCIL_BUFFER_SIZE + if (!clipRegion->isEmpty()) { + android::Rect bounds(clipRegion->bounds()); + clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom); + + if (clipRegion->isRect()) { + clipRegion->clear(); + clipRegion = NULL; + } + } else { + clipRect->setEmpty(); + clipRegion = NULL; + } +#endif +} + +bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) { +#if STENCIL_BUFFER_SIZE + android::Rect tmp(left, top, right, bottom); + clipRegion->orSelf(tmp); + copyClipRectFromRegion(); + return true; +#else + return false; +#endif +} + +bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) { +#if STENCIL_BUFFER_SIZE + android::Rect tmp(left, top, right, bottom); + clipRegion->xorSelf(tmp); + copyClipRectFromRegion(); + return true; +#else + return false; +#endif +} + +bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) { +#if STENCIL_BUFFER_SIZE + android::Rect tmp(left, top, right, bottom); + clipRegion->andSelf(tmp); + copyClipRectFromRegion(); + return true; +#else + return false; +#endif +} + +bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) { +#if STENCIL_BUFFER_SIZE + android::Rect tmp(left, top, right, bottom); + clipRegion->subtractSelf(tmp); + copyClipRectFromRegion(); + return true; +#else + return false; +#endif +} + +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; + + switch (op) { + case SkRegion::kDifference_Op: { + ensureClipRegion(); + clipped = clipRegionNand(r.left, r.top, r.right, r.bottom); + break; + } + case SkRegion::kIntersect_Op: { + if (CC_UNLIKELY(clipRegion)) { + clipped = clipRegionOr(r.left, r.top, r.right, r.bottom); + } else { + clipped = clipRect->intersect(r); + if (!clipped) { + clipRect->setEmpty(); + clipped = true; + } + } + break; + } + case SkRegion::kUnion_Op: { + if (CC_UNLIKELY(clipRegion)) { + clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom); + } else { + clipped = clipRect->unionWith(r); + } + break; + } + case SkRegion::kXOR_Op: { + ensureClipRegion(); + clipped = clipRegionXor(r.left, r.top, r.right, r.bottom); + break; + } + case SkRegion::kReverseDifference_Op: { + // TODO!!!!!!! + break; + } + case SkRegion::kReplace_Op: { + setClip(r.left, r.top, r.right, r.bottom); + 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); +#if STENCIL_BUFFER_SIZE + if (clipRegion) { + clipRegion->clear(); + clipRegion = NULL; + } +#endif + 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; + setClip(left, top, right, bottom); +} + +/////////////////////////////////////////////////////////////////////////////// +// 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..b2bc879 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,25 +174,57 @@ 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, + * Current clip rect. 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; /** + * Current clip region. The clip is stored in canvas-space coordinates, + * (screen-space coordinates in the regular case.) + * + * This is a reference to a region owned by this snapshot or another + * snapshot. This pointer must not be freed. See ::mClipRegionRoot. + * + * This field is used only if STENCIL_BUFFER_SIZE is > 0. + */ + Region* clipRegion; + + /** * 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; private: + void ensureClipRegion(); + void copyClipRectFromRegion(); + + bool clipRegionOr(float left, float top, float right, float bottom); + bool clipRegionXor(float left, float top, float right, float bottom); + bool clipRegionAnd(float left, float top, float right, float bottom); + bool clipRegionNand(float left, float top, float right, float bottom); + mat4 mTransformRoot; Rect mClipRectRoot; Rect mLocalClip; +#if STENCIL_BUFFER_SIZE + Region mClipRegionRoot; +#endif + }; // class Snapshot }; // namespace uirenderer diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk index 58d3e5c..2166ce7 100644 --- a/libs/rs/Android.mk +++ b/libs/rs/Android.mk @@ -89,7 +89,6 @@ LOCAL_SRC_FILES:= \ rsFifoSocket.cpp \ rsFileA3D.cpp \ rsFont.cpp \ - rsLocklessFifo.cpp \ rsObjectBase.cpp \ rsMatrix2x2.cpp \ rsMatrix3x3.cpp \ @@ -128,7 +127,7 @@ LOCAL_SRC_FILES:= \ driver/rsdShaderCache.cpp \ driver/rsdVertexArray.cpp -LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc libbcinfo +LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc libbcinfo libgui LOCAL_STATIC_LIBRARIES := libdex libft2 @@ -196,7 +195,6 @@ LOCAL_SRC_FILES:= \ rsFifoSocket.cpp \ rsFileA3D.cpp \ rsFont.cpp \ - rsLocklessFifo.cpp \ rsObjectBase.cpp \ rsMatrix2x2.cpp \ rsMatrix3x3.cpp \ diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp index 7acc054..368dd71 100644 --- a/libs/rs/driver/rsdGL.cpp +++ b/libs/rs/driver/rsdGL.cpp @@ -215,6 +215,8 @@ bool rsdGLInit(const Context *rsc) { ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs); checkEglError("eglGetConfigs", ret); + eglSwapInterval(dc->gl.egl.display, 0); + if (numConfigs) { EGLConfig* const configs = new EGLConfig[numConfigs]; diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 6887b22..ffb1196 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -115,6 +115,7 @@ ContextSetPriority { } ContextDestroyWorker { + sync } AssignName { diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index 972e3d6..fd85b07 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -124,7 +124,8 @@ void Allocation::elementData(Context *rsc, uint32_t x, const void *data, } const Element * e = mHal.state.type->getElement()->getField(cIdx); - if (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; @@ -157,8 +158,8 @@ void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y, } const Element * e = mHal.state.type->getElement()->getField(cIdx); - - if (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; diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index ad2ff0f..04284dd 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -18,6 +18,7 @@ #include "rsContext.h" #include "rsThreadIO.h" #include <ui/FramebufferNativeWindow.h> +#include <gui/DisplayEventReceiver.h> #include <sys/types.h> #include <sys/resource.h> @@ -245,42 +246,55 @@ void * Context::threadProc(void *vrsc) { } rsc->mRunning = true; - bool mDraw = true; - bool doWait = true; - - uint64_t targetTime = rsc->getTime(); - while (!rsc->mExit) { - uint64_t waitTime = 0; - uint64_t now = rsc->getTime(); - if (!doWait) { - if (now < targetTime) { - waitTime = targetTime - now; - doWait = true; - } + if (!rsc->mIsGraphicsContext) { + while (!rsc->mExit) { + rsc->mIO.playCoreCommands(rsc, true, -1); } + } else { +#ifndef ANDROID_RS_SERIALIZE + DisplayEventReceiver displayEvent; + DisplayEventReceiver::Event eventBuffer[1]; +#endif + int vsyncRate = 0; + int targetRate = 0; - mDraw |= rsc->mIO.playCoreCommands(rsc, doWait, waitTime); - mDraw &= (rsc->mRootScript.get() != NULL); - mDraw &= rsc->mHasSurface; - - if (mDraw && rsc->mIsGraphicsContext) { - uint64_t delay = rsc->runRootScript() * 1000000; - targetTime = rsc->getTime() + delay; - doWait = (delay == 0); + bool drawOnce = false; + while (!rsc->mExit) { + rsc->timerSet(RS_TIMER_IDLE); - if (rsc->props.mLogVisual) { - rsc->displayDebugStats(); +#ifndef ANDROID_RS_SERIALIZE + if (vsyncRate != targetRate) { + displayEvent.setVsyncRate(targetRate); + vsyncRate = targetRate; + } + if (targetRate) { + drawOnce |= rsc->mIO.playCoreCommands(rsc, true, displayEvent.getFd()); + while (displayEvent.getEvents(eventBuffer, 1) != 0) { + //ALOGE("vs2 time past %lld", (rsc->getTime() - eventBuffer[0].header.timestamp) / 1000000); + } + } else +#endif + { + drawOnce |= rsc->mIO.playCoreCommands(rsc, true, -1); } - mDraw = !rsc->mPaused; - rsc->timerSet(RS_TIMER_CLEAR_SWAP); - rsc->mHal.funcs.swap(rsc); - rsc->timerFrame(); - rsc->timerSet(RS_TIMER_INTERNAL); - rsc->timerPrint(); - rsc->timerReset(); - } else { - doWait = true; + if ((rsc->mRootScript.get() != NULL) && rsc->mHasSurface && + (targetRate || drawOnce) && !rsc->mPaused) { + + drawOnce = false; + targetRate = ((rsc->runRootScript() + 15) / 16); + + if (rsc->props.mLogVisual) { + rsc->displayDebugStats(); + } + + rsc->timerSet(RS_TIMER_CLEAR_SWAP); + rsc->mHal.funcs.swap(rsc); + rsc->timerFrame(); + rsc->timerSet(RS_TIMER_INTERNAL); + rsc->timerPrint(); + rsc->timerReset(); + } } } @@ -315,8 +329,8 @@ void Context::destroyWorkerThreadResources() { mFBOCache.deinit(this); } ObjectBase::freeAllChildren(this); - //ALOGV("destroyWorkerThreadResources 2"); mExit = true; + //ALOGV("destroyWorkerThreadResources 2"); } void Context::printWatchdogInfo(void *ctx) { @@ -382,7 +396,7 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { pthread_mutex_lock(&gInitMutex); mIO.init(); - mIO.setTimoutCallback(printWatchdogInfo, this, 2e9); + mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9); dev->addContext(this); mDev = dev; @@ -434,14 +448,12 @@ Context::~Context() { ALOGV("%p Context::~Context", this); if (!mIsContextLite) { - mIO.coreFlush(); - rsAssert(mExit); - mExit = true; mPaused = false; void *res; mIO.shutdown(); int status = pthread_join(mThreadId, &res); + rsAssert(mExit); if (mHal.funcs.shutdownDriver) { mHal.funcs.shutdownDriver(this); diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 61c29f9..a844a20 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -39,7 +39,6 @@ #include "rsFBOCache.h" #include "rsgApiStructs.h" -#include "rsLocklessFifo.h" // --------------------------------------------------------------------------- namespace android { diff --git a/libs/rs/rsFifo.cpp b/libs/rs/rsFifo.cpp deleted file mode 100644 index 3d5d8c4..0000000 --- a/libs/rs/rsFifo.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2011 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 "rsFifoSocket.h" -#include "utils/Timers.h" -#include "utils/StopWatch.h" - -using namespace android; -using namespace android::renderscript; - -Fifo::Fifo() { - -} - -Fifo::~Fifo() { - -} - diff --git a/libs/rs/rsFifo.h b/libs/rs/rsFifo.h index f924b95..911f446 100644 --- a/libs/rs/rsFifo.h +++ b/libs/rs/rsFifo.h @@ -35,9 +35,9 @@ protected: virtual ~Fifo(); public: - void virtual writeAsync(const void *data, size_t bytes) = 0; + bool virtual writeAsync(const void *data, size_t bytes, bool waitForSpace = true) = 0; void virtual writeWaitReturn(void *ret, size_t retSize) = 0; - size_t virtual read(void *data, size_t bytes) = 0; + size_t virtual read(void *data, size_t bytes, bool doWait = true, uint64_t timeToWait = 0) = 0; void virtual readReturn(const void *data, size_t bytes) = 0; void virtual flush() = 0; diff --git a/libs/rs/rsFifoSocket.cpp b/libs/rs/rsFifoSocket.cpp index 163a44b..bd511cf 100644 --- a/libs/rs/rsFifoSocket.cpp +++ b/libs/rs/rsFifoSocket.cpp @@ -22,6 +22,7 @@ #include <stdlib.h> #include <ctype.h> #include <unistd.h> +#include <poll.h> #include <sys/types.h> #include <sys/socket.h> @@ -29,55 +30,79 @@ using namespace android; using namespace android::renderscript; FifoSocket::FifoSocket() { - sequence = 1; + mShutdown = false; } FifoSocket::~FifoSocket() { } -bool FifoSocket::init() { +bool FifoSocket::init(bool supportNonBlocking, bool supportReturnValues, size_t maxDataSize) { int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); return false; } void FifoSocket::shutdown() { + mShutdown = true; + uint64_t d = 0; + ::send(sv[0], &d, sizeof(d), 0); + ::send(sv[1], &d, sizeof(d), 0); + close(sv[0]); + close(sv[1]); } -void FifoSocket::writeAsync(const void *data, size_t bytes) { +bool FifoSocket::writeAsync(const void *data, size_t bytes, bool waitForSpace) { if (bytes == 0) { - return; + return true; } //ALOGE("writeAsync %p %i", data, bytes); size_t ret = ::send(sv[0], data, bytes, 0); //ALOGE("writeAsync ret %i", ret); rsAssert(ret == bytes); + return true; } void FifoSocket::writeWaitReturn(void *retData, size_t retBytes) { + if (mShutdown) { + return; + } + //ALOGE("writeWaitReturn %p %i", retData, retBytes); - size_t ret = ::recv(sv[0], retData, retBytes, 0); + size_t ret = ::recv(sv[0], retData, retBytes, MSG_WAITALL); //ALOGE("writeWaitReturn %i", ret); rsAssert(ret == retBytes); } size_t FifoSocket::read(void *data, size_t bytes) { + if (mShutdown) { + return 0; + } + //ALOGE("read %p %i", data, bytes); - size_t ret = ::recv(sv[1], data, bytes, 0); - rsAssert(ret == bytes); - //ALOGE("read ret %i", ret); + size_t ret = ::recv(sv[1], data, bytes, MSG_WAITALL); + rsAssert(ret == bytes || mShutdown); + //ALOGE("read ret %i bytes %i", ret, bytes); + if (mShutdown) { + ret = 0; + } return ret; } -void FifoSocket::readReturn(const void *data, size_t bytes) { - ALOGE("readReturn %p %Zu", data, bytes); - size_t ret = ::send(sv[1], data, bytes, 0); - ALOGE("readReturn %Zu", ret); - rsAssert(ret == bytes); +bool FifoSocket::isEmpty() { + struct pollfd p; + p.fd = sv[1]; + p.events = POLLIN; + int r = poll(&p, 1, 0); + //ALOGE("poll r=%i", r); + return r == 0; } -void FifoSocket::flush() { +void FifoSocket::readReturn(const void *data, size_t bytes) { + //ALOGE("readReturn %p %Zu", data, bytes); + size_t ret = ::send(sv[1], data, bytes, 0); + //ALOGE("readReturn %Zu", ret); + //rsAssert(ret == bytes); } diff --git a/libs/rs/rsFifoSocket.h b/libs/rs/rsFifoSocket.h index 7df2b67..cac0a75 100644 --- a/libs/rs/rsFifoSocket.h +++ b/libs/rs/rsFifoSocket.h @@ -29,23 +29,23 @@ public: FifoSocket(); virtual ~FifoSocket(); - bool init(); + bool init(bool supportNonBlocking = true, + bool supportReturnValues = true, + size_t maxDataSize = 0); void shutdown(); + bool writeAsync(const void *data, size_t bytes, bool waitForSpace = true); + void writeWaitReturn(void *ret, size_t retSize); + size_t read(void *data, size_t bytes); + void readReturn(const void *data, size_t bytes); + bool isEmpty(); - - void virtual writeAsync(const void *data, size_t bytes); - void virtual writeWaitReturn(void *ret, size_t retSize); - size_t virtual read(void *data, size_t bytes); - void virtual readReturn(const void *data, size_t bytes); - - void virtual flush(); + int getWriteFd() {return sv[0];} + int getReadFd() {return sv[1];} protected: int sv[2]; - uint32_t sequence; - - + bool mShutdown; }; } diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp deleted file mode 100644 index 0466d8b..0000000 --- a/libs/rs/rsLocklessFifo.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2009 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 "rsLocklessFifo.h" -#include "utils/Timers.h" -#include "utils/StopWatch.h" - -using namespace android; -using namespace android::renderscript; - -LocklessCommandFifo::LocklessCommandFifo() : mBuffer(0), mInitialized(false) { - mTimeoutCallback = NULL; - mTimeoutCallbackData = NULL; - mTimeoutWait = 0; -} - -LocklessCommandFifo::~LocklessCommandFifo() { - if (!mInShutdown && mInitialized) { - shutdown(); - } - if (mBuffer) { - free(mBuffer); - } -} - -void LocklessCommandFifo::shutdown() { - mInShutdown = true; - mSignalToWorker.set(); -} - -bool LocklessCommandFifo::init(uint32_t sizeInBytes) { - // Add room for a buffer reset command - mBuffer = static_cast<uint8_t *>(malloc(sizeInBytes + 4)); - if (!mBuffer) { - ALOGE("LocklessFifo allocation failure"); - return false; - } - - if (!mSignalToControl.init() || !mSignalToWorker.init()) { - ALOGE("Signal setup failed"); - free(mBuffer); - return false; - } - - mInShutdown = false; - mSize = sizeInBytes; - mPut = mBuffer; - mGet = mBuffer; - mEnd = mBuffer + (sizeInBytes) - 1; - //dumpState("init"); - mInitialized = true; - return true; -} - -uint32_t LocklessCommandFifo::getFreeSpace() const { - int32_t freeSpace = 0; - //dumpState("getFreeSpace"); - - if (mPut >= mGet) { - freeSpace = mEnd - mPut; - } else { - freeSpace = mGet - mPut; - } - - if (freeSpace < 0) { - freeSpace = 0; - } - return freeSpace; -} - -bool LocklessCommandFifo::isEmpty() const { - uint32_t p = android_atomic_acquire_load((int32_t *)&mPut); - return ((uint8_t *)p) == mGet; -} - - -void * LocklessCommandFifo::reserve(uint32_t sizeInBytes) { - // Add space for command header and loop token; - sizeInBytes += 8; - - //dumpState("reserve"); - if (getFreeSpace() < sizeInBytes) { - makeSpace(sizeInBytes); - } - - return mPut + 4; -} - -void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes) { - if (mInShutdown) { - return; - } - //dumpState("commit 1"); - reinterpret_cast<uint16_t *>(mPut)[0] = command; - reinterpret_cast<uint16_t *>(mPut)[1] = sizeInBytes; - - int32_t s = ((sizeInBytes + 3) & ~3) + 4; - android_atomic_add(s, (int32_t *)&mPut); - //dumpState("commit 2"); - mSignalToWorker.set(); -} - -void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes) { - if (mInShutdown) { - return; - } - - //char buf[1024]; - //sprintf(buf, "RenderScript LocklessCommandFifo::commitSync %p %i %i", this, command, sizeInBytes); - //StopWatch compileTimer(buf); - commit(command, sizeInBytes); - flush(); -} - -void LocklessCommandFifo::flush() { - //dumpState("flush 1"); - while (mPut != mGet) { - while (!mSignalToControl.wait(mTimeoutWait)) { - if (mTimeoutCallback) { - mTimeoutCallback(mTimeoutCallbackData); - } - } - } - //dumpState("flush 2"); -} - -void LocklessCommandFifo::setTimoutCallback(void (*cbk)(void *), void *data, uint64_t timeout) { - mTimeoutCallback = cbk; - mTimeoutCallbackData = data; - mTimeoutWait = timeout; -} - -bool LocklessCommandFifo::wait(uint64_t timeout) { - while (isEmpty() && !mInShutdown) { - mSignalToControl.set(); - return mSignalToWorker.wait(timeout); - } - return true; -} - -const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData, uint64_t timeout) { - while (1) { - //dumpState("get"); - wait(timeout); - - if (isEmpty() || mInShutdown) { - *command = 0; - *bytesData = 0; - return NULL; - } - - *command = reinterpret_cast<const uint16_t *>(mGet)[0]; - *bytesData = reinterpret_cast<const uint16_t *>(mGet)[1]; - if (*command) { - // non-zero command is valid - return mGet+4; - } - - // zero command means reset to beginning. - mGet = mBuffer; - } -} - -void LocklessCommandFifo::next() { - uint32_t bytes = reinterpret_cast<const uint16_t *>(mGet)[1]; - - android_atomic_add(((bytes + 3) & ~3) + 4, (int32_t *)&mGet); - //mGet += ((bytes + 3) & ~3) + 4; - if (isEmpty()) { - mSignalToControl.set(); - } - //dumpState("next"); -} - -bool LocklessCommandFifo::makeSpaceNonBlocking(uint32_t bytes) { - //dumpState("make space non-blocking"); - if ((mPut+bytes) > mEnd) { - // Need to loop regardless of where get is. - if ((mGet > mPut) || (mBuffer+4 >= mGet)) { - return false; - } - - // Toss in a reset then the normal wait for space will do the rest. - reinterpret_cast<uint16_t *>(mPut)[0] = 0; - reinterpret_cast<uint16_t *>(mPut)[1] = 0; - mPut = mBuffer; - mSignalToWorker.set(); - } - - // it will fit here so we just need to wait for space. - if (getFreeSpace() < bytes) { - return false; - } - - return true; -} - -void LocklessCommandFifo::makeSpace(uint32_t bytes) { - //dumpState("make space"); - if ((mPut+bytes) > mEnd) { - // Need to loop regardless of where get is. - while ((mGet > mPut) || (mBuffer+4 >= mGet)) { - usleep(100); - } - - // Toss in a reset then the normal wait for space will do the rest. - reinterpret_cast<uint16_t *>(mPut)[0] = 0; - reinterpret_cast<uint16_t *>(mPut)[1] = 0; - mPut = mBuffer; - mSignalToWorker.set(); - } - - // it will fit here so we just need to wait for space. - while (getFreeSpace() < bytes) { - usleep(100); - } - -} - -void LocklessCommandFifo::dumpState(const char *s) const { - ALOGV("%s %p put %p, get %p, buf %p, end %p", s, this, mPut, mGet, mBuffer, mEnd); -} - -void LocklessCommandFifo::printDebugData() const { - dumpState("printing fifo debug"); - const uint32_t *pptr = (const uint32_t *)mGet; - pptr -= 8 * 4; - if (mGet < mBuffer) { - pptr = (const uint32_t *)mBuffer; - } - - - for (int ct=0; ct < 16; ct++) { - ALOGV("fifo %p = 0x%08x 0x%08x 0x%08x 0x%08x", pptr, pptr[0], pptr[1], pptr[2], pptr[3]); - pptr += 4; - } - -} diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h deleted file mode 100644 index dafc512..0000000 --- a/libs/rs/rsLocklessFifo.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#ifndef ANDROID_RS_LOCKLESS_FIFO_H -#define ANDROID_RS_LOCKLESS_FIFO_H - - -#include "rsUtils.h" -#include "rsSignal.h" - -namespace android { -namespace renderscript { - - -// A simple FIFO to be used as a producer / consumer between two -// threads. One is writer and one is reader. The common cases -// will not require locking. It is not threadsafe for multiple -// readers or writers by design. - -class LocklessCommandFifo { -public: - bool init(uint32_t size); - void shutdown(); - void setTimoutCallback(void (*)(void *), void *, uint64_t timeout); - - void printDebugData() const; - - LocklessCommandFifo(); - ~LocklessCommandFifo(); - -protected: - uint8_t * volatile mPut; - uint8_t * volatile mGet; - uint8_t * mBuffer; - uint8_t * mEnd; - uint8_t mSize; - bool mInShutdown; - bool mInitialized; - - Signal mSignalToWorker; - Signal mSignalToControl; - -public: - void * reserve(uint32_t bytes); - void commit(uint32_t command, uint32_t bytes); - void commitSync(uint32_t command, uint32_t bytes); - - void flush(); - bool wait(uint64_t timeout = 0); - - const void * get(uint32_t *command, uint32_t *bytesData, uint64_t timeout = 0); - void next(); - - void makeSpace(uint32_t bytes); - bool makeSpaceNonBlocking(uint32_t bytes); - - bool isEmpty() const; - uint32_t getFreeSpace() const; - -private: - void dumpState(const char *) const; - - void (*mTimeoutCallback)(void *); - void * mTimeoutCallbackData; - uint64_t mTimeoutWait; -}; - - -} -} -#endif diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index 929dd68..b4eb995 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -322,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 1917774..8e4b988 100644 --- a/libs/rs/rsThreadIO.cpp +++ b/libs/rs/rsThreadIO.cpp @@ -18,227 +18,189 @@ #include "rsThreadIO.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <fcntl.h> +#include <poll.h> + + using namespace android; using namespace android::renderscript; -ThreadIO::ThreadIO() : mUsingSocket(false) { +ThreadIO::ThreadIO() { + mRunning = true; } ThreadIO::~ThreadIO() { } -void ThreadIO::init(bool useSocket) { - mUsingSocket = useSocket; - mToCore.init(16 * 1024); - - if (mUsingSocket) { - mToClientSocket.init(); - mToCoreSocket.init(); - } else { - mToClient.init(1024); - } +void ThreadIO::init() { + mToClient.init(); + mToCore.init(); } void ThreadIO::shutdown() { - //ALOGE("shutdown 1"); + mRunning = false; mToCore.shutdown(); - //ALOGE("shutdown 2"); -} - -void ThreadIO::coreFlush() { - //ALOGE("coreFlush 1"); - if (mUsingSocket) { - } else { - mToCore.flush(); - } - //ALOGE("coreFlush 2"); } void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) { //ALOGE("coreHeader %i %i", cmdID, dataLen); - if (mUsingSocket) { - CoreCmdHeader hdr; - hdr.bytes = dataLen; - hdr.cmdID = cmdID; - mToCoreSocket.writeAsync(&hdr, sizeof(hdr)); - } else { - mCoreCommandSize = dataLen; - mCoreCommandID = cmdID; - mCoreDataPtr = (uint8_t *)mToCore.reserve(dataLen); - mCoreDataBasePtr = mCoreDataPtr; - } - //ALOGE("coreHeader ret %p", mCoreDataPtr); - return mCoreDataPtr; -} - -void ThreadIO::coreData(const void *data, size_t dataLen) { - //ALOGE("coreData %p %i", data, dataLen); - mToCoreSocket.writeAsync(data, dataLen); - //ALOGE("coreData ret %p", mCoreDataPtr); + CoreCmdHeader *hdr = (CoreCmdHeader *)&mSendBuffer[0]; + hdr->bytes = dataLen; + hdr->cmdID = cmdID; + mSendLen = dataLen + sizeof(CoreCmdHeader); + //mToCoreSocket.writeAsync(&hdr, sizeof(hdr)); + //ALOGE("coreHeader ret "); + return &mSendBuffer[sizeof(CoreCmdHeader)]; } void ThreadIO::coreCommit() { - //ALOGE("coreCommit %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize); - if (mUsingSocket) { - } else { - rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize); - mToCore.commit(mCoreCommandID, mCoreCommandSize); - } - //ALOGE("coreCommit ret"); -} - -void ThreadIO::coreCommitSync() { - //ALOGE("coreCommitSync %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize); - if (mUsingSocket) { - } else { - rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize); - mToCore.commitSync(mCoreCommandID, mCoreCommandSize); - } - //ALOGE("coreCommitSync ret"); + mToCore.writeAsync(&mSendBuffer, mSendLen); } void ThreadIO::clientShutdown() { - //ALOGE("coreShutdown 1"); mToClient.shutdown(); - //ALOGE("coreShutdown 2"); } void ThreadIO::coreSetReturn(const void *data, size_t dataLen) { - rsAssert(dataLen <= sizeof(mToCoreRet)); - memcpy(&mToCoreRet, data, dataLen); + uint32_t buf; + if (data == NULL) { + data = &buf; + dataLen = sizeof(buf); + } + + mToCore.readReturn(data, dataLen); } void ThreadIO::coreGetReturn(void *data, size_t dataLen) { - memcpy(data, &mToCoreRet, dataLen); -} + uint32_t buf; + if (data == NULL) { + data = &buf; + dataLen = sizeof(buf); + } -void ThreadIO::setTimoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) { - mToCore.setTimoutCallback(cb, dat, timeout); + mToCore.writeWaitReturn(data, dataLen); } +void ThreadIO::setTimeoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) { + //mToCore.setTimeoutCallback(cb, dat, timeout); +} -bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait) { +bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, int waitFd) { bool ret = false; - uint64_t startTime = con->getTime(); - while (!mToCore.isEmpty() || waitForCommand) { - uint32_t cmdID = 0; - uint32_t cmdSize = 0; - if (con->props.mLogTimes) { - con->timerSet(Context::RS_TIMER_IDLE); - } + uint8_t buf[2 * 1024]; + const CoreCmdHeader *cmd = (const CoreCmdHeader *)&buf[0]; + const void * data = (const void *)&buf[sizeof(CoreCmdHeader)]; + + struct pollfd p[2]; + p[0].fd = mToCore.getReadFd(); + p[0].events = POLLIN; + p[0].revents = 0; + p[1].fd = waitFd; + p[1].events = POLLIN; + p[1].revents = 0; + int pollCount = 1; + if (waitFd >= 0) { + pollCount = 2; + } - uint64_t delay = 0; - if (waitForCommand) { - delay = timeToWait - (con->getTime() - startTime); - if (delay > timeToWait) { - delay = 0; - } - } + if (con->props.mLogTimes) { + con->timerSet(Context::RS_TIMER_IDLE); + } - if (delay == 0 && timeToWait != 0 && mToCore.isEmpty()) { + int waitTime = -1; + while (mRunning) { + int pr = poll(p, pollCount, waitTime); + if (pr <= 0) { break; } - const void * data = mToCore.get(&cmdID, &cmdSize, delay); - if (!cmdSize) { - // exception or timeout occurred. - break; - } - ret = true; - if (con->props.mLogTimes) { - con->timerSet(Context::RS_TIMER_INTERNAL); + if (p[0].revents) { + size_t r = mToCore.read(&buf[0], sizeof(CoreCmdHeader)); + mToCore.read(&buf[sizeof(CoreCmdHeader)], cmd->bytes); + + if (r != sizeof(CoreCmdHeader)) { + // exception or timeout occurred. + break; + } + + ret = true; + if (con->props.mLogTimes) { + con->timerSet(Context::RS_TIMER_INTERNAL); + } + waitForCommand = false; + //ALOGV("playCoreCommands 3 %i %i", cmd->cmdID, cmd->bytes); + + if (cmd->cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) { + rsAssert(cmd->cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *))); + ALOGE("playCoreCommands error con %p, cmd %i", con, cmd->cmdID); + } + gPlaybackFuncs[cmd->cmdID](con, data, cmd->bytes); + + if (con->props.mLogTimes) { + con->timerSet(Context::RS_TIMER_IDLE); + } + + if (waitFd < 0) { + // If we don't have a secondary wait object we should stop blocking now + // that at least one command has been processed. + waitTime = 0; + } } - waitForCommand = false; - //ALOGV("playCoreCommands 3 %i %i", cmdID, cmdSize); - if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) { - rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *))); - ALOGE("playCoreCommands error con %p, cmd %i", con, cmdID); - mToCore.printDebugData(); + if (p[1].revents && !p[0].revents) { + // We want to finish processing fifo events before processing the vsync. + // Otherwise we can end up falling behind and having tremendous lag. + break; } - gPlaybackFuncs[cmdID](con, data, cmdSize << 2); - mToCore.next(); } return ret; } RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) { - if (mUsingSocket) { - mToClientSocket.read(&mLastClientHeader, sizeof(mLastClientHeader)); - } else { - size_t bytesData = 0; - const uint32_t *d = (const uint32_t *)mToClient.get(&mLastClientHeader.cmdID, (uint32_t*)&bytesData); - if (bytesData >= sizeof(uint32_t)) { - mLastClientHeader.userID = d[0]; - mLastClientHeader.bytes = bytesData - sizeof(uint32_t); - } else { - mLastClientHeader.userID = 0; - mLastClientHeader.bytes = 0; - } - } + //ALOGE("getClientHeader"); + mToClient.read(&mLastClientHeader, sizeof(mLastClientHeader)); + receiveLen[0] = mLastClientHeader.bytes; usrID[0] = mLastClientHeader.userID; + //ALOGE("getClientHeader %i %i %i", mLastClientHeader.cmdID, usrID[0], receiveLen[0]); return (RsMessageToClientType)mLastClientHeader.cmdID; } RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen, uint32_t *usrID, size_t bufferLen) { + //ALOGE("getClientPayload"); receiveLen[0] = mLastClientHeader.bytes; usrID[0] = mLastClientHeader.userID; if (bufferLen < mLastClientHeader.bytes) { return RS_MESSAGE_TO_CLIENT_RESIZE; } - if (mUsingSocket) { - if (receiveLen[0]) { - mToClientSocket.read(data, receiveLen[0]); - } - return (RsMessageToClientType)mLastClientHeader.cmdID; - } else { - uint32_t bytesData = 0; - uint32_t commandID = 0; - const uint32_t *d = (const uint32_t *)mToClient.get(&commandID, &bytesData); - //ALOGE("getMessageToClient 3 %i %i", commandID, bytesData); - //ALOGE("getMessageToClient %i %i", commandID, *subID); - if (bufferLen >= receiveLen[0]) { - memcpy(data, d+1, receiveLen[0]); - mToClient.next(); - return (RsMessageToClientType)commandID; - } + if (receiveLen[0]) { + mToClient.read(data, receiveLen[0]); } - return RS_MESSAGE_TO_CLIENT_RESIZE; + //ALOGE("getClientPayload x"); + return (RsMessageToClientType)mLastClientHeader.cmdID; } bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data, size_t dataLen, bool waitForSpace) { + + //ALOGE("sendToClient %i %i %i", cmdID, usrID, (int)dataLen); ClientCmdHeader hdr; hdr.bytes = dataLen; hdr.cmdID = cmdID; hdr.userID = usrID; - if (mUsingSocket) { - mToClientSocket.writeAsync(&hdr, sizeof(hdr)); - if (dataLen) { - mToClientSocket.writeAsync(data, dataLen); - } - return true; - } else { - if (!waitForSpace) { - if (!mToClient.makeSpaceNonBlocking(dataLen + sizeof(hdr))) { - // Not enough room, and not waiting. - return false; - } - } - //ALOGE("sendMessageToClient 2"); - uint32_t *p = (uint32_t *)mToClient.reserve(dataLen + sizeof(usrID)); - p[0] = usrID; - if (dataLen > 0) { - memcpy(p+1, data, dataLen); - } - mToClient.commit(cmdID, dataLen + sizeof(usrID)); - //ALOGE("sendMessageToClient 3"); - return true; + mToClient.writeAsync(&hdr, sizeof(hdr)); + if (dataLen) { + mToClient.writeAsync(data, dataLen); } - return false; + + //ALOGE("sendToClient x"); + return true; } diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h index ebce0ab..d56a1c9 100644 --- a/libs/rs/rsThreadIO.h +++ b/libs/rs/rsThreadIO.h @@ -18,7 +18,6 @@ #define ANDROID_RS_THREAD_IO_H #include "rsUtils.h" -#include "rsLocklessFifo.h" #include "rsFifoSocket.h" // --------------------------------------------------------------------------- @@ -32,23 +31,17 @@ public: ThreadIO(); ~ThreadIO(); - void init(bool useSocket = false); + void init(); void shutdown(); // Plays back commands from the client. // Returns true if any commands were processed. - bool playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait); + bool playCoreCommands(Context *con, bool waitForCommand, int waitFd); - void setTimoutCallback(void (*)(void *), void *, uint64_t timeout); - //LocklessCommandFifo mToCore; + void setTimeoutCallback(void (*)(void *), void *, uint64_t timeout); - - - void coreFlush(); void * coreHeader(uint32_t, size_t dataLen); - void coreData(const void *data, size_t dataLen); void coreCommit(); - void coreCommitSync(); void coreSetReturn(const void *data, size_t dataLen); void coreGetReturn(void *data, size_t dataLen); @@ -71,20 +64,16 @@ protected: } ClientCmdHeader; ClientCmdHeader mLastClientHeader; - size_t mCoreCommandSize; - uint32_t mCoreCommandID; - uint8_t * mCoreDataPtr; - uint8_t * mCoreDataBasePtr; + bool mRunning; - bool mUsingSocket; - LocklessCommandFifo mToClient; - LocklessCommandFifo mToCore; - - FifoSocket mToClientSocket; - FifoSocket mToCoreSocket; + FifoSocket mToClient; + FifoSocket mToCore; intptr_t mToCoreRet; + size_t mSendLen; + uint8_t mSendBuffer[2 * 1024]; + }; diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c index 6b84e56..385c8b5 100644 --- a/libs/rs/rsg_generator.c +++ b/libs/rs/rsg_generator.c @@ -256,7 +256,7 @@ void printApiCpp(FILE *f) { fprintf(f, " memcpy(payload, %s, %s_length);\n", vt->name, vt->name); fprintf(f, " cmd->%s = (", vt->name); printVarType(f, vt); - fprintf(f, ")payload;\n"); + fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n"); fprintf(f, " payload += %s_length;\n", vt->name); fprintf(f, " } else {\n"); fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name); @@ -270,26 +270,19 @@ void printApiCpp(FILE *f) { needFlush = 1; } + fprintf(f, " io->coreCommit();\n"); if (hasInlineDataPointers(api)) { - fprintf(f, " if (dataSize < 1024) {\n"); - fprintf(f, " io->coreCommit();\n"); - fprintf(f, " } else {\n"); - fprintf(f, " io->coreCommitSync();\n"); + fprintf(f, " if (dataSize >= 1024) {\n"); + fprintf(f, " io->coreGetReturn(NULL, 0);\n"); fprintf(f, " }\n"); - } else { - fprintf(f, " io->coreCommit"); - if (needFlush) { - fprintf(f, "Sync"); - } - fprintf(f, "();\n"); - } - - if (api->ret.typeName[0]) { + } else if (api->ret.typeName[0]) { fprintf(f, "\n "); printVarType(f, &api->ret); fprintf(f, " ret;\n"); fprintf(f, " io->coreGetReturn(&ret, sizeof(ret));\n"); fprintf(f, " return ret;\n"); + } else if (needFlush) { + fprintf(f, " io->coreGetReturn(NULL, 0);\n"); } } fprintf(f, "};\n\n"); @@ -434,6 +427,7 @@ void printPlaybackCpp(FILE *f) { for (ct=0; ct < apiCount; ct++) { const ApiEntry * api = &apis[ct]; + int needFlush = 0; if (api->direct) { continue; @@ -444,6 +438,13 @@ void printPlaybackCpp(FILE *f) { //fprintf(f, " ALOGE(\"play command %s\\n\");\n", api->name); fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name); + if (hasInlineDataPointers(api)) { + fprintf(f, " const uint8_t *baseData = 0;\n"); + fprintf(f, " if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name); + fprintf(f, " baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n"); + fprintf(f, " }\n"); + } + fprintf(f, " "); if (api->ret.typeName[0]) { fprintf(f, "\n "); @@ -453,12 +454,31 @@ void printPlaybackCpp(FILE *f) { fprintf(f, "rsi_%s(con", api->name); for (ct2=0; ct2 < api->paramCount; ct2++) { const VarType *vt = &api->params[ct2]; - fprintf(f, ",\n cmd->%s", vt->name); + needFlush += vt->ptrLevel; + + if (hasInlineDataPointers(api) && vt->ptrLevel) { + fprintf(f, ",\n (const %s *)&baseData[(intptr_t)cmd->%s]", vt->typeName, vt->name); + } else { + fprintf(f, ",\n cmd->%s", vt->name); + } } fprintf(f, ");\n"); - if (api->ret.typeName[0]) { + if (hasInlineDataPointers(api)) { + fprintf(f, " size_t totalSize = 0;\n"); + for (ct2=0; ct2 < api->paramCount; ct2++) { + if (api->params[ct2].ptrLevel) { + fprintf(f, " totalSize += cmd->%s_length;\n", api->params[ct2].name); + } + } + + fprintf(f, " if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name); + fprintf(f, " con->mIO.coreSetReturn(NULL, 0);\n"); + fprintf(f, " }\n"); + } else if (api->ret.typeName[0]) { fprintf(f, " con->mIO.coreSetReturn(&ret, sizeof(ret));\n"); + } else if (api->sync || needFlush) { + fprintf(f, " con->mIO.coreSetReturn(NULL, 0);\n"); } fprintf(f, "};\n\n"); @@ -466,6 +486,7 @@ void printPlaybackCpp(FILE *f) { for (ct=0; ct < apiCount; ct++) { const ApiEntry * api = &apis[ct]; + int needFlush = 0; fprintf(f, "void rspr_%s(Context *con, Fifo *f, uint8_t *scratch, size_t scratchSize) {\n", api->name); @@ -475,6 +496,7 @@ void printPlaybackCpp(FILE *f) { for (ct2=0; ct2 < api->paramCount; ct2++) { const VarType *vt = &api->params[ct2]; + needFlush += vt->ptrLevel; if (vt->ptrLevel == 1) { fprintf(f, " cmd.%s = (", vt->name); printVarType(f, vt); @@ -515,6 +537,8 @@ void printPlaybackCpp(FILE *f) { if (api->ret.typeName[0]) { fprintf(f, " f->readReturn(&ret, sizeof(ret));\n"); + } else if (needFlush) { + fprintf(f, " f->readReturn(NULL, 0);\n"); } fprintf(f, "};\n\n"); diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 8cd047a..6e2e731 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -126,6 +126,9 @@ void Region::addRectUnchecked(int l, int t, int r, int b) Region& Region::orSelf(const Rect& r) { return operationSelf(r, op_or); } +Region& Region::xorSelf(const Rect& r) { + return operationSelf(r, op_xor); +} Region& Region::andSelf(const Rect& r) { return operationSelf(r, op_and); } @@ -143,6 +146,9 @@ Region& Region::operationSelf(const Rect& r, int op) { Region& Region::orSelf(const Region& rhs) { return operationSelf(rhs, op_or); } +Region& Region::xorSelf(const Region& rhs) { + return operationSelf(rhs, op_xor); +} Region& Region::andSelf(const Region& rhs) { return operationSelf(rhs, op_and); } @@ -165,6 +171,9 @@ Region& Region::translateSelf(int x, int y) { const Region Region::merge(const Rect& rhs) const { return operation(rhs, op_or); } +const Region Region::mergeExclusive(const Rect& rhs) const { + return operation(rhs, op_xor); +} const Region Region::intersect(const Rect& rhs) const { return operation(rhs, op_and); } @@ -182,6 +191,9 @@ const Region Region::operation(const Rect& rhs, int op) const { const Region Region::merge(const Region& rhs) const { return operation(rhs, op_or); } +const Region Region::mergeExclusive(const Region& rhs) const { + return operation(rhs, op_xor); +} const Region Region::intersect(const Region& rhs) const { return operation(rhs, op_and); } @@ -205,6 +217,9 @@ const Region Region::translate(int x, int y) const { Region& Region::orSelf(const Region& rhs, int dx, int dy) { return operationSelf(rhs, dx, dy, op_or); } +Region& Region::xorSelf(const Region& rhs, int dx, int dy) { + return operationSelf(rhs, dx, dy, op_xor); +} Region& Region::andSelf(const Region& rhs, int dx, int dy) { return operationSelf(rhs, dx, dy, op_and); } @@ -222,6 +237,9 @@ Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) { const Region Region::merge(const Region& rhs, int dx, int dy) const { return operation(rhs, dx, dy, op_or); } +const Region Region::mergeExclusive(const Region& rhs, int dx, int dy) const { + return operation(rhs, dx, dy, op_xor); +} const Region Region::intersect(const Region& rhs, int dx, int dy) const { return operation(rhs, dx, dy, op_and); } @@ -421,6 +439,7 @@ void Region::boolean_operation(int op, Region& dst, SkRegion::Op sk_op; switch (op) { case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break; + case op_xor: sk_op = SkRegion::kUnion_XOR; name="XOR"; break; case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break; case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break; } diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk index 77b8424..ecb455a 100644 --- a/libs/usb/tests/AccessoryChat/Android.mk +++ b/libs/usb/tests/AccessoryChat/Android.mk @@ -23,9 +23,4 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := AccessoryChat -LOCAL_JAVA_LIBRARIES := com.android.future.usb.accessory - -# Force an old SDK version to make sure we aren't using newer UsbManager APIs -LOCAL_SDK_VERSION := 8 - include $(BUILD_PACKAGE) diff --git a/libs/usb/tests/AccessoryChat/AndroidManifest.xml b/libs/usb/tests/AccessoryChat/AndroidManifest.xml index 802b715..6667eba 100644 --- a/libs/usb/tests/AccessoryChat/AndroidManifest.xml +++ b/libs/usb/tests/AccessoryChat/AndroidManifest.xml @@ -17,8 +17,9 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.accessorychat"> + <uses-feature android:name="android.hardware.usb.accessory" /> + <application android:label="Accessory Chat"> - <uses-library android:name="com.android.future.usb.accessory" /> <activity android:name="AccessoryChat" android:label="Accessory Chat"> <intent-filter> @@ -35,5 +36,5 @@ android:resource="@xml/accessory_filter" /> </activity> </application> - <uses-sdk android:minSdkVersion="10" /> + <uses-sdk android:minSdkVersion="12" /> </manifest> diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c index 85b52dd..06b477f 100644 --- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c +++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c @@ -98,7 +98,7 @@ static int usb_device_added(const char *devname, void* client_data) { vendorId = usb_device_get_vendor_id(device); productId = usb_device_get_product_id(device); - if (vendorId == 0x18D1 || vendorId == 0x22B8) { + if (vendorId == 0x18D1 || vendorId == 0x22B8 || vendorId == 0x04e8) { if (!sDevice && (productId == 0x2D00 || productId == 0x2D01)) { struct usb_descriptor_header* desc; struct usb_descriptor_iter iter; diff --git a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java index c3f4fa3..bf0cef0 100644 --- a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java +++ b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java @@ -33,8 +33,8 @@ import android.util.Log; import android.widget.EditText; import android.widget.TextView; -import com.android.future.usb.UsbAccessory; -import com.android.future.usb.UsbManager; +import android.hardware.usb.UsbManager; +import android.hardware.usb.UsbAccessory; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -64,9 +64,11 @@ public class AccessoryChat extends Activity implements Runnable, TextView.OnEdit public void onReceive(Context context, Intent intent) { if (ACTION_USB_PERMISSION.equals(intent.getAction())) { synchronized (this) { - UsbAccessory accessory = UsbManager.getAccessory(intent); + UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { - openAccessory(accessory); + if (accessory != null) { + openAccessory(accessory); + } } else { Log.d(TAG, "permission denied for accessory " + accessory); } @@ -80,7 +82,7 @@ public class AccessoryChat extends Activity implements Runnable, TextView.OnEdit public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mUsbManager = UsbManager.getInstance(this); + mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(mUsbReceiver, filter); 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/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); |
