Android - Preventing screen capture and secure windows

   Android has an API FLAG_SECURE to prevent the window contents to be captured. This can be applied to any kind of window controlled by the application and an application could have multiple windows shown simultaneously (each on top of the other). This begs a question as to what happens when FLAG_SECURE is requested only for one of the window and not for dialog windows or vice versa. An application like Netflix might want to enforce security just for playback window and not a dialog showing options etc.

   What happens if the dialog window is in focus? The fact that FLAG_SECURE is associated with a window seems that one could probably skip the check when a non secure window (Dialog) is in focus. This is a concern for application developers. Turns out this is not possible and any attempt to capture would fail (irrespective of the security of the focus window). This is because the framework checks for all windows of the current display and bails out when even one of them is requested to be secure.

    // if we have secure windows on this display, never allow the screen capture
    // unless the producer interface is local (i.e.: we can take a screenshot for
    // ourselves).
    if (!producer->asBinder()->localBinder()) {
        Mutex::Autolock _l(mStateLock);
        sp<const DisplayDevice> hw(getDisplayDevice(display));
        if (hw->getSecureLayerVisible()) {
            ALOGW("FB is protected: PERMISSION_DENIED");
            return PERMISSION_DENIED;
        }
    }


    void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
        mVisibleLayersSortedByZ = layers;
        mSecureLayerVisible = false;
        size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) { 
            const sp<Layer>& layer(layers[i]);
            if (layer->isSecure()) {
                mSecureLayerVisible = true;
            }
        }
    }

    The API is exposed at the level of a Window translates into a property of a Layer. The Z order of the Layers is updated based on run time changes and security is updated accordingly. But what happens if an application has multiple activities and the second activity's non-secure window hides the first activity's secure window? Technically, this is not a concern as the secure window's content can't be seen or captured. Turns out, the framework indeed allows the capture of the second activity's window. The first activity's window doesn't even have to be rendered as it is not going to be visible. Screen capture works as none of the layers (including the second activity's window) are marked as secure.

    type   |  handle  | hint | flag | tr | blnd |  format     |     source crop(l,t,r,b)       |           frame        |      dirtyRect         |  name 
------------+----------+----------+----------+----+-------+----------+-----------------------------------+---------------------------+-------------------
      GLES | b8113398 | 0002 | 0000 | 00 | 0100 | RGBA_8888   |      0,      0,    768,   1280 |    0,    0,  768, 1280 | [    0,    0,    0,    0] | com.sample.newapp.pro/com.sample.newapp.SecondActivity


   Framework also handles the case when second activity's non-secure window is totally translucent revealing the first activity's secure window despite being on top of it. Attempt to capture the screen contents in this case would fail.

    type   |  handle  | hint | flag | tr | blnd |  format     |     source crop(l,t,r,b)       |           frame        |      dirtyRect         |  name 
------------+----------+----------+----------+----+-------+----------+-----------------------------------+---------------------------+-------------------
       HWC | b813bea8 | 0002 | 0000 | 00 | 0100 | RGBA_8888   |      0,      0,    768,   1280 |    0,    0,  768, 1280 | [    0,    0,    0,    0] | com.sample.newapp.pro/com.sample.newapp.FirstActivity

       HWC | b8118fe8 | 0002 | 0000 | 00 | 0105 | RGBA_8888   |      0,      0,    768,   1280 |    0,    0,  768, 1280 | [    0,    0,    0,    0] | com.sample.newapp.pro/com.sample.newapp.SecondActivity


 The fact that the second activity's window is translucent requires for the first activity's window to be rendered and passed on to SurfaceFlinger. In this case, the Layer corresponding to first activity's window is marked as secure and this blocks the screen capture.

No comments: