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

Commit 485df208 authored by Evan Rosky's avatar Evan Rosky
Browse files

Add metadata store to surfaces

This adds a key/value metadata storage mechanism to
surfaces that allows the windowmanager to pass information
to the surfaceflinger frontend.

This then moves the existing metadata (window type and
ownerUID) into this metadata structure.

Bug: 122925737
Test: Phone boots and surfaces fling.
Change-Id: I59739ec5198d815e03811ef659628e45d09721a1
parent ea5b7219
Loading
Loading
Loading
Loading
+67 −25
Original line number Diff line number Diff line
@@ -46,10 +46,9 @@ import android.hardware.display.DisplayedContentSamplingAttributes;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import android.view.Surface.OutOfResourcesException;

@@ -60,6 +59,7 @@ import dalvik.system.CloseGuard;
import libcore.util.NativeAllocationRegistry;

import java.io.Closeable;
import java.nio.ByteBuffer;

/**
 * Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is
@@ -75,7 +75,7 @@ public final class SurfaceControl implements Parcelable {
    private static final String TAG = "SurfaceControl";

    private static native long nativeCreate(SurfaceSession session, String name,
            int w, int h, int format, int flags, long parentObject, int windowType, int ownerUid)
            int w, int h, int format, int flags, long parentObject, Parcel metadata)
            throws OutOfResourcesException;
    private static native long nativeReadFromParcel(Parcel in);
    private static native long nativeCopyFromSurfaceControl(long nativeObject);
@@ -182,6 +182,7 @@ public final class SurfaceControl implements Parcelable {
    private static native void nativeTransferTouchFocus(long transactionObj, IBinder fromToken,
            IBinder toToken);
    private static native boolean nativeGetProtectedContentSupport();
    private static native void nativeSetMetadata(long transactionObj, int key, Parcel data);

    private final CloseGuard mCloseGuard = CloseGuard.get();
    private String mName;
@@ -412,6 +413,18 @@ public final class SurfaceControl implements Parcelable {
        assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject));
    }

    /**
     * owner UID.
     * @hide
     */
    public static final int METADATA_OWNER_UID = 1;

    /**
     * Window type as per {@link WindowManager.LayoutParams}.
     * @hide
     */
    public static final int METADATA_WINDOW_TYPE = 2;

    /**
     * Builder class for {@link SurfaceControl} objects.
     */
