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

Commit 027b2188 authored by Bo Liu's avatar Bo Liu Committed by Wei Wang
Browse files

Integrate HWUI with PerformanceHintManager

PerformanceHintManager.Session is in java, so add JNI and a HintSessionWrapper
class in HardwareRenderer. Then pass the two calls as two std::functions
into DrawFrameTask.

Note Session is created per HardwareRenderer, not global (per
RenderThread).

Session includes UI thread, render thread, and the thread pool.
Desired duration is from the intended start duration to the frame
deadline. Add an actual frame start time to compute

Add system properties:
debug.hwui.use_hint_manager to enable PerformanceHintManager
debug.hwui.target_cpu_time_percent to control percentage of frame time
  to be used for target cpu duration.

Test: Manual test that there are no crashes and values make sense.
Bug: 158791282
Change-Id: I83f25433c10daa20033803fb7c4ae45eab34f1d3
parent 25318b73
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -737,7 +737,7 @@ public final class Choreographer {
            }

            mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos, vsyncEventData.id,
                    vsyncEventData.frameDeadline);
                    vsyncEventData.frameDeadline, startNanos);
            mFrameScheduled = false;
            mLastFrameTimeNanos = frameTimeNanos;
            mLastVsyncEventData = vsyncEventData;
+12 −11
Original line number Diff line number Diff line
@@ -242,18 +242,19 @@ public final class FrameMetrics {
        int PERFORM_TRAVERSALS_START = 7;
        int DRAW_START = 8;
        int FRAME_DEADLINE = 9;
        int SYNC_QUEUED = 10;
        int SYNC_START = 11;
        int ISSUE_DRAW_COMMANDS_START = 12;
        int SWAP_BUFFERS = 13;
        int FRAME_COMPLETED = 14;
        int DEQUEUE_BUFFER_DURATION = 15;
        int QUEUE_BUFFER_DURATION = 16;
        int GPU_COMPLETED = 17;
        int SWAP_BUFFERS_COMPLETED = 18;
        int DISPLAY_PRESENT_TIME = 19;
        int FRAME_START_TIME = 10;
        int SYNC_QUEUED = 11;
        int SYNC_START = 12;
        int ISSUE_DRAW_COMMANDS_START = 13;
        int SWAP_BUFFERS = 14;
        int FRAME_COMPLETED = 15;
        int DEQUEUE_BUFFER_DURATION = 16;
        int QUEUE_BUFFER_DURATION = 17;
        int GPU_COMPLETED = 18;
        int SWAP_BUFFERS_COMPLETED = 19;
        int DISPLAY_PRESENT_TIME = 20;

        int FRAME_STATS_COUNT = 20; // must always be last and in sync with
        int FRAME_STATS_COUNT = 21; // must always be last and in sync with
                                    // FrameInfoIndex::NumIndexes in libs/hwui/FrameInfo.h
    }

