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

Commit 65d07391 authored by Kean Mariotti's avatar Kean Mariotti Committed by Android (Google) Code Review
Browse files

Merge "WindowTracing: fix deadlock" into main

parents 827ce461 d6d94543
Loading
Loading
Loading
Loading
+35 −23
Original line number Diff line number Diff line
@@ -38,15 +38,18 @@ import java.util.concurrent.atomic.AtomicBoolean;

public final class WindowTracingDataSource extends DataSource<WindowTracingDataSource.Instance,
        WindowTracingDataSource.TlsState, Void> {

    public static class TlsState {
        public final Config mConfig;
        public final AtomicBoolean mIsStarting = new AtomicBoolean(true);
        public final AtomicBoolean mIsStarting;

        private TlsState(Config config) {
        private TlsState(Config config, AtomicBoolean isStarting) {
            mConfig = config;
            mIsStarting = isStarting;
        }
    }


    public static class Config {
        public final @WindowTracingLogLevel int mLogLevel;
        public final @WindowTracingLogFrequency int mLogFrequency;
@@ -59,12 +62,34 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS
        }
    }

    public abstract static class Instance extends DataSourceInstance {
    public static class Instance extends DataSourceInstance {
        public final Config mConfig;
        public final AtomicBoolean mIsStarting = new AtomicBoolean(true);
        private final WeakReference<WindowTracingPerfetto> mWindowTracing;

        public Instance(DataSource dataSource, int instanceIndex, Config config) {
        public Instance(DataSource dataSource,
                int instanceIndex,
                Config config,
                WeakReference<WindowTracingPerfetto> windowTracing) {
            super(dataSource, instanceIndex);
            mConfig = config;
            mWindowTracing = windowTracing;
        }

        @Override
        protected void onStart(StartCallbackArguments args) {
            WindowTracingPerfetto windowTracing = mWindowTracing.get();
            if (windowTracing != null) {
                windowTracing.onStart(mConfig);
            }
        }

        @Override
        protected void onStop(StopCallbackArguments args) {
            WindowTracingPerfetto windowTracing = mWindowTracing.get();
            if (windowTracing != null) {
                windowTracing.onStop(this);
            }
        }
    }

@@ -85,6 +110,7 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS
                new DataSourceParams.Builder()
                        .setBufferExhaustedPolicy(
                                PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_STALL_AND_ABORT)
                        .setPostponeStop(true)
                        .build();
        register(params);
        Log.i(TAG, "Registered with perfetto service");
@@ -94,23 +120,9 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS
    public Instance createInstance(ProtoInputStream configStream, int instanceIndex) {
        final Config config = parseDataSourceConfig(configStream);

        return new Instance(this, instanceIndex, config != null ? config : CONFIG_DEFAULT) {
            @Override
            protected void onStart(StartCallbackArguments args) {
                WindowTracingPerfetto windowTracing = mWindowTracing.get();
                if (windowTracing != null) {
                    windowTracing.onStart(mConfig);
                }
            }

            @Override
            protected void onStop(StopCallbackArguments args) {
                WindowTracingPerfetto windowTracing = mWindowTracing.get();
                if (windowTracing != null) {
                    windowTracing.onStop(mConfig);
                }
            }
        };
        return new Instance(this,
                instanceIndex,
                config != null ? config : CONFIG_DEFAULT, mWindowTracing);
    }

    @Override
@@ -119,9 +131,9 @@ public final class WindowTracingDataSource extends DataSource<WindowTracingDataS
        try (Instance dsInstance = args.getDataSourceInstanceLocked()) {
            if (dsInstance == null) {
                // Datasource instance has been removed
                return new TlsState(CONFIG_DEFAULT);
                return new TlsState(CONFIG_DEFAULT,  new AtomicBoolean(true));
            }
            return new TlsState(dsInstance.mConfig);
            return new TlsState(dsInstance.mConfig, dsInstance.mIsStarting);
        }
    }

+33 −11
Original line number Diff line number Diff line
@@ -19,17 +19,19 @@ package com.android.server.wm;
import android.annotation.Nullable;
import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
import android.internal.perfetto.protos.WinscopeExtensionsImplOuterClass.WinscopeExtensionsImpl;
import android.os.Handler;
import android.os.Looper;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.Choreographer;

import com.android.internal.annotations.VisibleForTesting;

import android.os.Trace;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

class WindowTracingPerfetto extends WindowTracing {
@@ -39,6 +41,7 @@ class WindowTracingPerfetto extends WindowTracing {
    private final AtomicInteger mCountSessionsOnFrame = new AtomicInteger();
    private final AtomicInteger mCountSessionsOnTransaction = new AtomicInteger();
    private final WindowTracingDataSource mDataSource;
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());

    WindowTracingPerfetto(WindowManagerService service, Choreographer choreographer) {
        this(service, choreographer, service.mGlobalLock, PRODUCTION_DATA_SOURCE_NAME);
@@ -112,6 +115,8 @@ class WindowTracingPerfetto extends WindowTracing {
            boolean isStartLogEvent = where == WHERE_START_TRACING;
            boolean isOnFrameLogEvent = where == WHERE_ON_FRAME;

            ArrayList<Runnable> pendingStopDones = new ArrayList<Runnable>();

            mDataSource.trace((context) -> {
                WindowTracingDataSource.Config dataSourceConfig =
                        context.getCustomTlsState().mConfig;
@@ -144,7 +149,19 @@ class WindowTracingPerfetto extends WindowTracing {
                dumpToProto(os, dataSourceConfig.mLogLevel, where, timestamp);
                os.end(tokenExtensionsField);
                os.end(tokenWinscopeExtensions);

                if (dataSourceConfig.mLogFrequency == WindowTracingLogFrequency.SINGLE_DUMP) {
                    // Postpone the stopDone() call to when DataSource#trace() has returned.
                    // At this point the tracing data has not been written to Perfetto yet,
                    // hence we can't already call stopDone().
                    pendingStopDones.add(context::stopDone);
                }
            });

            for (int i = 0; i < pendingStopDones.size(); ++i) {
                pendingStopDones.get(i).run();
                Log.i(TAG, "Stopped session (frequency=SINGLE_DUMP) (postponed stop)");
            }
        } catch (Exception e) {
            Log.wtf(TAG, "Exception while tracing state", e);
        } finally {
@@ -170,22 +187,27 @@ class WindowTracingPerfetto extends WindowTracing {
            Log.i(TAG, "Started session (frequency=TRANSACTION, log level="
                    + config.mLogFrequency + ")");
            mCountSessionsOnTransaction.incrementAndGet();
        } else if (config.mLogFrequency == WindowTracingLogFrequency.SINGLE_DUMP) {
            Log.i(TAG, "Started session (frequency=SINGLE_DUMP, log level="
                    + config.mLogFrequency + ")");
            return; // onStop() will trigger the start log event of SINGLE_DUMP tracing sessions
        }

        Log.i(TAG, getStatus());

        log(WHERE_START_TRACING);
        mMainHandler.post(() -> log(WHERE_START_TRACING));
    }

    void onStop(WindowTracingDataSource.Config config) {
        if (config.mLogFrequency == WindowTracingLogFrequency.FRAME) {
    void onStop(WindowTracingDataSource.Instance instance) {
        if (instance.mConfig.mLogFrequency == WindowTracingLogFrequency.FRAME) {
            instance.stopDone();
            Log.i(TAG, "Stopped session (frequency=FRAME)");
            mCountSessionsOnFrame.decrementAndGet();
            Log.i(TAG, "Stopped session (frequency=TRANSACTION)");
        } else if (config.mLogFrequency == WindowTracingLogFrequency.TRANSACTION) {
        } else if (instance.mConfig.mLogFrequency == WindowTracingLogFrequency.TRANSACTION) {
            instance.stopDone();
            mCountSessionsOnTransaction.decrementAndGet();
            Log.i(TAG, "Stopped session (frequency=TRANSACTION)");
        } else if (instance.mConfig.mLogFrequency == WindowTracingLogFrequency.SINGLE_DUMP) {
            Log.i(TAG, "Triggering log event on stop (frequency=SINGLE_DUMP)");
            mMainHandler.post(() -> log(WHERE_START_TRACING));
        }

        Log.i(TAG, getStatus());
    }
}