From dd3cb84cfbe8068790c6233b5829fae9c4a0ee93 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Fri, 19 Oct 2012 18:19:11 -0700 Subject: [PATCH] SurfaceFlinger: add support for secure displays This change adds support for displays that are not allowed to display surfaces with the eSecure flag set. All non-virtual displays are considered secure, while virtual displays have their secure-ness specified at creation time. Bug: 7368436 Change-Id: I81ad535d2d1e5a7ff78269017e85b111f0098500 --- include/gui/ISurfaceComposer.h | 6 +-- include/gui/SurfaceComposerClient.h | 2 +- include/ui/DisplayInfo.h | 3 +- libs/gui/ISurfaceComposer.cpp | 20 ++------ libs/gui/SurfaceComposerClient.cpp | 12 +++-- services/surfaceflinger/DisplayDevice.cpp | 9 ++-- services/surfaceflinger/DisplayDevice.h | 9 +++- services/surfaceflinger/Layer.cpp | 8 +++- services/surfaceflinger/LayerScreenshot.cpp | 21 ++++++++- services/surfaceflinger/LayerScreenshot.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 52 ++++++++------------- services/surfaceflinger/SurfaceFlinger.h | 5 +- 12 files changed, 81 insertions(+), 69 deletions(-) diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 002aafc52..6500ad584 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -69,7 +69,8 @@ public: /* create a display * requires ACCESS_SURFACE_FLINGER permission. */ - virtual sp createDisplay(const String8& displayName) = 0; + virtual sp createDisplay(const String8& displayName, + bool secure) = 0; /* get the token for the existing default displays. possible values * for id are eDisplayIdMain and eDisplayIdHdmi. @@ -108,9 +109,6 @@ public: /* returns information about a display * intended to be used to get information about built-in displays */ virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info) = 0; - - /* connects to an external display */ - virtual void connectDisplay(const sp& display) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 21d16a947..ae5d69a11 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -86,7 +86,7 @@ public: ); //! Create a display - static sp createDisplay(const String8& displayName); + static sp createDisplay(const String8& displayName, bool secure); //! Get the token for the existing default displays. //! Possible values for id are eDisplayIdMain and eDisplayIdHdmi. diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h index c7dc35484..c3a4d6bea 100644 --- a/include/ui/DisplayInfo.h +++ b/include/ui/DisplayInfo.h @@ -32,7 +32,8 @@ struct DisplayInfo { float fps; float density; uint8_t orientation; - uint8_t reserved[3]; + bool secure; + uint8_t reserved[2]; // TODO: this needs to go away (currently needed only by webkit) PixelFormatInfo pixelFormatInfo; }; diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index aff1b45ff..85a94882e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -179,11 +179,12 @@ public: return result; } - virtual sp createDisplay(const String8& displayName) + virtual sp createDisplay(const String8& displayName, bool secure) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeString8(displayName); + data.writeInt32(secure ? 1 : 0); remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply); return reply.readStrongBinder(); } @@ -222,14 +223,6 @@ public: memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo)); return reply.readInt32(); } - - - virtual void connectDisplay(const sp& display) { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display->asBinder()); - remote()->transact(BnSurfaceComposer::CONNECT_DISPLAY, data, &reply); - } }; IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer"); @@ -309,7 +302,8 @@ status_t BnSurfaceComposer::onTransact( case CREATE_DISPLAY: { CHECK_INTERFACE(ISurfaceComposer, data, reply); String8 displayName = data.readString8(); - sp display(createDisplay(displayName)); + bool secure = bool(data.readInt32()); + sp display(createDisplay(displayName, secure)); reply->writeStrongBinder(display); return NO_ERROR; } break; @@ -338,12 +332,6 @@ status_t BnSurfaceComposer::onTransact( memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo)); reply->writeInt32(result); } break; - case CONNECT_DISPLAY: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp surfaceTexture = - interface_cast(data.readStrongBinder()); - connectDisplay(surfaceTexture); - } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8586ed218..80dd6ee96 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -131,7 +131,7 @@ class Composer : public Singleton DisplayState& getDisplayStateLocked(const sp& token); public: - sp createDisplay(const String8& displayName); + sp createDisplay(const String8& displayName, bool secure); sp getBuiltInDisplay(int32_t id); status_t setPosition(const sp& client, SurfaceID id, @@ -175,8 +175,9 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer); // --------------------------------------------------------------------------- -sp Composer::createDisplay(const String8& displayName) { - return ComposerService::getComposerService()->createDisplay(displayName); +sp Composer::createDisplay(const String8& displayName, bool secure) { + return ComposerService::getComposerService()->createDisplay(displayName, + secure); } sp Composer::getBuiltInDisplay(int32_t id) { @@ -459,8 +460,9 @@ sp SurfaceComposerClient::createSurface( return result; } -sp SurfaceComposerClient::createDisplay(const String8& displayName) { - return Composer::getInstance().createDisplay(displayName); +sp SurfaceComposerClient::createDisplay(const String8& displayName, + bool secure) { + return Composer::getInstance().createDisplay(displayName, secure); } sp SurfaceComposerClient::getBuiltInDisplay(int32_t id) { diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 40631ee35..ce98b6769 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -69,7 +69,9 @@ void checkGLErrors() DisplayDevice::DisplayDevice( const sp& flinger, - DisplayType type, const wp& displayToken, + DisplayType type, + bool isSecure, + const wp& displayToken, const sp& nativeWindow, const sp& framebufferSurface, EGLConfig config) @@ -83,6 +85,7 @@ DisplayDevice::DisplayDevice( mDisplayWidth(), mDisplayHeight(), mFormat(), mFlags(), mPageFlipCount(), + mIsSecure(isSecure), mSecureLayerVisible(false), mScreenAcquired(false), mLayerStack(0), @@ -431,13 +434,13 @@ void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const { snprintf(buffer, SIZE, "+ DisplayDevice: %s\n" " type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " - "flips=%u, secure=%d, acquired=%d, numLayers=%u\n" + "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n" " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], " "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", mDisplayName.string(), mType, mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(), mOrientation, tr.getType(), getPageFlipCount(), - mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(), + mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(), mViewport.left, mViewport.top, mViewport.right, mViewport.bottom, mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, tr[0][0], tr[1][0], tr[2][0], diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 058680b8a..d6da4227f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -67,7 +67,9 @@ public: DisplayDevice( const sp& flinger, - DisplayType type, const wp& displayToken, + DisplayType type, + bool isSecure, + const wp& displayToken, const sp& nativeWindow, const sp& framebufferSurface, EGLConfig config); @@ -78,6 +80,10 @@ public: // when an non existing id is requested bool isValid() const; + // isSecure indicates whether this display can be trusted to display + // secure surfaces. + bool isSecure() const { return mIsSecure; } + // Flip the front and back buffers if the back buffer is "dirty". Might // be instantaneous, might involve copying the frame buffer around. void flip(const Region& dirty) const; @@ -167,6 +173,7 @@ private: uint32_t mFlags; mutable uint32_t mPageFlipCount; String8 mDisplayName; + bool mIsSecure; /* * Can only accessed from the main thread, these members diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c2da23888..064f68963 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -253,6 +253,10 @@ void Layer::setGeometry( layer.setSkip(true); } + if (isSecure() && !hw->isSecure()) { + layer.setSkip(true); + } + /* * Transformations are applied in this order: * 1) buffer orientation/flip/mirror @@ -342,7 +346,9 @@ void Layer::onDraw(const sp& hw, const Region& clip) const // is probably going to have something visibly wrong. } - if (!isProtected()) { + bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); + + if (!blackOutLayer) { // TODO: we could be more subtle with isFixedSize() const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp index 0fd744fdd..f8009b330 100644 --- a/services/surfaceflinger/LayerScreenshot.cpp +++ b/services/surfaceflinger/LayerScreenshot.cpp @@ -37,7 +37,7 @@ namespace android { LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, const sp& client) : LayerBaseClient(flinger, client), - mTextureName(0), mFlinger(flinger) + mTextureName(0), mFlinger(flinger), mIsSecure(false) { } @@ -56,6 +56,10 @@ status_t LayerScreenshot::captureLocked(int32_t layerStack) { return result; } initTexture(u, v); + + // Currently screenshot always comes from the default display + mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible(); + return NO_ERROR; } @@ -66,6 +70,10 @@ status_t LayerScreenshot::capture() { return result; } initTexture(u, v); + + // Currently screenshot always comes from the default display + mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible(); + return NO_ERROR; } @@ -84,6 +92,10 @@ void LayerScreenshot::initStates(uint32_t w, uint32_t h, uint32_t flags) { if (!(flags & ISurfaceComposerClient::eHidden)) { capture(); } + if (flags & ISurfaceComposerClient::eSecure) { + ALOGW("ignoring surface flag eSecure - LayerScreenshot is considered " + "secure iff it captures the contents of a secure surface."); + } } uint32_t LayerScreenshot::doTransaction(uint32_t flags) @@ -125,6 +137,11 @@ void LayerScreenshot::onDraw(const sp& hw, const Region& cl glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } + GLuint texName = mTextureName; + if (isSecure() && !hw->isSecure()) { + texName = mFlinger->getProtectedTexName(); + } + LayerMesh mesh; computeGeometry(hw, &mesh); @@ -133,7 +150,7 @@ void LayerScreenshot::onDraw(const sp& hw, const Region& cl glDisable(GL_TEXTURE_EXTERNAL_OES); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, mTextureName); + glBindTexture(GL_TEXTURE_2D, texName); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h index 7807ffc5b..38cbd88fa 100644 --- a/services/surfaceflinger/LayerScreenshot.h +++ b/services/surfaceflinger/LayerScreenshot.h @@ -34,6 +34,7 @@ class LayerScreenshot : public LayerBaseClient GLuint mTextureName; GLfloat mTexCoords[8]; sp mFlinger; + bool mIsSecure; public: LayerScreenshot(SurfaceFlinger* flinger, const sp& client); virtual ~LayerScreenshot(); @@ -44,7 +45,7 @@ public: virtual uint32_t doTransaction(uint32_t flags); virtual void onDraw(const sp& hw, const Region& clip) const; virtual bool isOpaque() const { return false; } - virtual bool isSecure() const { return false; } + virtual bool isSecure() const { return mIsSecure; } virtual bool isProtectedByApp() const { return false; } virtual bool isProtectedByDRM() const { return false; } virtual const char* getTypeId() const { return "LayerScreenshot"; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8e569bea2..38e02f1b8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,7 +163,8 @@ sp SurfaceFlinger::createConnection() return bclient; } -sp SurfaceFlinger::createDisplay(const String8& displayName) +sp SurfaceFlinger::createDisplay(const String8& displayName, + bool secure) { class DisplayToken : public BBinder { sp flinger; @@ -184,6 +185,7 @@ sp SurfaceFlinger::createDisplay(const String8& displayName) Mutex::Autolock _l(mStateLock); DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL); info.displayName = displayName; + info.isSecure = secure; mCurrentState.displays.add(token, info); return token; @@ -485,12 +487,14 @@ status_t SurfaceFlinger::readyToRun() // set-up the displays that are already connected if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) { + // All non-virtual displays are currently considered secure. + bool isSecure = true; mCurrentState.displays.add(token, DisplayDeviceState(type)); sp fbs = new FramebufferSurface(*mHwc, i); sp stc = new SurfaceTextureClient( static_cast< sp >(fbs->getBufferQueue())); sp hw = new DisplayDevice(this, - type, token, stc, fbs, mEGLConfig); + type, isSecure, token, stc, fbs, mEGLConfig); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always @@ -666,6 +670,10 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& display, DisplayInfo* info->xdpi = xdpi; info->ydpi = ydpi; info->fps = float(1e9 / hwc.getRefreshPeriod(type)); + + // All non-virtual displays are currently considered secure. + info->secure = true; + return NO_ERROR; } @@ -675,34 +683,6 @@ sp SurfaceFlinger::createDisplayEventConnection() { return mEventThread->createEventConnection(); } -void SurfaceFlinger::connectDisplay(const sp& surface) { - - sp token; - { // scope for the lock - Mutex::Autolock _l(mStateLock); - token = mExtDisplayToken; - } - - if (token == 0) { - token = createDisplay(String8("Display from connectDisplay")); - } - - { // scope for the lock - Mutex::Autolock _l(mStateLock); - if (surface == 0) { - // release our current display. we're guarantee to have - // a reference to it (token), while we hold the lock - mExtDisplayToken = 0; - } else { - mExtDisplayToken = token; - } - - DisplayDeviceState& info(mCurrentState.displays.editValueFor(token)); - info.surface = surface; - setTransactionFlags(eDisplayTransactionNeeded); - } -} - // ---------------------------------------------------------------------------- void SurfaceFlinger::waitForEvent() { @@ -1183,6 +1163,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) for (size_t i=0 ; i fbs; sp stc; @@ -1193,21 +1174,28 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) "surface is provided (%p), ignoring it", state.surface.get()); + // All non-virtual displays are currently considered + // secure. + isSecure = true; + // for supported (by hwc) displays we provide our // own rendering surface fbs = new FramebufferSurface(*mHwc, state.type); stc = new SurfaceTextureClient( - static_cast< sp >(fbs->getBufferQueue())); + static_cast< sp >( + fbs->getBufferQueue())); } else { if (state.surface != NULL) { stc = new SurfaceTextureClient(state.surface); } + isSecure = state.isSecure; } const wp& display(curr.keyAt(i)); if (stc != NULL) { sp hw = new DisplayDevice(this, - state.type, display, stc, fbs, mEGLConfig); + state.type, isSecure, display, stc, fbs, + mEGLConfig); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index de9716781..b0d3bacf5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -140,6 +140,7 @@ private: friend class LayerBase; friend class LayerBaseClient; friend class Layer; + friend class LayerScreenshot; // We're reference counted, never destroy SurfaceFlinger directly virtual ~SurfaceFlinger(); @@ -168,6 +169,7 @@ private: Rect frame; uint8_t orientation; String8 displayName; + bool isSecure; }; struct State { @@ -187,7 +189,7 @@ private: */ virtual sp createConnection(); virtual sp createGraphicBufferAlloc(); - virtual sp createDisplay(const String8& displayName); + virtual sp createDisplay(const String8& displayName, bool secure); virtual sp getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags); @@ -204,7 +206,6 @@ private: // called when screen is turning back on virtual void unblank(const sp& display); virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info); - virtual void connectDisplay(const sp& display); /* ------------------------------------------------------------------------ * DeathRecipient interface