Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e5c2b59 authored by Robert Carr's avatar Robert Carr Committed by android-build-merger
Browse files

Merge "SurfaceFlinger: Fixes around rotation and cropping." into pi-dev

am: 855087f3

Change-Id: Ic7aa9c5a4a021cece8d112e99d0367c7a4e85dd8
parents 83174493 855087f3
Loading
Loading
Loading
Loading
+22 −9
Original line number Diff line number Diff line
@@ -345,20 +345,25 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
        win.intersect(s.crop, &win);
    }

    Rect bounds = win;
    const auto& p = mDrawingParent.promote();
    FloatRect floatWin = win.toFloatRect();
    FloatRect parentBounds = floatWin;
    if (p != nullptr) {
        // Look in computeScreenBounds recursive call for explanation of
        // why we pass false here.
        bounds = p->computeScreenBounds(false /* reduceTransparentRegion */);
        // We pass an empty Region here for reasons mirroring that of the case described in
        // the computeScreenBounds reduceTransparentRegion=false case.
        parentBounds = p->computeBounds(Region());
    }

    Transform t = getTransform();
    Transform t = s.active.transform;

    FloatRect floatWin = win.toFloatRect();
    if (p != nullptr) {

    if (p != nullptr || !s.finalCrop.isEmpty()) {
        floatWin = t.transform(floatWin);
        floatWin = floatWin.intersect(bounds.toFloatRect());
        floatWin = floatWin.intersect(parentBounds);

        if (!s.finalCrop.isEmpty()) {
            floatWin = floatWin.intersect(s.finalCrop.toFloatRect());
        }
        floatWin = t.inverse().transform(floatWin);
    }

@@ -1249,7 +1254,15 @@ bool Layer::setColor(const half3& color) {
    return true;
}

bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
        bool allowNonRectPreservingTransforms) {
    Transform t;
    t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);

    if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
        ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
        return false;
    }
    mCurrentState.sequence++;
    mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
    mCurrentState.modified = true;
+1 −1
Original line number Diff line number Diff line
@@ -258,7 +258,7 @@ public:
    // Set a 2x2 transformation matrix on the layer. This transform
    // will be applied after parent transforms, but before any final
    // producer specified transform.
    bool setMatrix(const layer_state_t::matrix22_t& matrix);
    bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms);

    // This second set of geometry attributes are controlled by
    // setGeometryAppliesWithResize, and their default mode is to be
+32 −7
Original line number Diff line number Diff line
@@ -3342,6 +3342,18 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
    return flags;
}

bool callingThreadHasUnscopedSurfaceFlingerAccess() {
    IPCThreadState* ipc = IPCThreadState::self();
    const int pid = ipc->getCallingPid();
    const int uid = ipc->getCallingUid();

    if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
            !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
        return false;
    }
    return true;
}

uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) {
    const layer_state_t& s = composerState.state;
    sp<Client> client(static_cast<Client*>(composerState.client.get()));
@@ -3423,7 +3435,22 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState
            flags |= eTraversalNeeded;
    }
    if (what & layer_state_t::eMatrixChanged) {
        if (layer->setMatrix(s.matrix))
        // TODO: b/109894387
        //
        // SurfaceFlinger's renderer is not prepared to handle cropping in the face of arbitrary
        // rotation. To see the problem observe that if we have a square parent, and a child
        // of the same size, then we rotate the child 45 degrees around it's center, the child
        // must now be cropped to a non rectangular 8 sided region.
        //
        // Of course we can fix this in the future. For now, we are lucky, SurfaceControl is
        // private API, and the WindowManager only uses rotation in one case, which is on a top
        // level layer in which cropping is not an issue.
        //
        // However given that abuse of rotation matrices could lead to surfaces extending outside
        // of cropped areas, we need to prevent non-root clients without permission ACCESS_SURFACE_FLINGER
        // (a.k.a. everyone except WindowManager and tests) from setting non rectangle preserving
        // transformations.
        if (layer->setMatrix(s.matrix, callingThreadHasUnscopedSurfaceFlingerAccess()))
            flags |= eTraversalNeeded;
    }
    if (what & layer_state_t::eTransparentRegionChanged) {
@@ -4440,12 +4467,10 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
        case INJECT_VSYNC:
        {
            // codes that require permission check
            if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
                IPCThreadState* ipc = IPCThreadState::self();
            const int pid = ipc->getCallingPid();
            const int uid = ipc->getCallingUid();
            if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
                    !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
                ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
                        ipc->getCallingPid(), ipc->getCallingUid());
                return PERMISSION_DENIED;
            }
            break;