diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 240 |
1 files changed, 144 insertions, 96 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97edfee..b0881a4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -32,6 +32,7 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/MemoryHeapBase.h> +#include <binder/PermissionCache.h> #include <utils/String8.h> #include <utils/String16.h> @@ -67,17 +68,19 @@ namespace android { // --------------------------------------------------------------------------- +const String16 sHardwareTest("android.permission.HARDWARE_TEST"); +const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"); +const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); +const String16 sDump("android.permission.DUMP"); + +// --------------------------------------------------------------------------- + SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), - mTransactionCount(0), mResizeTransationPending(false), mLayersRemoved(false), mBootTime(systemTime()), - mHardwareTest("android.permission.HARDWARE_TEST"), - mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"), - mReadFramebuffer("android.permission.READ_FRAME_BUFFER"), - mDump("android.permission.DUMP"), mVisibleRegionsDirty(false), mHwWorkListDirty(false), mDeferReleaseConsole(false), @@ -160,9 +163,34 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); mBootFinished = true; + + // wait patiently for the window manager death + const String16 name("window"); + sp<IBinder> window(defaultServiceManager()->getService(name)); + if (window != 0) { + window->linkToDeath(this); + } + + // stop boot animation property_set("ctl.stop", "bootanim"); } +void SurfaceFlinger::binderDied(const wp<IBinder>& who) +{ + // the window manager died on us. prepare its eulogy. + + // unfreeze the screen in case it was... frozen + mFreezeDisplayTime = 0; + mFreezeCount = 0; + mFreezeDisplay = false; + + // reset screen orientation + setOrientation(0, eOrientationDefault, 0); + + // restart the boot-animation + property_set("ctl.start", "bootanim"); +} + void SurfaceFlinger::onFirstRef() { run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); @@ -248,7 +276,8 @@ status_t SurfaceFlinger::readyToRun() glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrthof(0, w, h, 0, 0, 1); + // put the origin in the left-bottom corner + glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h mReadyToRunBarrier.open(); @@ -381,13 +410,11 @@ bool SurfaceFlinger::threadLoop() handleConsoleEvents(); } - if (LIKELY(mTransactionCount == 0)) { - // if we're in a global transaction, don't do anything. - const uint32_t mask = eTransactionNeeded | eTraversalNeeded; - uint32_t transactionFlags = peekTransactionFlags(mask); - if (LIKELY(transactionFlags)) { - handleTransaction(transactionFlags); - } + // if we're in a global transaction, don't do anything. + const uint32_t mask = eTransactionNeeded | eTraversalNeeded; + uint32_t transactionFlags = peekTransactionFlags(mask); + if (UNLIKELY(transactionFlags)) { + handleTransaction(transactionFlags); } // post surfaces (if needed) @@ -1172,28 +1199,33 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) return old; } -void SurfaceFlinger::openGlobalTransaction() -{ - android_atomic_inc(&mTransactionCount); -} -void SurfaceFlinger::closeGlobalTransaction() -{ - if (android_atomic_dec(&mTransactionCount) == 1) { - signalEvent(); +void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) { + Mutex::Autolock _l(mStateLock); - // if there is a transaction with a resize, wait for it to - // take effect before returning. - Mutex::Autolock _l(mStateLock); - while (mResizeTransationPending) { - status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); - if (CC_UNLIKELY(err != NO_ERROR)) { - // just in case something goes wrong in SF, return to the - // called after a few seconds. - LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); - mResizeTransationPending = false; - break; - } + uint32_t flags = 0; + const size_t count = state.size(); + for (size_t i=0 ; i<count ; i++) { + const ComposerState& s(state[i]); + sp<Client> client( static_cast<Client *>(s.client.get()) ); + flags |= setClientStateLocked(client, s.state); + } + if (flags) { + setTransactionFlags(flags); + } + + signalEvent(); + + // if there is a transaction with a resize, wait for it to + // take effect before returning. + while (mResizeTransationPending) { + status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); + if (CC_UNLIKELY(err != NO_ERROR)) { + // just in case something goes wrong in SF, return to the + // called after a few seconds. + LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); + mResizeTransationPending = false; + break; } } } @@ -1389,60 +1421,52 @@ status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer) return err; } -status_t SurfaceFlinger::setClientState( +uint32_t SurfaceFlinger::setClientStateLocked( const sp<Client>& client, - int32_t count, - const layer_state_t* states) + const layer_state_t& s) { - Mutex::Autolock _l(mStateLock); uint32_t flags = 0; - for (int i=0 ; i<count ; i++) { - const layer_state_t& s(states[i]); - sp<LayerBaseClient> layer(client->getLayerUser(s.surface)); - if (layer != 0) { - const uint32_t what = s.what; - if (what & ePositionChanged) { - if (layer->setPosition(s.x, s.y)) - flags |= eTraversalNeeded; - } - if (what & eLayerChanged) { - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayer(s.z)) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; - } - } - if (what & eSizeChanged) { - if (layer->setSize(s.w, s.h)) { - flags |= eTraversalNeeded; - mResizeTransationPending = true; - } - } - if (what & eAlphaChanged) { - if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) - flags |= eTraversalNeeded; - } - if (what & eMatrixChanged) { - if (layer->setMatrix(s.matrix)) - flags |= eTraversalNeeded; - } - if (what & eTransparentRegionChanged) { - if (layer->setTransparentRegionHint(s.transparentRegion)) - flags |= eTraversalNeeded; + sp<LayerBaseClient> layer(client->getLayerUser(s.surface)); + if (layer != 0) { + const uint32_t what = s.what; + if (what & ePositionChanged) { + if (layer->setPosition(s.x, s.y)) + flags |= eTraversalNeeded; + } + if (what & eLayerChanged) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setLayer(s.z)) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; } - if (what & eVisibilityChanged) { - if (layer->setFlags(s.flags, s.mask)) - flags |= eTraversalNeeded; + } + if (what & eSizeChanged) { + if (layer->setSize(s.w, s.h)) { + flags |= eTraversalNeeded; + mResizeTransationPending = true; } } + if (what & eAlphaChanged) { + if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) + flags |= eTraversalNeeded; + } + if (what & eMatrixChanged) { + if (layer->setMatrix(s.matrix)) + flags |= eTraversalNeeded; + } + if (what & eTransparentRegionChanged) { + if (layer->setTransparentRegionHint(s.transparentRegion)) + flags |= eTraversalNeeded; + } + if (what & eVisibilityChanged) { + if (layer->setFlags(s.flags, s.mask)) + flags |= eTraversalNeeded; + } } - if (flags) { - setTransactionFlags(flags); - } - return NO_ERROR; + return flags; } void SurfaceFlinger::screenReleased(int dpy) @@ -1464,7 +1488,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) const size_t SIZE = 4096; char buffer[SIZE]; String8 result; - if (!mDump.checkCalling()) { + + if (!PermissionCache::checkCallingPermission(sDump)) { snprintf(buffer, SIZE, "Permission Denial: " "can't dump SurfaceFlinger from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), @@ -1583,8 +1608,7 @@ status_t SurfaceFlinger::onTransact( { switch (code) { case CREATE_CONNECTION: - case OPEN_GLOBAL_TRANSACTION: - case CLOSE_GLOBAL_TRANSACTION: + case SET_TRANSACTION_STATE: case SET_ORIENTATION: case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: @@ -1596,7 +1620,8 @@ status_t SurfaceFlinger::onTransact( IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); - if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) { + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) { LOGE("Permission Denial: " "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; @@ -1609,7 +1634,8 @@ status_t SurfaceFlinger::onTransact( IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); - if ((uid != AID_GRAPHICS) && !mReadFramebuffer.check(pid, uid)) { + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) { LOGE("Permission Denial: " "can't read framebuffer pid=%d, uid=%d", pid, uid); return PERMISSION_DENIED; @@ -1621,7 +1647,7 @@ status_t SurfaceFlinger::onTransact( status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { CHECK_INTERFACE(ISurfaceComposer, data, reply); - if (UNLIKELY(!mHardwareTest.checkCalling())) { + if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) { IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); @@ -1766,7 +1792,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() } GLfloat vtx[8]; - const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} }; + const GLfloat texCoords[4][2] = { {0,1}, {0,1-v}, {u,1-v}, {u,1} }; glBindTexture(GL_TEXTURE_2D, tname); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1775,6 +1801,22 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vtx); + /* + * Texture coordinate mapping + * + * u + * 1 +----------+---+ + * | | | | image is inverted + * | V | | w.r.t. the texture + * 1-v +----------+ | coordinates + * | | + * | | + * | | + * 0 +--------------+ + * 0 1 + * + */ + class s_curve_interpolator { const float nbFrames, s, v; public: @@ -1825,7 +1867,12 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked() }; // the full animation is 24 frames - const int nbFrames = 12; + char value[PROPERTY_VALUE_MAX]; + property_get("debug.sf.electron_frames", value, "24"); + int nbFrames = (atoi(value) + 1) >> 1; + if (nbFrames <= 0) // just in case + nbFrames = 24; + s_curve_interpolator itr(nbFrames, 7.5f); s_curve_interpolator itg(nbFrames, 8.0f); s_curve_interpolator itb(nbFrames, 8.5f); @@ -2200,10 +2247,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, // invert everything, b/c glReadPixel() below will invert the FB glViewport(0, 0, sw, sh); glScissor(0, 0, sw, sh); + glEnable(GL_SCISSOR_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - glOrthof(0, hw_w, 0, hw_h, 0, 1); + glOrthof(0, hw_w, hw_h, 0, 0, 1); glMatrixMode(GL_MODELVIEW); // redraw the screen entirely... @@ -2219,6 +2267,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, } // XXX: this is needed on tegra + glEnable(GL_SCISSOR_TEST); glScissor(0, 0, sw, sh); // check for errors and return screen capture @@ -2404,8 +2453,7 @@ status_t Client::onTransact( const int self_pid = getpid(); if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) { // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) + if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger)) { LOGE("Permission Denial: " "can't openGlobalTransaction pid=%d, uid=%d", pid, uid); @@ -2463,9 +2511,6 @@ sp<ISurface> Client::createSurface( status_t Client::destroySurface(SurfaceID sid) { return mFlinger->removeSurface(this, sid); } -status_t Client::setState(int32_t count, const layer_state_t* states) { - return mFlinger->setClientState(this, count, states); -} // --------------------------------------------------------------------------- @@ -2474,11 +2519,14 @@ GraphicBufferAlloc::GraphicBufferAlloc() {} GraphicBufferAlloc::~GraphicBufferAlloc() {} sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) { + PixelFormat format, uint32_t usage, status_t* error) { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); status_t err = graphicBuffer->initCheck(); + *error = err; if (err != 0 || graphicBuffer->handle == 0) { - GraphicBuffer::dumpAllocationsToSystemLog(); + if (err == NO_MEMORY) { + GraphicBuffer::dumpAllocationsToSystemLog(); + } LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " "failed (%s), handle=%p", w, h, strerror(-err), graphicBuffer->handle); |