@@ -423,8 +436,7 @@ public final class SurfaceControl implements Parcelable {
        private int mFormat = PixelFormat.OPAQUE;
        private String mName;
        private SurfaceControl mParent;
        private int mWindowType = -1;
        private int mOwnerUid = -1;
        private SparseIntArray mMetadata;

        /**
         * Begin building a SurfaceControl with a given {@link SurfaceSession}.
@@ -455,8 +467,8 @@ public final class SurfaceControl implements Parcelable {
                throw new IllegalArgumentException(
                        "Only buffer layers can set a valid buffer size.");
            }
            return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat,
                    mFlags, mParent, mWindowType, mOwnerUid);
            return new SurfaceControl(
                    mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);
        }

        /**
@@ -581,23 +593,17 @@ public final class SurfaceControl implements Parcelable {
        }

        /**
         * Set surface metadata.
         * Sets a metadata int.
         *
         * Currently these are window-types as per {@link WindowManager.LayoutParams} and
         * owner UIDs. Child surfaces inherit their parents
         * metadata so only the WindowManager needs to set this on root Surfaces.
         *
         * @param windowType A window-type
         * @param ownerUid UID of the window owner.
         * @param key metadata key
         * @param data associated data
         * @hide
         */
        public Builder setMetadata(int windowType, int ownerUid) {
            if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
                throw new UnsupportedOperationException(
                        "It only makes sense to set Surface metadata from the WindowManager");
        public Builder setMetadata(int key, int data) {
            if (mMetadata == null) {
                mMetadata = new SparseIntArray();
            }
            mWindowType = windowType;
            mOwnerUid = ownerUid;
            mMetadata.put(key, data);
            return this;
        }

@@ -682,13 +688,12 @@ public final class SurfaceControl implements Parcelable {
     * @param h The surface initial height.
     * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
     * in the creation flags.
     * @param windowType The type of the window as specified in WindowManager.java.
     * @param ownerUid A unique per-app ID.
     * @param metadata Initial metadata.
     *
     * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
     */
    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
            SurfaceControl parent, int windowType, int ownerUid)
            SurfaceControl parent, SparseIntArray metadata)
                    throws OutOfResourcesException, IllegalArgumentException {
        if (name == null) {
            throw new IllegalArgumentException("name must not be null");
@@ -706,8 +711,21 @@ public final class SurfaceControl implements Parcelable {
        mName = name;
        mWidth = w;
        mHeight = h;
        Parcel metaParcel = Parcel.obtain();
        try {
            if (metadata != null && metadata.size() > 0) {
                metaParcel.writeInt(metadata.size());
                for (int i = 0; i < metadata.size(); ++i) {
                    metaParcel.writeInt(metadata.keyAt(i));
                    metaParcel.writeByteArray(
                            ByteBuffer.allocate(4).putInt(metadata.valueAt(i)).array());
                }
            }
            mNativeObject = nativeCreate(session, name, w, h, format, flags,
            parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
                    parent != null ? parent.mNativeObject : 0, metaParcel);
        } finally {
            metaParcel.recycle();
        }
        if (mNativeObject == 0) {
            throw new OutOfResourcesException(
                    "Couldn't allocate SurfaceControl native object");
@@ -2325,6 +2343,30 @@ public final class SurfaceControl implements Parcelable {
            return this;
        }

        /**
         * Sets an arbitrary piece of metadata on the surface. This is a helper for int data.
         * @hide
         */
        public Transaction setMetadata(int key, int data) {
            Parcel parcel = Parcel.obtain();
            parcel.writeInt(data);
            try {
                setMetadata(key, parcel);
            } finally {
                parcel.recycle();
            }
            return this;
        }

        /**
         * Sets an arbitrary piece of metadata on the surface.
         * @hide
         */
        public Transaction setMetadata(int key, Parcel data) {
            nativeSetMetadata(mNativeObject, key, data);
            return this;
        }

        /**
         * Merge the other transaction into this transaction, clearing the
         * other transaction as if it had been applied.
+37 −3
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ static jlong nativeGetNativeTransactionFinalizer(JNIEnv* env, jclass clazz) {

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
        jint windowType, jint ownerUid) {
        jobject metadataParcel) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client;
    if (sessionObj != NULL) {
@@ -134,8 +134,18 @@ static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
    }
    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    sp<SurfaceControl> surface;
    LayerMetadata metadata;
    Parcel* parcel = parcelForJavaObject(env, metadataParcel);
    if (parcel && !parcel->objectsCount()) {
        status_t err = metadata.readFromParcel(parcel);
        if (err != NO_ERROR) {
          jniThrowException(env, "java/lang/IllegalArgumentException",
                            "Metadata parcel has wrong format");
        }
    }

    status_t err = client->createSurfaceChecked(
            String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
            String8(name.c_str()), w, h, format, &surface, flags, parent, std::move(metadata));
    if (err == NAME_NOT_FOUND) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return 0;
@@ -377,6 +387,28 @@ static void nativeTransferTouchFocus(JNIEnv* env, jclass clazz, jlong transactio
    transaction->transferTouchFocus(fromToken, toToken);
}

static void nativeSetMetadata(JNIEnv* env, jclass clazz, jlong transactionObj,
        jlong nativeObject, jint id, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (!parcel) {
        jniThrowNullPointerException(env, "attribute data");
        return;
    }
    if (parcel->objectsCount()) {
        jniThrowException(env, "java/lang/RuntimeException",
                "Tried to marshall a Parcel that contained Binder objects.");
        return;
    }

    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);

    std::vector<uint8_t> byteData(parcel->dataSize());
    memcpy(byteData.data(), parcel->data(), parcel->dataSize());

    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
    transaction->setMetadata(ctrl, id, std::move(byteData));
}

static void nativeSetColor(JNIEnv* env, jclass clazz, jlong transactionObj,
        jlong nativeObject, jfloatArray fColor) {
    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -981,7 +1013,7 @@ static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
// ----------------------------------------------------------------------------

static const JNINativeMethod sSurfaceControlMethods[] = {
    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIIIJII)J",
    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIIIJLandroid/os/Parcel;)J",
            (void*)nativeCreate },
    {"nativeReadFromParcel", "(Landroid/os/Parcel;)J",
            (void*)nativeReadFromParcel },
@@ -1099,6 +1131,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeSetInputWindowInfo },
    {"nativeTransferTouchFocus", "(JLandroid/os/IBinder;Landroid/os/IBinder;)V",
            (void*)nativeTransferTouchFocus },
    {"nativeSetMetadata", "(JILandroid/os/Parcel;)V",
            (void*)nativeSetMetadata },
    {"nativeGetDisplayedContentSamplingAttributes",
            "(Landroid/os/IBinder;)Landroid/hardware/display/DisplayedContentSamplingAttributes;",
            (void*)nativeGetDisplayedContentSamplingAttributes },
+5 −1
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.server.wm;

import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;

import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
@@ -68,7 +71,8 @@ class AppWindowThumbnail implements Animatable {
                .setName("thumbnail anim: " + appToken.toString())
                .setBufferSize(mWidth, mHeight)
                .setFormat(PixelFormat.TRANSLUCENT)
                .setMetadata(appToken.windowType,
                .setMetadata(METADATA_WINDOW_TYPE, appToken.windowType)
                .setMetadata(METADATA_OWNER_UID,
                        window != null ? window.mOwnerUid : Binder.getCallingUid())
                .build();

+4 −2
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.wm;

import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;

import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -35,7 +37,6 @@ import android.os.IBinder;
import android.os.Trace;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowContentFrameStats;
@@ -103,7 +104,8 @@ class WindowSurfaceController {
                .setBufferSize(w, h)
                .setFormat(format)
                .setFlags(flags)
                .setMetadata(windowType, ownerUid);
                .setMetadata(METADATA_WINDOW_TYPE, windowType)
                .setMetadata(METADATA_OWNER_UID, ownerUid);
        mSurfaceControl = b.build();
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }