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

Commit 9f363c62 authored by MingWei's avatar MingWei Committed by MingWei Liao
Browse files

Improve content capture trace and prevent redundant works

1. Only start trace session when content capture is enabled.
2. Only start notifyContentCaptureEvents loop when content capture is
   enabled.
3. Make sure FLAG_SECURE will not have effect when the session is
   already disabled by the app. Otherwise, the default absense of
   FLAG_SECURE will temporarily override the disabling state by app.
   This would make ViewRootImpl cache the incorrect state during startup
   and run some redundant works.

BUG: 295199827
Test: refactoring CL. Existing unit tests still pass.
Change-Id: I422c7f9af6ce296cdb26d5575445f50fc298de4f
parent 8e10e17e
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -3975,8 +3975,17 @@ public final class ViewRootImpl implements ViewParent,
    }

    private void notifyContentCaptureEvents() {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
        try {
            if (!isContentCaptureEnabled()) {
                if (DEBUG_CONTENT_CAPTURE) {
                    Log.d(mTag, "notifyContentCaptureEvents while disabled");
                }
                mAttachInfo.mContentCaptureEvents = null;
                return;
            }
            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
            }
            MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
                    .getMainContentCaptureSession();
            for (int i = 0; i < mAttachInfo.mContentCaptureEvents.size(); i++) {
@@ -4890,12 +4899,13 @@ public final class ViewRootImpl implements ViewParent,
        if (DEBUG_CONTENT_CAPTURE) {
            Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
        }
        try {
            if (!isContentCaptureEnabled()) return;

            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
                        + getClass().getSimpleName());
            }
        try {
            if (!isContentCaptureEnabled()) return;

            // Initial dispatch of window bounds to content capture
            if (mAttachInfo.mContentCaptureManager != null) {
@@ -4916,12 +4926,13 @@ public final class ViewRootImpl implements ViewParent,
        if (DEBUG_CONTENT_CAPTURE) {
            Log.v(mTag, "handleContentCaptureFlush()");
        }
        try {
            if (!isContentCaptureEnabled()) return;

            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
                        + getClass().getSimpleName());
            }
        try {
            if (!isContentCaptureEnabled()) return;

            final ContentCaptureManager ccm = mAttachInfo.mContentCaptureManager;
            if (ccm == null) {
+5 −1
Original line number Diff line number Diff line
@@ -783,7 +783,9 @@ public final class ContentCaptureManager {
                (params.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0;

        MainContentCaptureSession mainSession;
        boolean alreadyDisabledByApp;
        synchronized (mLock) {
            alreadyDisabledByApp = (mFlags & ContentCaptureContext.FLAG_DISABLED_BY_APP) != 0;
            if (flagSecureEnabled) {
                mFlags |= ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
            } else {
@@ -791,7 +793,9 @@ public final class ContentCaptureManager {
            }
            mainSession = mMainSession;
        }
        if (mainSession != null) {

        // Prevent overriding the status of disabling by app
        if (mainSession != null && !alreadyDisabledByApp) {
            mainSession.setDisabled(flagSecureEnabled);
        }
    }
+15 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.RemoteException;
import android.os.Trace;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
@@ -373,12 +374,26 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
            return;
        }

        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
            if (eventType == TYPE_VIEW_TREE_APPEARING) {
                Trace.asyncTraceBegin(
                        Trace.TRACE_TAG_VIEW, /* methodName= */ "sendEventAsync", /* cookie= */ 0);
            }
        }

        if (isContentProtectionReceiverEnabled()) {
            sendContentProtectionEvent(event);
        }
        if (isContentCaptureReceiverEnabled()) {
            sendContentCaptureEvent(event, forceFlush);
        }

        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
            if (eventType == TYPE_VIEW_TREE_APPEARED) {
                Trace.asyncTraceEnd(
                        Trace.TRACE_TAG_VIEW, /* methodName= */ "sendEventAsync", /* cookie= */ 0);
            }
        }
    }

    @UiThread
+47 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static org.testng.Assert.assertThrows;

import android.content.ContentCaptureOptions;
import android.content.Context;
import android.view.WindowManager;

import com.android.internal.util.RingBuffer;

@@ -147,6 +148,52 @@ public class ContentCaptureManagerTest {
        assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
    }

    @Test
    public void testUpdateWindowAttribute_setFlagSecure() {
        final ContentCaptureManager manager =
                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
        // Ensure main session is created.
        final MainContentCaptureSession unused = manager.getMainContentCaptureSession();
        final WindowManager.LayoutParams initialParam = new WindowManager.LayoutParams();
        initialParam.flags |= WindowManager.LayoutParams.FLAG_SECURE;

        manager.updateWindowAttributes(initialParam);

        assertThat(manager.isContentCaptureEnabled()).isFalse();
    }

    @Test
    public void testUpdateWindowAttribute_clearFlagSecure() {
        final ContentCaptureManager manager =
                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
        // Ensure main session is created.
        final MainContentCaptureSession unused = manager.getMainContentCaptureSession();
        final WindowManager.LayoutParams initialParam = new WindowManager.LayoutParams();
        initialParam.flags |= WindowManager.LayoutParams.FLAG_SECURE;
        // Default param does not have FLAG_SECURE set.
        final WindowManager.LayoutParams resetParam = new WindowManager.LayoutParams();

        manager.updateWindowAttributes(initialParam);
        manager.updateWindowAttributes(resetParam);

        assertThat(manager.isContentCaptureEnabled()).isTrue();
    }

    @Test
    public void testUpdateWindowAttribute_clearFlagSecureAfterDisabledByApp() {
        final ContentCaptureManager manager =
                new ContentCaptureManager(mMockContext, mMockContentCaptureManager, EMPTY_OPTIONS);
        // Ensure main session is created.
        final MainContentCaptureSession unused = manager.getMainContentCaptureSession();
        // Default param does not have FLAG_SECURE set.
        final WindowManager.LayoutParams resetParam = new WindowManager.LayoutParams();

        manager.setContentCaptureEnabled(false);
        manager.updateWindowAttributes(resetParam);

        assertThat(manager.isContentCaptureEnabled()).isFalse();
    }

    private ContentCaptureOptions createOptions(
            ContentCaptureOptions.ContentProtectionOptions contentProtectionOptions) {
        return new ContentCaptureOptions(