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

Commit a657ac9c authored by Winson Chung's avatar Winson Chung
Browse files

Add initial SysUI trace support

Bug: 144854916
Test: Take a sysui trace
Change-Id: Ia8a87c8c6756ecbb77beb06a60d5b46b883ed8d9
t stat
parent b53b30cd
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ oneway interface IOverviewProxy {

    void onInitialize(in Bundle params) = 12;


    /**
     * @deprecated
     */
+5 −1
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ public class QuickStepContract {
    // The notification panel is expanded and interactive (either locked or unlocked), and the
    // quick settings is not expanded
    public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11;
    // Winscope tracing is enabled
    public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -98,7 +100,8 @@ public class QuickStepContract {
            SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
            SYSUI_STATE_OVERVIEW_DISABLED,
            SYSUI_STATE_HOME_DISABLED,
            SYSUI_STATE_SEARCH_DISABLED
            SYSUI_STATE_SEARCH_DISABLED,
            SYSUI_STATE_TRACING_ENABLED
    })
    public @interface SystemUiStateFlags {}

@@ -117,6 +120,7 @@ public class QuickStepContract {
        str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
        str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
        str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
        str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : "");
        return str.toString();
    }

+186 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.shared.tracing;

import android.os.Trace;
import android.util.Log;
import android.view.Choreographer;

import com.android.internal.util.TraceBuffer;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.function.Consumer;

/**
 * A proto tracer implementation that can be updated directly (upon state change), or on the next
 * scheduled frame.
 *
 * @param <P> The class type of the proto provider
 * @param <S> The proto class type of the encapsulating proto
 * @param <T> The proto class type of the individual proto entries in the buffer
 * @param <R> The proto class type of the entry root proto in the buffer
 */
public class FrameProtoTracer<P, S extends P, T extends P, R>
        implements TraceBuffer.ProtoProvider<P, S, T>, Choreographer.FrameCallback {

    private static final String TAG = "FrameProtoTracer";
    private static final int BUFFER_CAPACITY = 1024 * 1024;

    private final Object mLock = new Object();
    private final TraceBuffer<P, S, T> mBuffer;
    private final File mTraceFile;
    private final ProtoTraceParams<P, S, T, R> mParams;
    private final Choreographer mChoreographer;
    private final Queue<T> mPool = new LinkedList<>();
    private final ArrayList<ProtoTraceable<R>> mTraceables = new ArrayList<>();
    private final ArrayList<ProtoTraceable<R>> mTmpTraceables = new ArrayList<>();

    private volatile boolean mEnabled;
    private boolean mFrameScheduled;

    public interface ProtoTraceParams<P, S, T, R> {
        File getTraceFile();
        S getEncapsulatingTraceProto();
        T updateBufferProto(T reuseObj, ArrayList<ProtoTraceable<R>> traceables);
        byte[] serializeEncapsulatingProto(S encapsulatingProto, Queue<T> buffer);
        byte[] getProtoBytes(P proto);
        int getProtoSize(P proto);
    }

    public FrameProtoTracer(ProtoTraceParams<P, S, T, R> params) {
        mParams = params;
        mBuffer = new TraceBuffer<>(BUFFER_CAPACITY, this, new Consumer<T>() {
            @Override
            public void accept(T t) {
                onProtoDequeued(t);
            }
        });
        mTraceFile = params.getTraceFile();
        mChoreographer = Choreographer.getMainThreadInstance();
    }

    @Override
    public int getItemSize(P proto) {
        return mParams.getProtoSize(proto);
    }

    @Override
    public byte[] getBytes(P proto) {
        return mParams.getProtoBytes(proto);
    }

    @Override
    public void write(S encapsulatingProto, Queue<T> buffer, OutputStream os) throws IOException {
        os.write(mParams.serializeEncapsulatingProto(encapsulatingProto, buffer));
    }

    public void start() {
        synchronized (mLock) {
            if (mEnabled) {
                return;
            }
            mBuffer.resetBuffer();
            mEnabled = true;
        }
        logState();
    }

    public void stop() {
        synchronized (mLock) {
            if (!mEnabled) {
                return;
            }
            mEnabled = false;
        }
        writeToFile();
    }

    public boolean isEnabled() {
        return mEnabled;
    }

    public void add(ProtoTraceable<R> traceable) {
        synchronized (mLock) {
            mTraceables.add(traceable);
        }
    }

    public void remove(ProtoTraceable<R> traceable) {
        synchronized (mLock) {
            mTraceables.remove(traceable);
        }
    }

    public void scheduleFrameUpdate() {
        if (!mEnabled || mFrameScheduled) {
            return;
        }

        // Schedule an update on the next frame
        mChoreographer.postFrameCallback(this);
        mFrameScheduled = true;
    }

    public void update() {
        if (!mEnabled) {
            return;
        }

        logState();
    }

    public float getBufferUsagePct() {
        return (float) mBuffer.getBufferSize() / BUFFER_CAPACITY;
    }

    @Override
    public void doFrame(long frameTimeNanos) {
        logState();
    }

    private void onProtoDequeued(T proto) {
        mPool.add(proto);
    }

    private void logState() {
        synchronized (mLock) {
            mTmpTraceables.addAll(mTraceables);
        }

        mBuffer.add(mParams.updateBufferProto(mPool.poll(), mTmpTraceables));
        mTmpTraceables.clear();
        mFrameScheduled = false;
    }

    private void writeToFile() {
        try {
            Trace.beginSection("ProtoTracer.writeToFile");
            mBuffer.writeTraceToFile(mTraceFile, mParams.getEncapsulatingTraceProto());
        } catch (IOException e) {
            Log.e(TAG, "Unable to write buffer to file", e);
        } finally {
            Trace.endSection();
        }
    }
}

+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package com.android.systemui.shared.tracing;

/**
 * @see FrameProtoTracer
 */
public interface ProtoTraceable<T> {

    /**
     * NOTE: Implementations should update all fields in this proto.
     */
    void writeToProto(T proto);
}
+3 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.leak.GarbageMonitor;
@@ -327,6 +328,7 @@ public class Dependency {
    @Inject Lazy<SystemWindows> mSystemWindows;
    @Inject Lazy<DisplayImeController> mDisplayImeController;
    @Inject Lazy<RecordingController> mRecordingController;
    @Inject Lazy<ProtoTracer> mProtoTracer;

    @Inject
    public Dependency() {
@@ -519,6 +521,7 @@ public class Dependency {
        mProviders.put(DisplayWindowController.class, mDisplayWindowController::get);
        mProviders.put(SystemWindows.class, mSystemWindows::get);
        mProviders.put(DisplayImeController.class, mDisplayImeController::get);
        mProviders.put(ProtoTracer.class, mProtoTracer::get);

        // TODO(b/118592525): to support multi-display , we start to add something which is
        //                    per-display, while others may be global. I think it's time to add
Loading