+6 −2
Original line number Diff line number Diff line
@@ -87,18 +87,22 @@ public final class FrameInfo {
    // When the frame needs to be ready by
    public static final int FRAME_DEADLINE = 9;

    // When frame actually started.
    public static final int FRAME_START_TIME = 10;

    // Must be the last one
    // This value must be in sync with `UI_THREAD_FRAME_INFO_SIZE` in FrameInfo.h
    private static final int FRAME_INFO_SIZE = FRAME_DEADLINE + 1;
    private static final int FRAME_INFO_SIZE = FRAME_START_TIME + 1;

    /** checkstyle */
    public void setVsync(long intendedVsync, long usedVsync, long frameTimelineVsyncId,
            long frameDeadline) {
            long frameDeadline, long frameStartTime) {
        frameInfo[FRAME_TIMELINE_VSYNC_ID] = frameTimelineVsyncId;
        frameInfo[INTENDED_VSYNC] = intendedVsync;
        frameInfo[VSYNC] = usedVsync;
        frameInfo[FLAGS] = 0;
        frameInfo[FRAME_DEADLINE] = frameDeadline;
        frameInfo[FRAME_START_TIME] = frameStartTime;
    }

    /** checkstyle */
+58 −10
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.PerformanceHintManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
@@ -165,7 +166,7 @@ public class HardwareRenderer {
     * to opaque with no light source configured.
     */
    public HardwareRenderer() {
        ProcessInitializer.sInstance.initDisplayInfo();
        ProcessInitializer.sInstance.initUsingContext();
        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
        mRootNode.setClipToBounds(false);
        mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
@@ -365,7 +366,8 @@ public class HardwareRenderer {
         */
        public @NonNull FrameRenderRequest setVsyncTime(long vsyncTime) {
            // TODO(b/168552873): populate vsync Id once available to Choreographer public API
            mFrameInfo.setVsync(vsyncTime, vsyncTime, FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE);
            mFrameInfo.setVsync(vsyncTime, vsyncTime, FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE,
                    vsyncTime);
            mFrameInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
            return this;
        }
@@ -835,6 +837,36 @@ public class HardwareRenderer {
        callback.onPictureCaptured(picture);
    }

    /** called by native */
    static PerformanceHintManager.Session createHintSession(int[] tids) {
        PerformanceHintManager performanceHintManager =
                ProcessInitializer.sInstance.getHintManager();
        if (performanceHintManager == null) {
            return null;
        }
        // Native code will always set a target duration before reporting actual durations.
        // So this is just a placeholder value that's never used.
        long targetDurationNanos = 16666667;
        return performanceHintManager.createHintSession(tids, targetDurationNanos);
    }

    /** called by native */
    static void updateTargetWorkDuration(PerformanceHintManager.Session session,
            long targetDurationNanos) {
        session.updateTargetWorkDuration(targetDurationNanos);
    }

    /** called by native */
    static void reportActualWorkDuration(PerformanceHintManager.Session session,
            long actualDurationNanos) {
        session.reportActualWorkDuration(actualDurationNanos);
    }

    /** called by native */
    static void closeHintSession(PerformanceHintManager.Session session) {
        session.close();
    }

    /**
     * Interface used to receive callbacks when a frame is being drawn.
     *
@@ -1071,6 +1103,7 @@ public class HardwareRenderer {
        private boolean mIsolated = false;
        private Context mContext;
        private String mPackageName;
        private PerformanceHintManager mPerformanceHintManager;
        private IGraphicsStats mGraphicsStatsService;
        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
            @Override
@@ -1082,6 +1115,10 @@ public class HardwareRenderer {
        private ProcessInitializer() {
        }

        synchronized PerformanceHintManager getHintManager() {
            return mPerformanceHintManager;
        }

        synchronized void setPackageName(String name) {
            if (mInitialized) return;
            mPackageName = name;
@@ -1127,15 +1164,23 @@ public class HardwareRenderer {
            }
        }

        synchronized void initDisplayInfo() {
            if (mDisplayInitialized) return;
        synchronized void initUsingContext() {
            if (mContext == null) return;

            // If we're in an isolated sandbox mode then we shouldn't try to communicate with DMS
            if (mIsolated) {
            initDisplayInfo();

            // HintManager and HintSession are designed to be accessible from isoalted processes
            // so not checking for isolated process here.
            initHintSession();

            // Defensively clear out the context in case we were passed a context that can leak
            // if we live longer than it, e.g. an activity context.
            mContext = null;
        }

        private void initDisplayInfo() {
            if (mDisplayInitialized) return;
            if (mIsolated) {
                mDisplayInitialized = true;
                return;
            }
@@ -1167,11 +1212,14 @@ public class HardwareRenderer {
                    display.getRefreshRate(), wideColorDataspace.mNativeDataspace,
                    display.getAppVsyncOffsetNanos(), display.getPresentationDeadlineNanos());

            // Defensively clear out the context
            mContext = null;
            mDisplayInitialized = true;
        }

        private void initHintSession() {
            if (mContext == null) return;
            mPerformanceHintManager = mContext.getSystemService(PerformanceHintManager.class);
        }

        private void rotateBuffer() {
            nRotateProcessStatsBuffer();
            requestBuffer();
+8 −21
Original line number Diff line number Diff line
@@ -21,29 +21,16 @@ namespace android {
namespace uirenderer {

const std::array FrameInfoNames{
        "Flags",
        "FrameTimelineVsyncId",
        "IntendedVsync",
        "Vsync",
        "InputEventId",
        "HandleInputStart",
        "AnimationStart",
        "PerformTraversalsStart",
        "DrawStart",
        "FrameDeadline",
        "SyncQueued",
        "SyncStart",
        "IssueDrawCommandsStart",
        "SwapBuffers",
        "FrameCompleted",
        "DequeueBufferDuration",
        "QueueBufferDuration",
        "GpuCompleted",
        "SwapBuffersCompleted",
        "DisplayPresentTime",
        "Flags",          "FrameTimelineVsyncId",   "IntendedVsync",
        "Vsync",          "InputEventId",           "HandleInputStart",
        "AnimationStart", "PerformTraversalsStart", "DrawStart",
        "FrameDeadline",  "FrameStartTime",         "SyncQueued",
        "SyncStart",      "IssueDrawCommandsStart", "SwapBuffers",
        "FrameCompleted", "DequeueBufferDuration",  "QueueBufferDuration",
        "GpuCompleted",   "SwapBuffersCompleted",   "DisplayPresentTime",
};

static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 20,
static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 21,
              "Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");

void FrameInfo::importUiThreadInfo(int64_t* info) {
Loading