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

Commit 236cb8e4 authored by Yisroel Forta's avatar Yisroel Forta Committed by Android (Google) Code Review
Browse files

Merge "Revert^2 "AppStartInfo surfaceflinger and renderthread timestamps"" into main

parents 711879ab de3584cb
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -756,6 +756,15 @@ interface IActivityManager {
     */
    void addStartInfoTimestamp(int key, long timestampNs, int userId);

    /**
    * Reports view related timestamps to be added to the calling apps most
    * recent {@link ApplicationStartInfo}.
    *
    * @param renderThreadDrawStartTimeNs Clock monotonic time in nanoseconds of RenderThread draw start
    * @param framePresentedTimeNs        Clock monotonic time in nanoseconds of frame presented
    */
    oneway void reportStartInfoViewTimestamps(long renderThreadDrawStartTimeNs, long framePresentedTimeNs);

    /**
     * Return a list of {@link ApplicationExitInfo} records.
     *
+87 −0
Original line number Diff line number Diff line
@@ -177,6 +177,7 @@ import android.graphics.Region;
import android.graphics.RenderNode;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.hardware.SyncFence;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerGlobal;
@@ -219,6 +220,7 @@ import android.util.proto.ProtoOutputStream;
import android.view.InputDevice.InputSourceClass;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceControl.TransactionStats;
import android.view.View.AttachInfo;
import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
@@ -293,6 +295,7 @@ import java.util.OptionalInt;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
 * The top of a view hierarchy, implementing the needed protocol between View
@@ -1189,6 +1192,13 @@ public final class ViewRootImpl implements ViewParent,
    private String mFpsTraceName;
    private String mLargestViewTraceName;
    private final boolean mAppStartInfoTimestampsFlagValue;
    @GuardedBy("this")
    private boolean mAppStartTimestampsSent = false;
    private boolean mAppStartTrackingStarted = false;
    private long mRenderThreadDrawStartTimeNs = -1;
    private long mFirstFramePresentedTimeNs = -1;
    private static boolean sToolkitSetFrameRateReadOnlyFlagValue;
    private static boolean sToolkitFrameRateFunctionEnablingReadOnlyFlagValue;
    private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
@@ -1306,6 +1316,8 @@ public final class ViewRootImpl implements ViewParent,
        } else {
            mSensitiveContentProtectionService = null;
        }
        mAppStartInfoTimestampsFlagValue = android.app.Flags.appStartInfoTimestamps();
    }
    public static void addFirstDrawHandler(Runnable callback) {
@@ -2578,6 +2590,12 @@ public final class ViewRootImpl implements ViewParent,
                    notifySurfaceDestroyed();
                }
                destroySurface();
                // Reset so they can be sent again for warm starts.
                mAppStartTimestampsSent = false;
                mAppStartTrackingStarted = false;
                mRenderThreadDrawStartTimeNs = -1;
                mFirstFramePresentedTimeNs = -1;
            }
        }
    }
@@ -4376,6 +4394,30 @@ public final class ViewRootImpl implements ViewParent,
                reportDrawFinished(t, seqId);
            }
        });
        // Only trigger once per {@link ViewRootImpl} instance, so don't add listener if
        // {link mTransactionCompletedTimeNs} has already been set.
        if (mAppStartInfoTimestampsFlagValue && !mAppStartTrackingStarted) {
            mAppStartTrackingStarted = true;
            Transaction transaction = new Transaction();
            transaction.addTransactionCompletedListener(mExecutor,
                    new Consumer<TransactionStats>() {
                        @Override
                        public void accept(TransactionStats transactionStats) {
                            SyncFence presentFence = transactionStats.getPresentFence();
                            if (presentFence.awaitForever()) {
                                if (mFirstFramePresentedTimeNs == -1) {
                                    // Only trigger once per {@link ViewRootImpl} instance.
                                    mFirstFramePresentedTimeNs = presentFence.getSignalTime();
                                    maybeSendAppStartTimes();
                                }
                            }
                            presentFence.close();
                        }
                    });
            applyTransactionOnDraw(transaction);
        }
        if (DEBUG_BLAST) {
            Log.d(mTag, "Setup new sync=" + mWmsRequestSyncGroup.getName());
        }
@@ -4383,6 +4425,45 @@ public final class ViewRootImpl implements ViewParent,
        mWmsRequestSyncGroup.add(this, null /* runnable */);
    }
    private void maybeSendAppStartTimes() {
        synchronized (this) {
            if (mAppStartTimestampsSent) {
                // Don't send timestamps more than once.
                return;
            }
            // If we already have {@link mRenderThreadDrawStartTimeNs} then pass it through, if not
            // post to main thread and check if we have it there.
            if (mRenderThreadDrawStartTimeNs != -1) {
                sendAppStartTimesLocked();
            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        synchronized (ViewRootImpl.this) {
                            if (mRenderThreadDrawStartTimeNs == -1) {
                                return;
                            }
                            sendAppStartTimesLocked();
                        }
                    }
                });
            }
        }
    }
    @GuardedBy("this")
    private void sendAppStartTimesLocked() {
        try {
            ActivityManager.getService().reportStartInfoViewTimestamps(
                    mRenderThreadDrawStartTimeNs, mFirstFramePresentedTimeNs);
            mAppStartTimestampsSent = true;
        } catch (RemoteException e) {
            // Ignore, timestamps may be lost.
            if (DBG) Log.d(TAG, "Exception attempting to report start timestamps.", e);
        }
    }
    /**
     * Helper used to notify the service to block projection when a sensitive
     * view (the view displays sensitive content) is attached to the window.
@@ -5569,7 +5650,13 @@ public final class ViewRootImpl implements ViewParent,
                    registerCallbackForPendingTransactions();
                }
                long timeNs = SystemClock.uptimeNanos();
                mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
                // Only trigger once per {@link ViewRootImpl} instance.
                if (mAppStartInfoTimestampsFlagValue && mRenderThreadDrawStartTimeNs == -1) {
                    mRenderThreadDrawStartTimeNs = timeNs;
                }
            } else {
                // If we get here with a disabled & requested hardware renderer, something went
                // wrong (an invalidate posted right before we destroyed the hardware surface
+13 −0
Original line number Diff line number Diff line
@@ -10237,6 +10237,19 @@ public class ActivityManagerService extends IActivityManager.Stub
        addStartInfoTimestampInternal(key, timestampNs, userId, callingUid);
    }
    @Override
    public void reportStartInfoViewTimestamps(long renderThreadDrawStartTimeNs,
            long framePresentedTimeNs) {
        int callingUid = Binder.getCallingUid();
        int userId = UserHandle.getUserId(callingUid);
        addStartInfoTimestampInternal(
                ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME,
                renderThreadDrawStartTimeNs, userId, callingUid);
        addStartInfoTimestampInternal(
                ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE,
                framePresentedTimeNs, userId, callingUid);
    }
    private void addStartInfoTimestampInternal(int key, long timestampNs, int userId, int uid) {
        mProcessList.getAppStartInfoTracker().addTimestampToStart(
                Settings.getPackageNameForUid(mContext, uid),
+50 −14
Original line number Diff line number Diff line
@@ -1195,31 +1195,67 @@ public final class AppStartInfoTracker {

            // Records are sorted newest to oldest, grab record at index 0.
            ApplicationStartInfo startInfo = mInfos.get(0);

            if (!isAddTimestampAllowed(startInfo, key, timestampNs)) {
                return;
            }

            startInfo.addStartupTimestamp(key, timestampNs);

            if (key == ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME
                    && android.app.Flags.appStartInfoTimestamps()) {
                startInfo.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
                checkCompletenessAndCallback(startInfo);
            }
        }

        private boolean isAddTimestampAllowed(ApplicationStartInfo startInfo, int key,
                long timestampNs) {
            int startupState = startInfo.getStartupState();

            // If startup state is error then don't accept any further timestamps.
            if (startupState == ApplicationStartInfo.STARTUP_STATE_ERROR) {
                if (DEBUG) Slog.d(TAG, "Startup state is error, not accepting new timestamps.");
                return;
                return false;
            }

            // If startup state is first frame drawn then only accept fully drawn timestamp.
            if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN
                    && key != ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN) {
                if (DEBUG) {
                    Slog.d(TAG, "Startup state is first frame drawn and timestamp is not fully "
                            + "drawn, not accepting new timestamps.");
            Map<Integer, Long> timestamps = startInfo.getStartupTimestamps();

            if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN) {
                switch (key) {
                    case ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN:
                        // Allowed, continue to confirm it's not already added.
                        break;
                    case ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME:
                        Long firstFrameTimeNs = timestamps
                                .get(ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME);
                        if (firstFrameTimeNs == null) {
                            // This should never happen. State can't be first frame drawn if first
                            // frame timestamp was not provided.
                            return false;
                        }
                return;

                        if (timestampNs > firstFrameTimeNs) {
                            // Initial renderthread frame has to occur before first frame.
                            return false;
                        }

            startInfo.addStartupTimestamp(key, timestampNs);
                        // Allowed, continue to confirm it's not already added.
                        break;
                    case ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE:
                        // Allowed, continue to confirm it's not already added.
                        break;
                    default:
                        return false;
                }
            }

            if (key == ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME
                    && android.app.Flags.appStartInfoTimestamps()) {
                startInfo.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
                checkCompletenessAndCallback(startInfo);
            if (timestamps.get(key) != null) {
                // Timestamp should not occur more than once for a given start.
                return false;
            }

            return true;
        }

        @GuardedBy("mLock")