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

Commit 9fc390e7 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Add mechanism to trace specific sf tx changes without rebuilding fw" into main

parents 1d751f10 52cfba0d
Loading
Loading
Loading
Loading
+111 −25
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -796,7 +797,7 @@ public final class SurfaceControl implements Parcelable {
        if (nativeObject != 0) {
            // Only add valid surface controls to the registry. This is called at the end of this
            // method since its information is dumped if the process threshold is reached.
            addToRegistry();
            SurfaceControlRegistry.getProcessInstance().add(this);
        }
    }

@@ -1501,7 +1502,7 @@ public final class SurfaceControl implements Parcelable {
            if (mCloseGuard != null) {
                mCloseGuard.warnIfOpen();
            }
            removeFromRegistry();
            SurfaceControlRegistry.getProcessInstance().remove(this);
        } finally {
            super.finalize();
        }
@@ -1519,6 +1520,10 @@ public final class SurfaceControl implements Parcelable {
     */
    public void release() {
        if (mNativeObject != 0) {
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "release", null, this, null);
            }
            mFreeNativeResources.run();
            mNativeObject = 0;
            mNativeHandle = 0;
@@ -1532,7 +1537,7 @@ public final class SurfaceControl implements Parcelable {
                    mChoreographer = null;
                }
            }
            removeFromRegistry();
            SurfaceControlRegistry.getProcessInstance().remove(this);
        }
    }

@@ -2765,8 +2770,10 @@ public final class SurfaceControl implements Parcelable {

        private Transaction(long nativeObject) {
            mNativeObject = nativeObject;
            mFreeNativeResources =
                    sRegistry.registerNativeAllocation(this, mNativeObject);
            mFreeNativeResources = sRegistry.registerNativeAllocation(this, mNativeObject);
            if (!SurfaceControlRegistry.sCallStackDebuggingInitialized) {
                SurfaceControlRegistry.initializeCallStackDebugging();
            }
        }

        private Transaction(Parcel in) {
@@ -2845,6 +2852,11 @@ public final class SurfaceControl implements Parcelable {
            applyResizedSurfaces();
            notifyReparentedSurfaces();
            nativeApplyTransaction(mNativeObject, sync, oneWay);

            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "apply", this, null, null);
            }
        }

        /**
@@ -2920,6 +2932,10 @@ public final class SurfaceControl implements Parcelable {
        @UnsupportedAppUsage
        public Transaction show(SurfaceControl sc) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "show", this, sc, null);
            }
            nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_HIDDEN);
            return this;
        }
@@ -2934,6 +2950,10 @@ public final class SurfaceControl implements Parcelable {
        @UnsupportedAppUsage
        public Transaction hide(SurfaceControl sc) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "hide", this, sc, null);
            }
            nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
            return this;
        }
@@ -2950,6 +2970,10 @@ public final class SurfaceControl implements Parcelable {
        @NonNull
        public Transaction setPosition(@NonNull SurfaceControl sc, float x, float y) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setPosition", this, sc, "x=" + x + " y=" + y);
            }
            nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
            return this;
        }
@@ -2968,6 +2992,10 @@ public final class SurfaceControl implements Parcelable {
            checkPreconditions(sc);
            Preconditions.checkArgument(scaleX >= 0, "Negative value passed in for scaleX");
            Preconditions.checkArgument(scaleY >= 0, "Negative value passed in for scaleY");
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setScale", this, sc, "sx=" + scaleX + " sy=" + scaleY);
            }
            nativeSetScale(mNativeObject, sc.mNativeObject, scaleX, scaleY);
            return this;
        }
@@ -2985,6 +3013,10 @@ public final class SurfaceControl implements Parcelable {
        public Transaction setBufferSize(@NonNull SurfaceControl sc,
                @IntRange(from = 0) int w, @IntRange(from = 0) int h) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setBufferSize", this, sc, "w=" + w + " h=" + h);
            }
            mResizedSurfaces.put(sc, new Point(w, h));
            return this;
        }
@@ -3005,6 +3037,10 @@ public final class SurfaceControl implements Parcelable {
        public Transaction setFixedTransformHint(@NonNull SurfaceControl sc,
                       @Surface.Rotation int transformHint) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setFixedTransformHint", this, sc, "hint=" + transformHint);
            }
            nativeSetFixedTransformHint(mNativeObject, sc.mNativeObject, transformHint);
            return this;
        }
@@ -3018,6 +3054,10 @@ public final class SurfaceControl implements Parcelable {
        @NonNull
        public Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "unsetFixedTransformHint", this, sc, null);
            }
            nativeSetFixedTransformHint(mNativeObject, sc.mNativeObject, -1/* INVALID_ROTATION */);
            return this;
        }
@@ -3035,6 +3075,10 @@ public final class SurfaceControl implements Parcelable {
        public Transaction setLayer(@NonNull SurfaceControl sc,
                @IntRange(from = Integer.MIN_VALUE, to = Integer.MAX_VALUE) int z) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setLayer", this, sc, "z=" + z);
            }
            nativeSetLayer(mNativeObject, sc.mNativeObject, z);
            return this;
        }
@@ -3044,6 +3088,10 @@ public final class SurfaceControl implements Parcelable {
         */
        public Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo, int z) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setRelativeLayer", this, sc, "relTo=" + relativeTo + " z=" + z);
            }
            nativeSetRelativeLayer(mNativeObject, sc.mNativeObject, relativeTo.mNativeObject, z);
            return this;
        }
@@ -3053,6 +3101,10 @@ public final class SurfaceControl implements Parcelable {
         */
        public Transaction setTransparentRegionHint(SurfaceControl sc, Region transparentRegion) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "unsetFixedTransformHint", this, sc, "region=" + transparentRegion);
            }
            nativeSetTransparentRegionHint(mNativeObject,
                    sc.mNativeObject, transparentRegion);
            return this;
@@ -3069,6 +3121,10 @@ public final class SurfaceControl implements Parcelable {
        public Transaction setAlpha(@NonNull SurfaceControl sc,
                @FloatRange(from = 0.0, to = 1.0) float alpha) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setAlpha", this, sc, "alpha=" + alpha);
            }
            nativeSetAlpha(mNativeObject, sc.mNativeObject, alpha);
            return this;
        }
@@ -3124,6 +3180,11 @@ public final class SurfaceControl implements Parcelable {
        public Transaction setMatrix(SurfaceControl sc,
                float dsdx, float dtdx, float dtdy, float dsdy) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setMatrix", this, sc,
                        "dsdx=" + dsdx + " dtdx=" + dtdx + " dtdy=" + dtdy + " dsdy=" + dsdy);
            }
            nativeSetMatrix(mNativeObject, sc.mNativeObject,
                    dsdx, dtdx, dtdy, dsdy);
            return this;
@@ -3189,6 +3250,10 @@ public final class SurfaceControl implements Parcelable {
        @UnsupportedAppUsage
        public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setWindowCrop", this, sc, "crop=" + crop);
            }
            if (crop != null) {
                nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
                        crop.left, crop.top, crop.right, crop.bottom);
@@ -3211,6 +3276,10 @@ public final class SurfaceControl implements Parcelable {
         */
        public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setCrop", this, sc, "crop=" + crop);
            }
            if (crop != null) {
                Preconditions.checkArgument(crop.isValid(), "Crop isn't valid.");
                nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
@@ -3233,6 +3302,10 @@ public final class SurfaceControl implements Parcelable {
         */
        public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setCornerRadius", this, sc, "w=" + width + " h=" + height);
            }
            nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, width, height);
            return this;
        }
@@ -3247,6 +3320,10 @@ public final class SurfaceControl implements Parcelable {
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        public Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setCornerRadius", this, sc, "cornerRadius=" + cornerRadius);
            }
            nativeSetCornerRadius(mNativeObject, sc.mNativeObject, cornerRadius);

            return this;
