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

Commit c767fd2b authored by chaviw's avatar chaviw
Browse files

Added client requests for ImpressionAttestation

Since the ImpressionAttestation requests will be from outside the
system, exposed some methods in IWindowManager and IWindowSession to
allow apps to generate the impression token and allow the ads services
to validate the token.

Most of the methods are passthroughs to ExtServices since client apps
cannot directly call into ExtServices

For the generateImpressionToken method, WindowManager will look up the
information about the window to find it's location in the display. It
will then update the bounds passed in so they are in screen space
instead of window space. WindowManager will take the screenshot, using
the uid from the window session, and send the screenshot to ExtServices.
That's where the hash and token will be generated.

Test: Builds
Bug: 155825630
Change-Id: Iacc6c398794d9a302e4d609a16fa99a810369aff
parent b3c1ce5f
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.graphics.Region;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.service.attestation.ImpressionToken;
import android.view.DisplayCutout;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
@@ -760,4 +761,23 @@ interface IWindowManager
     * {@link android.content.pm.PackageManager#getHoldLockToken()}.
     */
    void holdLock(in IBinder token, in int durationMs);

    /**
     * Gets an array of support hashing algorithms that can be used to generate the hash of the
     * screenshot. The String value of one algorithm should be used when requesting to generate
     * the impression attestation token.
     *
     * @return a String array of supported hashing algorithms.
     */
    String[] getSupportedImpressionAlgorithms();

    /**
     * Validate the impression token was generated by the system. The impression token passed in
     * should be the token generated when calling {@link IWindowSession#generateImpressionToken}
     *
     * @param impressionToken The token to verify that it was generated by the system.
     * @return true if the token was generated by the system or false if the token cannot be
     *         verified.
     */
    boolean verifyImpressionToken(in ImpressionToken impressionToken);
}
+13 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.service.attestation.ImpressionToken;
import android.util.MergedConfiguration;
import android.view.DisplayCutout;
import android.view.InputChannel;
@@ -344,4 +345,16 @@ interface IWindowSession {
     *                     window, the system will try to find a new focus target.
     */
    void grantEmbeddedWindowFocus(IWindow window, in IBinder inputToken, boolean grantFocus);

    /**
     * Generates an impression token that can be used to validate whether specific content was on
     * screen.
     *
     * @param window The token for the window where the view to attest is shown.
     * @param boundsInWindow The size and position of the ads view in the window
     * @param hashAlgorithm The String for the hashing algorithm to use based on values returned
     *                      from {@link IWindowManager#getSupportedImpressionAlgorithms()}
     */
    ImpressionToken generateImpressionToken(IWindow window, in Rect boundsInWindow,
            in String hashAlgorithm);
}
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.attestation.ImpressionToken;
import android.util.Log;
import android.util.MergedConfiguration;
import android.window.ClientWindowFrames;
@@ -460,4 +461,10 @@ public class WindowlessWindowManager implements IWindowSession {
    public void grantEmbeddedWindowFocus(IWindow callingWindow, IBinder targetInputToken,
                                         boolean grantFocus) {
    }

    @Override
    public ImpressionToken generateImpressionToken(IWindow window, Rect boundsInWindow,
            String hashAlgorithm) {
        return null;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -5680,4 +5680,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }
        return count;
    }

    MagnificationSpec getMagnificationSpec() {
        return mMagnificationSpec;
    }
}
+85 −1
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.server.wm;

import static android.service.attestation.ImpressionAttestationService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;

import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -29,7 +32,9 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.HardwareBuffer;
import android.os.Binder;
import android.os.Bundle;
@@ -43,6 +48,7 @@ import android.service.attestation.IImpressionAttestationService;
import android.service.attestation.ImpressionAttestationService;
import android.service.attestation.ImpressionToken;
import android.util.Slog;
import android.view.MagnificationSpec;

import com.android.internal.annotations.GuardedBy;

@@ -59,7 +65,8 @@ import java.util.function.BiConsumer;
 * blocking calls into another service.
 */
public class ImpressionAttestationController {
    private static final String TAG = "ImpressionAttestationController";
    private static final String TAG =
            TAG_WITH_CLASS_NAME ? "ImpressionAttestationController" : TAG_WM;
    private static final boolean DEBUG = false;

    private final Object mServiceConnectionLock = new Object();
@@ -81,6 +88,10 @@ public class ImpressionAttestationController {

    private final String mSalt;

    private final float[] mTmpFloat9 = new float[9];
    private final Matrix mTmpMatrix = new Matrix();
    private final RectF mTmpRectF = new RectF();

    private interface Command {
        void run(IImpressionAttestationService service) throws RemoteException;
    }
@@ -150,6 +161,79 @@ public class ImpressionAttestationController {
        return results.getParcelable(ImpressionAttestationService.EXTRA_IMPRESSION_TOKEN);
    }

    /**
     * Calculate the bounds to take the screenshot when generating the impression token. This takes
     * into account window transform, magnification, and display bounds.
     *
     * Call while holding {@link WindowManagerService#mGlobalLock}
     *
     * @param win Window that the impression token is generated for.
     * @param boundsInWindow The bounds passed in about where in the window to take the screenshot.
     * @param outBounds The result of the calculated bounds
     */
    void calculateImpressionTokenBoundsLocked(WindowState win, Rect boundsInWindow,
            Rect outBounds) {
        if (DEBUG) {
            Slog.d(TAG, "calculateImpressionTokenBounds: boundsInWindow=" + boundsInWindow);
        }
        outBounds.set(boundsInWindow);

        DisplayContent displayContent = win.getDisplayContent();
        if (displayContent == null) {
            return;
        }

        // Intersect boundsInWindow with the window to make sure it's not outside the window
        // requesting the token. Offset the window bounds to 0,0 since the boundsInWindow are
        // offset from the window location, not display.
        final Rect windowBounds = new Rect();
        win.getBounds(windowBounds);
        windowBounds.offsetTo(0, 0);
        outBounds.intersectUnchecked(windowBounds);

        if (DEBUG) {
            Slog.d(TAG, "calculateImpressionTokenBounds: boundsIntersectWindow=" + outBounds);
        }

        if (outBounds.isEmpty()) {
            return;
        }

        // Transform the bounds using the window transform in case there's a scale or offset.
        // This allows the bounds to be in display space.
        win.getTransformationMatrix(mTmpFloat9, mTmpMatrix);
        mTmpRectF.set(outBounds);
        mTmpMatrix.mapRect(mTmpRectF, mTmpRectF);
        outBounds.set((int) mTmpRectF.left, (int) mTmpRectF.top, (int) mTmpRectF.right,
                (int) mTmpRectF.bottom);
        if (DEBUG) {
            Slog.d(TAG, "calculateImpressionTokenBounds: boundsInDisplay=" + outBounds);
        }

        // Apply the magnification spec values to the bounds since the content could be magnified
        final MagnificationSpec magSpec = displayContent.getMagnificationSpec();
        if (magSpec != null) {
            outBounds.scale(magSpec.scale);
            outBounds.offset((int) magSpec.offsetX, (int) magSpec.offsetY);
        }

        if (DEBUG) {
            Slog.d(TAG, "calculateImpressionTokenBounds: boundsWithMagnification=" + outBounds);
        }

        if (outBounds.isEmpty()) {
            return;
        }

        // Intersect with the display bounds since it shouldn't take a screenshot of content
        // outside the display since it's not visible to the user.
        final Rect displayBounds = displayContent.getBounds();
        outBounds.intersectUnchecked(displayBounds);
        if (DEBUG) {
            Slog.d(TAG, "calculateImpressionTokenBounds: finalBounds=" + outBounds);
        }
    }

    /**
     * Run a command, starting the service connection if necessary.
     */
Loading