@@ -3262,6 +3339,10 @@ public final class SurfaceControl implements Parcelable {
         */
        public Transaction setBackgroundBlurRadius(SurfaceControl sc, int radius) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setBackgroundBlurRadius", this, sc, "radius=" + radius);
            }
            nativeSetBackgroundBlurRadius(mNativeObject, sc.mNativeObject, radius);
            return this;
        }
@@ -3318,6 +3399,10 @@ public final class SurfaceControl implements Parcelable {
        public Transaction reparent(@NonNull SurfaceControl sc,
                @Nullable SurfaceControl newParent) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "reparent", this, sc, "newParent=" + newParent);
            }
            long otherObject = 0;
            if (newParent != null) {
                newParent.checkNotReleased();
@@ -3337,6 +3422,11 @@ public final class SurfaceControl implements Parcelable {
        @UnsupportedAppUsage
        public Transaction setColor(SurfaceControl sc, @Size(3) float[] color) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "reparent", this, sc,
                        "r=" + color[0] + " g=" + color[1] + " b=" + color[2]);
            }
            nativeSetColor(mNativeObject, sc.mNativeObject, color);
            return this;
        }
@@ -3347,6 +3437,10 @@ public final class SurfaceControl implements Parcelable {
        */
        public Transaction unsetColor(SurfaceControl sc) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "unsetColor", this, sc, null);
            }
            nativeSetColor(mNativeObject, sc.mNativeObject, INVALID_COLOR);
            return this;
        }
@@ -3358,6 +3452,10 @@ public final class SurfaceControl implements Parcelable {
         */
        public Transaction setSecure(SurfaceControl sc, boolean isSecure) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setSecure", this, sc, "secure=" + isSecure);
            }
            if (isSecure) {
                nativeSetFlags(mNativeObject, sc.mNativeObject, SECURE, SECURE);
            } else {
@@ -3411,6 +3509,10 @@ public final class SurfaceControl implements Parcelable {
        @NonNull
        public Transaction setOpaque(@NonNull SurfaceControl sc, boolean isOpaque) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setOpaque", this, sc, "opaque=" + isOpaque);
            }
            if (isOpaque) {
                nativeSetFlags(mNativeObject, sc.mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE);
            } else {
@@ -3580,6 +3682,10 @@ public final class SurfaceControl implements Parcelable {
          */
        public Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) {
            checkPreconditions(sc);
            if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
                SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
                        "setShadowRadius", this, sc, "radius=" + shadowRadius);
            }
            nativeSetShadowRadius(mNativeObject, sc.mNativeObject, shadowRadius);
            return this;
        }
@@ -4463,26 +4569,6 @@ public final class SurfaceControl implements Parcelable {
        return -1;
    }

    /**
     * Adds this surface control to the registry for this process if it is created.
     */
    private void addToRegistry() {
        final SurfaceControlRegistry registry = SurfaceControlRegistry.getProcessInstance();
        if (registry != null) {
            registry.add(this);
        }
    }

    /**
     * Removes this surface control from the registry for this process.
     */
    private void removeFromRegistry() {
        final SurfaceControlRegistry registry = SurfaceControlRegistry.getProcessInstance();
        if (registry != null) {
            registry.remove(this);
        }
    }

    // Called by native
    private static void invokeReleaseCallback(Consumer<SyncFence> callback, long nativeFencePtr) {
        SyncFence fence = new SyncFence(nativeFencePtr);
+133 −3
Original line number Diff line number Diff line
@@ -23,7 +23,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.content.Context;
import android.os.Build;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
@@ -104,6 +106,9 @@ public class SurfaceControlRegistry {
    // Number of surface controls to dump when the max threshold is exceeded
    private static final int DUMP_LIMIT = 256;

    // An instance of a registry that is a no-op
    private static final SurfaceControlRegistry NO_OP_REGISTRY = new NoOpRegistry();

    // Static lock, must be held for all registry operations
    private static final Object sLock = new Object();

@@ -113,6 +118,22 @@ public class SurfaceControlRegistry {
    // The registry for a given process
    private static volatile SurfaceControlRegistry sProcessRegistry;

    // Whether call stack debugging has been initialized. This is evaluated only once per process
    // instance when the first SurfaceControl.Transaction object is created
    static boolean sCallStackDebuggingInitialized;

    // Whether call stack debugging is currently enabled, ie. whether there is a valid match string
    // for either a specific surface control name or surface control transaction method
    static boolean sCallStackDebuggingEnabled;

    // The name of the surface control to log stack traces for.  Always non-null if
    // sCallStackDebuggingEnabled is true.  Can be combined with the match call.
    private static String sCallStackDebuggingMatchName;

    // The surface control transaction method name to log stack traces for.  Always non-null if
    // sCallStackDebuggingEnabled is true.  Can be combined with the match name.
    private static String sCallStackDebuggingMatchCall;

    // Mapping of the active SurfaceControls to the elapsed time when they were registered
    @GuardedBy("sLock")
    private final WeakHashMap<SurfaceControl, Long> mSurfaceControls;
@@ -160,6 +181,12 @@ public class SurfaceControlRegistry {
        }
    }

    @VisibleForTesting
    public void setCallStackDebuggingParams(String matchName, String matchCall) {
        sCallStackDebuggingMatchName = matchName.toLowerCase();
        sCallStackDebuggingMatchCall = matchCall.toLowerCase();
    }

    /**
     * Creates and initializes the registry for all SurfaceControls in this process. The caller must
     * hold the READ_FRAME_BUFFER permission.
@@ -196,11 +223,9 @@ public class SurfaceControlRegistry {
     * createProcessInstance(Context) was previously called from a valid caller.
     * @hide
     */
    @Nullable
    @VisibleForTesting
    public static SurfaceControlRegistry getProcessInstance() {
        synchronized (sLock) {
            return sProcessRegistry;
            return sProcessRegistry != null ? sProcessRegistry : NO_OP_REGISTRY;
        }
    }

@@ -247,6 +272,91 @@ public class SurfaceControlRegistry {
        }
    }

    /**
     * Initializes global call stack debugging if this is a debug build and a filter is specified.
     * This is a no-op if
     *
     * Usage:
     *   adb shell setprop persist.wm.debug.sc.tx.log_match_call <call or \"\" to unset>
     *   adb shell setprop persist.wm.debug.sc.tx.log_match_name <name or \"\" to unset>
     *   adb reboot
     */
    final static void initializeCallStackDebugging() {
        if (sCallStackDebuggingInitialized || !Build.IS_DEBUGGABLE) {
            // Return early if already initialized or this is not a debug build
            return;
        }

        sCallStackDebuggingInitialized = true;
        sCallStackDebuggingMatchCall =
                SystemProperties.get("persist.wm.debug.sc.tx.log_match_call", null)
                        .toLowerCase();
        sCallStackDebuggingMatchName =
                SystemProperties.get("persist.wm.debug.sc.tx.log_match_name", null)
                        .toLowerCase();
        // Only enable stack debugging if any of the match filters are set
        sCallStackDebuggingEnabled = (!sCallStackDebuggingMatchCall.isEmpty()
                || !sCallStackDebuggingMatchName.isEmpty());
        if (sCallStackDebuggingEnabled) {
            Log.d(TAG, "Enabling transaction call stack debugging:"
                    + " matchCall=" + sCallStackDebuggingMatchCall
                    + " matchName=" + sCallStackDebuggingMatchName);
        }
    }

    /**
     * Dumps the callstack if it matches the global debug properties. Caller should first verify
     * {@link #sCallStackDebuggingEnabled} is true.
     *
     * @param call the name of the call
     * @param tx (optional) the transaction associated with this call
     * @param sc the affected surface
     * @param details additional details to print with the stack track
     */
    final void checkCallStackDebugging(@NonNull String call,
            @Nullable SurfaceControl.Transaction tx, @Nullable SurfaceControl sc,
            @Nullable String details) {
        if (!sCallStackDebuggingEnabled) {
            return;
        }
        if (!matchesForCallStackDebugging(sc != null ? sc.getName() : null, call)) {
            return;
        }
        final String txMsg = tx != null ? "tx=" + tx.getId() + " ": "";
        final String scMsg = sc != null ? " sc=" + sc.getName() + "": "";
        final String msg = details != null
                ? call + " (" + txMsg + scMsg + ") " + details
                : call + " (" + txMsg + scMsg + ")";
        Log.e(TAG, msg, new Throwable());
    }

    /**
     * Tests whether the given surface control name/method call matches the filters set for the
     * call stack debugging.
     */
    @VisibleForTesting
    public final boolean matchesForCallStackDebugging(@Nullable String name, @NonNull String call) {
        final boolean matchCall = !sCallStackDebuggingMatchCall.isEmpty();
        if (matchCall && !call.toLowerCase().contains(sCallStackDebuggingMatchCall)) {
            // Skip if target call doesn't match requested caller
            return false;
        }
        final boolean matchName = !sCallStackDebuggingMatchName.isEmpty();
        if (matchName && (name == null
                || !name.toLowerCase().contains(sCallStackDebuggingMatchName))) {
            // Skip if target surface doesn't match requested surface
            return false;
        }
        return true;
    }

    /**
     * Returns whether call stack debugging is enabled for this process.
     */
    final static boolean isCallStackDebuggingEnabled() {
        return sCallStackDebuggingEnabled;
    }

    /**
     * Forces the gc and finalizers to run, used prior to dumping to ensure we only dump strongly
     * referenced surface controls.
@@ -272,7 +382,27 @@ public class SurfaceControlRegistry {
        synchronized (sLock) {
            if (sProcessRegistry != null) {
                sDefaultReporter.onMaxLayersExceeded(sProcessRegistry.mSurfaceControls, limit, pw);
                pw.println("sCallStackDebuggingInitialized=" + sCallStackDebuggingInitialized);
                pw.println("sCallStackDebuggingEnabled=" + sCallStackDebuggingEnabled);
                pw.println("sCallStackDebuggingMatchName=" + sCallStackDebuggingMatchName);
                pw.println("sCallStackDebuggingMatchCall=" + sCallStackDebuggingMatchCall);
            }
        }
    }

    /**
     * A no-op implementation of the registry.
     */
    private static class NoOpRegistry extends SurfaceControlRegistry {

        @Override
        public void setReportingThresholds(int maxLayersReportingThreshold,
                int resetReportingThreshold, Reporter reporter) {}

        @Override
        void add(SurfaceControl sc) {}

        @Override
        void remove(SurfaceControl sc) {}
    }
}
+23 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.eq;
@@ -148,6 +149,28 @@ public class SurfaceControlRegistryTests {
        reporter.assertLastReportedSetEquals(sc5, sc6, sc7, sc8);
    }

    @Test
    public void testCallStackDebugging_matchesFilters() {
        SurfaceControlRegistry registry = SurfaceControlRegistry.getProcessInstance();

        // Specific name, any call
        registry.setCallStackDebuggingParams("com.android.app1", "");
        assertFalse(registry.matchesForCallStackDebugging("com.android.noMatchApp", "setAlpha"));
        assertTrue(registry.matchesForCallStackDebugging("com.android.app1", "setAlpha"));

        // Any name, specific call
        registry.setCallStackDebuggingParams("", "setAlpha");
        assertFalse(registry.matchesForCallStackDebugging("com.android.app1", "setLayer"));
        assertTrue(registry.matchesForCallStackDebugging("com.android.app1", "setAlpha"));
        assertTrue(registry.matchesForCallStackDebugging("com.android.app2", "setAlpha"));

        // Specific name, specific call
        registry.setCallStackDebuggingParams("com.android.app1", "setAlpha");
        assertFalse(registry.matchesForCallStackDebugging("com.android.app1", "setLayer"));
        assertFalse(registry.matchesForCallStackDebugging("com.android.app2", "setAlpha"));
        assertTrue(registry.matchesForCallStackDebugging("com.android.app1", "setAlpha"));
    }

    private SurfaceControl buildTestSurface() {
        return new SurfaceControl.Builder()
                .setContainerLayer()