/*
 * Copyright (C) 2018 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 android.graphics;

import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.TimeUtils;
import android.view.IGraphicsStats;
import android.view.IGraphicsStatsCallback;
import android.view.NativeVectorDrawableAnimator;
import android.view.PixelCopy;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.TextureLayer;
import android.view.animation.AnimationUtils;

import java.io.File;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;

import sun.misc.Cleaner;

/**
 * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
 * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
 * HardwareRenderer instances as desired.</p>
 *
 * <h3>Resources & lifecycle</h3>
 *
 * <p>All HardwareRenderer instances share a common render thread. The render thread contains
 * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
 * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
 * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
 * is to have a HardwareRenderer instance for every active {@link Surface}. For example
 * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
 * of which may be drawing at the same time.</p>
 *
 * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
 * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
 * consumers such as {@link android.view.SurfaceView},
 * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
 * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
 * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
 * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
 * Failure to do so will cause the render thread to stall on that surface, blocking all
 * HardwareRenderer instances.</p>
 */
public class HardwareRenderer {
    private static final String LOG_TAG = "HardwareRenderer";

    // Keep in sync with DrawFrameTask.h SYNC_* flags
    /**
     * Nothing interesting to report. Sync & draw kicked off
     */
    public static final int SYNC_OK = 0;

    /**
     * The renderer is requesting a redraw. This can occur if there's an animation that's running
     * in the RenderNode tree and the hardware renderer is unable to self-animate.
     *
     * <p>If this is returned from syncAndDraw the expectation is that syncAndDraw
     * will be called again on the next vsync signal.
     */
    public static final int SYNC_REDRAW_REQUESTED = 1 << 0;

    /**
     * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
     * This can happen if {@link Surface#release()} was called. The user should no longer
     * attempt to call syncAndDraw until a new surface has been provided by calling
     * setSurface.
     *
     * <p>Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
     */
    public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;

    /**
     * The hardware renderer has been set to a "stopped" state. If this is returned then the
     * rendering content has been synced, however a frame was not produced.
     */
    public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;

    /**
     * The content was synced but the renderer has declined to produce a frame in this vsync
     * interval. This can happen if a frame was already drawn in this vsync or if the renderer
     * is outrunning the frame consumer. The renderer will internally re-schedule itself
     * to render a frame in the next vsync signal, so the caller does not need to do anything
     * in response to this signal.
     */
    public static final int SYNC_FRAME_DROPPED = 1 << 3;

    /** @hide */
    @IntDef(value = {
            SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
            SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SyncAndDrawResult {
    }

    /** @hide */
    public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
    /** @hide */
    public static final int FLAG_DUMP_RESET = 1 << 1;
    /** @hide */
    public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;

    /** @hide */
    @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
            FLAG_DUMP_FRAMESTATS,
            FLAG_DUMP_RESET
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DumpFlags {
    }

    /**
     * Name of the file that holds the shaders cache.
     */
    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";

    private final long mNativeProxy;
    /** @hide */
    protected RenderNode mRootNode;
    private boolean mOpaque = true;
    private boolean mForceDark = false;
    private boolean mIsWideGamut = false;

    /**
     * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
     * to opaque with no light source configured.
     */
    public HardwareRenderer() {
        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
        mRootNode.setClipToBounds(false);
        mNativeProxy = nCreateProxy(!mOpaque, mIsWideGamut, mRootNode.mNativeRenderNode);
        if (mNativeProxy == 0) {
            throw new OutOfMemoryError("Unable to create hardware renderer");
        }
        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
        ProcessInitializer.sInstance.init(mNativeProxy);
    }

    /**
     * Destroys the rendering context of this HardwareRenderer. This destroys the resources
     * associated with this renderer and releases the currently set {@link Surface}. This must
     * be called when this HardwareRenderer is no longer needed.
     *
     * <p>The renderer may be restored from this state by setting a new {@link Surface}, setting
     * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
     * rendering by issuing a new {@link FrameRenderRequest}.
     *
     * <p>It is recommended to call this in response to callbacks such as
     * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
     *
     * <p>Note that if there are any outstanding frame commit callbacks they may never being
     * invoked if the frame was deferred to a later vsync.
     */
    public void destroy() {
        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
    }

    /**
     * Sets a name for this renderer. This is used to identify this renderer instance
     * when reporting debug information such as the per-window frame time metrics
     * reported by 'adb shell dumpsys gfxinfo [package] framestats'
     *
     * @param name The debug name to use for this HardwareRenderer instance
     */
    public void setName(@NonNull String name) {
        nSetName(mNativeProxy, name);
    }

    /**
     * Sets the center of the light source. The light source point controls the directionality
     * and shape of shadows rendered by RenderNode Z & elevation.
     *
     * <p>The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
     * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
     *
     * <p>The light source should be setup both as part of initial configuration, and whenever
     * the window moves to ensure the light source stays anchored in display space instead
     * of in window space.
     *
     * <p>This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
     * before shadows will work.
     *
     * @param lightX      The X position of the light source
     * @param lightY      The Y position of the light source
     * @param lightZ      The Z position of the light source. Must be >= 0.
     * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
     *                    larger radius will have softer shadows.
     */
    public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
            float lightRadius) {
        validateFinite(lightX, "lightX");
        validateFinite(lightY, "lightY");
        validatePositive(lightZ, "lightZ");
        validatePositive(lightRadius, "lightRadius");
        nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
    }

    /**
     * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
     * has max alpha, and ramps down from the values provided to zero.
     *
     * <p>These values are typically provided by the current theme, see
     * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
     *
     * <p>This must be set at least once along with
     * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
     *
     * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
     *                           is 0.039f.
     * @param spotShadowAlpha    The alpha for the spot shadow. If unsure, a reasonable default is
     *                           0.19f.
     */
    public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
            @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
        validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
        validateAlpha(spotShadowAlpha, "spotShadowAlpha");
        nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
    }

    /**
     * Sets the content root to render. It is not necessary to call this whenever the content
     * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
     * contained within the content node, will be applied whenever a new {@link FrameRenderRequest}
     * is issued via {@link #createRenderRequest()} and {@link FrameRenderRequest#syncAndDraw()}.
     *
     * @param content The content to set as the root RenderNode. If null the content root is removed
     *                and the renderer will draw nothing.
     */
    public void setContentRoot(@Nullable RenderNode content) {
        RecordingCanvas canvas = mRootNode.beginRecording();
        if (content != null) {
            canvas.drawRenderNode(content);
        }
        mRootNode.endRecording();
    }

    /**
     * <p>The surface to render into. The surface is assumed to be associated with the display and
     * as such is still driven by vsync signals such as those from
     * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
     * the display's (typically 60hz).</p>
     *
     * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
     * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
     * consumers such as {@link android.view.SurfaceView},
     * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
     * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
     * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
     * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
     * Failure to do so will cause the render thread to stall on that surface, blocking all
     * HardwareRenderer instances.</p>
     *
     * @param surface The surface to render into. If null then rendering will be stopped. If
     *                non-null then {@link Surface#isValid()} must be true.
     */
    public void setSurface(@Nullable Surface surface) {
        setSurface(surface, false);
    }

    /**
     * See {@link #setSurface(Surface)}
     *
     * @hide
     * @param discardBuffer determines whether the surface will attempt to preserve its contents
     *                      between frames.  If set to true the renderer will attempt to preserve
     *                      the contents of the buffer between frames if the implementation allows
     *                      it.  If set to false no attempt will be made to preserve the buffer's
     *                      contents between frames.
     */
    public void setSurface(@Nullable Surface surface, boolean discardBuffer) {
        if (surface != null && !surface.isValid()) {
            throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
        }
        nSetSurface(mNativeProxy, surface, discardBuffer);
    }

    /**
     * Sets the parameters that can be used to control a render request for a
     * {@link HardwareRenderer}. This is not thread-safe and must not be held on to for longer
     * than a single frame request.
     */
    public final class FrameRenderRequest {
        private FrameInfo mFrameInfo = new FrameInfo();
        private boolean mWaitForPresent;

        private FrameRenderRequest() { }

        private void reset() {
            mWaitForPresent = false;
            // Default to the animation time which, if choreographer is in play, will default to the
            // current vsync time. Otherwise it will be 'now'.
            mRenderRequest.setVsyncTime(
                    AnimationUtils.currentAnimationTimeMillis() * TimeUtils.NANOS_PER_MS);
        }

        /** @hide */
        public void setFrameInfo(FrameInfo info) {
            System.arraycopy(info.frameInfo, 0, mFrameInfo.frameInfo, 0, info.frameInfo.length);
        }

        /**
         * Sets the vsync time that represents the start point of this frame. Typically this
         * comes from {@link android.view.Choreographer.FrameCallback}. Other compatible time
         * sources include {@link System#nanoTime()}, however if the result is being displayed
         * on-screen then using {@link android.view.Choreographer} is strongly recommended to
         * ensure smooth animations.
         *
         * <p>If the clock source is not from a CLOCK_MONOTONIC source then any animations driven
         * directly by RenderThread will not be synchronized properly with the current frame.
         *
         * @param vsyncTime The vsync timestamp for this frame. The timestamp is in nanoseconds
         *                  and should come from a CLOCK_MONOTONIC source.
         *
         * @return this instance
         */
        public @NonNull FrameRenderRequest setVsyncTime(long vsyncTime) {
            mFrameInfo.setVsync(vsyncTime, vsyncTime);
            mFrameInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
            return this;
        }

        /**
         * Adds a frame commit callback. This callback will be invoked when the current rendering
         * content has been rendered into a frame and submitted to the swap chain. The frame may
         * not currently be visible on the display when this is invoked, but it has been submitted.
         * This callback is useful in combination with {@link PixelCopy} to capture the current
         * rendered content of the UI reliably.
         *
         * @param executor The executor to run the callback on. It is strongly recommended that
         *                 this executor post to a different thread, as the calling thread is
         *                 highly sensitive to being blocked.
         * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
         *                            Will be invoked on the given {@link Executor}.
         *
         * @return this instance
         */
        public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
                @NonNull Runnable frameCommitCallback) {
            setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback));
            return this;
        }

        /**
         * Sets whether or not {@link #syncAndDraw()} should block until the frame has been
         * presented. If this is true and {@link #syncAndDraw()} does not return
         * {@link #SYNC_FRAME_DROPPED} or an error then when {@link #syncAndDraw()} has returned
         * the frame has been submitted to the {@link Surface}. The default and typically
         * recommended value is false, as blocking for present will prevent pipelining from
         * happening, reducing overall throughput. This is useful for situations such as
         * {@link SurfaceHolder.Callback2#surfaceRedrawNeeded(SurfaceHolder)} where it is desired
         * to block until a frame has been presented to ensure first-frame consistency with
         * other Surfaces.
         *
         * @param shouldWait If true the next call to {@link #syncAndDraw()} will block until
         *                   completion.
         * @return this instance
         */
        public @NonNull FrameRenderRequest setWaitForPresent(boolean shouldWait) {
            mWaitForPresent = shouldWait;
            return this;
        }

        /**
         * Syncs the RenderNode tree to the render thread and requests a frame to be drawn. This
         * {@link FrameRenderRequest} instance should no longer be used after calling this method.
         * The system internally may reuse instances of {@link FrameRenderRequest} to reduce
         * allocation churn.
         *
         * @return The result of the sync operation.
         */
        @SyncAndDrawResult
        public int syncAndDraw() {
            int syncResult = syncAndDrawFrame(mFrameInfo);
            if (mWaitForPresent && (syncResult & SYNC_FRAME_DROPPED) == 0) {
                fence();
            }
            return syncResult;
        }
    }

    private FrameRenderRequest mRenderRequest = new FrameRenderRequest();

    /**
     * Returns a {@link FrameRenderRequest} that can be used to render a new frame. This is used
     * to synchronize the RenderNode content provided by {@link #setContentRoot(RenderNode)} with
     * the RenderThread and then renders a single frame to the Surface set with
     * {@link #setSurface(Surface)}.
     *
     * @return An instance of {@link FrameRenderRequest}. The instance may be reused for every
     * frame, so the caller should not hold onto it for longer than a single render request.
     */
    public @NonNull FrameRenderRequest createRenderRequest() {
        mRenderRequest.reset();
        return mRenderRequest;
    }

    /**
     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
     *
     * @hide
     */
    @SyncAndDrawResult
    public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
        return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
    }

    /**
     * Suspends any current rendering into the surface but do not do any destruction. This
     * is useful to temporarily suspend using the active Surface in order to do any Surface
     * mutations necessary.
     *
     * <p>Any subsequent draws will override the pause, resuming normal operation.
     *
     * @return true if there was an outstanding render request, false otherwise. If this is true
     * the caller should ensure that {@link #createRenderRequest()}
     * and {@link FrameRenderRequest#syncAndDraw()} is called at the soonest
     * possible time to resume normal operation.
     *
     * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
     * Surface before getting a new one. However things like SurfaceView will ensure that
     * the old surface remains un-destroyed until after a new frame has been produced with
     * the new surface.
     * @hide
     */
    public boolean pause() {
        return nPause(mNativeProxy);
    }

    /**
     * Hard stops rendering into the surface. If the renderer is stopped it will
     * block any attempt to render. Calls to {@link FrameRenderRequest#syncAndDraw()} will
     * still sync over the latest rendering content, however they will not render and instead
     * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
     *
     * <p>If false is passed then rendering will resume as normal. Any pending rendering requests
     * will produce a new frame at the next vsync signal.
     *
     * <p>This is useful in combination with lifecycle events such as {@link Activity#onStop()}
     * and {@link Activity#onStart()}.
     *
     * @param stopped true to stop all rendering, false to resume
     * @hide
     */
    public void setStopped(boolean stopped) {
        nSetStopped(mNativeProxy, stopped);
    }

    /**
     * Hard stops rendering into the surface. If the renderer is stopped it will
     * block any attempt to render. Calls to {@link FrameRenderRequest#syncAndDraw()} will
     * still sync over the latest rendering content, however they will not render and instead
     * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
     *
     * <p>This is useful in combination with lifecycle events such as {@link Activity#onStop()}.
     * See {@link #start()} for resuming rendering.
     */
    public void stop() {
        nSetStopped(mNativeProxy, true);
    }

    /**
     * Resumes rendering into the surface. Any pending rendering requests
     * will produce a new frame at the next vsync signal.
     *
     * <p>This is useful in combination with lifecycle events such as {@link Activity#onStart()}.
     * See {@link #stop()} for stopping rendering.
     */
    public void start() {
        nSetStopped(mNativeProxy, false);
    }

    /**
     * Destroys all the display lists associated with the current rendering content.
     * This includes releasing a reference to the current content root RenderNode. It will
     * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
     * rendering after calling this, along with re-recording the display lists for the
     * RenderNode tree.
     *
     * <p>It is recommended, but not necessary, to use this in combination with lifecycle events
     * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
     * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
     * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
     *
     * See also {@link #stop()}.
     */
    public void clearContent() {
        nDestroyHardwareResources(mNativeProxy);
    }

    /**
     * Whether or not the force-dark feature should be used for this renderer.
     * @hide
     */
    public boolean setForceDark(boolean enable) {
        if (mForceDark != enable) {
            mForceDark = enable;
            nSetForceDark(mNativeProxy, enable);
            return true;
        }
        return false;
    }

    /**
     * Allocate buffers ahead of time to avoid allocation delays during rendering.
     *
     * <p>Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
     * memory usage of Surfaces that render rarely or never hit triple buffering. However
     * for UI it can result in a slight bit of jank on first launch. This hint will
     * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
     * necessary for typical rendering.
     *
     * <p>Must be called after a {@link Surface} has been set.
     *
     * TODO: Figure out if we even need/want this. Should HWUI just be doing this in response
     * to setSurface anyway? Vulkan swapchain makes this murky, so delay making it public
     * @hide
     */
    public void allocateBuffers() {
        nAllocateBuffers(mNativeProxy);
    }

    /**
     * Notifies the hardware renderer that a call to {@link FrameRenderRequest#syncAndDraw()} will
     * be coming soon. This is used to help schedule when RenderThread-driven animations will
     * happen as the renderer wants to avoid producing more than one frame per vsync signal.
     */
    public void notifyFramePending() {
        nNotifyFramePending(mNativeProxy);
    }

    /**
     * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
     *
     * <p>If the renderer is set to opaque it is the app's responsibility to ensure that the
     * content renders to every pixel of the Surface, otherwise corruption may result. Note that
     * this includes ensuring that the first draw of any given pixel does not attempt to blend
     * against the destination. If this is false then the hardware renderer will clear to
     * transparent at the start of every frame.
     *
     * @param opaque true if the content rendered is opaque, false if the renderer should clear
     *               to transparent before rendering
     */
    public void setOpaque(boolean opaque) {
        if (mOpaque != opaque) {
            mOpaque = opaque;
            nSetOpaque(mNativeProxy, mOpaque);
        }
    }

    /**
     * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
     *
     * @return true if the renderer is opaque, false otherwise
     */
    public boolean isOpaque() {
        return mOpaque;
    }

    /** @hide */
    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
        nSetFrameCompleteCallback(mNativeProxy, callback);
    }

    /**
     * TODO: Public API this?
     *
     * @hide
     */
    public void addObserver(HardwareRendererObserver observer) {
        nAddObserver(mNativeProxy, observer.getNativeInstance());
    }

    /**
     * TODO: Public API this?
     *
     * @hide
     */
    public void removeObserver(HardwareRendererObserver observer) {
        nRemoveObserver(mNativeProxy, observer.getNativeInstance());
    }

    /**
     * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
     * will be wide gamut depends on the hardware support for such rendering.
     *
     * @param wideGamut true if this renderer should render in wide gamut, false if it should
     *                  render in sRGB
     *                  TODO: Figure out color...
     * @hide
     */
    public void setWideGamut(boolean wideGamut) {
        mIsWideGamut = wideGamut;
        nSetWideGamut(mNativeProxy, wideGamut);
    }

    /**
     * Blocks until all previously queued work has completed.
     *
     * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
     * better
     *
     * @hide
     */
    public void fence() {
        nFence(mNativeProxy);
    }

    /** @hide */
    public void registerAnimatingRenderNode(RenderNode animator) {
        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
    }

    /** @hide */
    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
                animator.getAnimatorNativePtr());
    }

    /**
     * Prevents any further drawing until {@link FrameRenderRequest#syncAndDraw()} is called.
     * This is a signal that the contents of the RenderNode tree are no longer safe to play back.
     * In practice this usually means that there are Functor pointers in the
     * display list that are no longer valid.
     *
     * TODO: Can we get webview off of this?
     *
     * @hide
     */
    public void stopDrawing() {
        nStopDrawing(mNativeProxy);
    }

    /**
     * Creates a new hardware layer. A hardware layer built by calling this
     * method will be treated as a texture layer, instead of as a render target.
     *
     * @return A hardware layer
     * @hide
     */
    public TextureLayer createTextureLayer() {
        long layer = nCreateTextureLayer(mNativeProxy);
        return TextureLayer.adoptTextureLayer(this, layer);
    }

    /**
     * Detaches the layer's surface texture from the GL context and releases
     * the texture id
     *
     * @hide
     */
    public void detachSurfaceTexture(long hardwareLayer) {
        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
    }


    /** @hide */
    public void buildLayer(RenderNode node) {
        if (node.hasDisplayList()) {
            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
        }
    }

    /** @hide */
    public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
        return nCopyLayerInto(mNativeProxy, layer.getDeferredLayerUpdater(),
            bitmap.getNativeInstance());
    }

    /**
     * Indicates that the specified hardware layer needs to be updated
     * as soon as possible.
     *
     * @param layer The hardware layer that needs an update
     * @hide
     */
    public void pushLayerUpdate(TextureLayer layer) {
        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
    }

    /**
     * Tells the HardwareRenderer that the layer is destroyed. The renderer
     * should remove the layer from any update queues.
     *
     * @hide
     */
    public void onLayerDestroyed(TextureLayer layer) {
        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
    }

    /** @hide */
    public void setFrameCallback(FrameDrawingCallback callback) {
        nSetFrameCallback(mNativeProxy, callback);
    }

    /**
     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
     * rendernode of the UI thread.
     *
     * @param node       The node to add.
     * @param placeFront If true, the render node will be placed in front of the content node,
     *                   otherwise behind the content node.
     * @hide
     */
    public void addRenderNode(RenderNode node, boolean placeFront) {
        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
    }

    /**
     * Only especially added render nodes can be removed.
     *
     * @param node The node which was added via addRenderNode which should get removed again.
     * @hide
     */
    public void removeRenderNode(RenderNode node) {
        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
    }

    /**
     * Draws a particular render node. If the node is not the content node, only the additional
     * nodes will get drawn and the content remains untouched.
     *
     * @param node The node to be drawn.
     * @hide
     */
    public void drawRenderNode(RenderNode node) {
        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
    }

    /**
     * Loads system properties used by the renderer. This method is invoked
     * whenever system properties are modified. Implementations can use this
     * to trigger live updates of the renderer based on properties.
     *
     * @return True if a property has changed.
     * @hide
     */
    public boolean loadSystemProperties() {
        return nLoadSystemProperties(mNativeProxy);
    }

    /**
     * @hide
     */
    public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
        nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
    }

    /**
     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
     * will be prevented to overdraw this area. It will be synchronized with the draw call.
     * This should be updated in the content view's draw call.
     *
     * @param left   The left side of the protected bounds.
     * @param top    The top side of the protected bounds.
     * @param right  The right side of the protected bounds.
     * @param bottom The bottom side of the protected bounds.
     * @hide
     */
    public void setContentDrawBounds(int left, int top, int right, int bottom) {
        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
    }

    /** @hide */
    public void setPictureCaptureCallback(@Nullable PictureCapturedCallback callback) {
        nSetPictureCaptureCallback(mNativeProxy, callback);
    }

    /** @hide */
    public boolean isWideGamut() {
        return mIsWideGamut;
    }

    /** called by native */
    static void invokePictureCapturedCallback(long picturePtr, PictureCapturedCallback callback) {
        Picture picture = new Picture(picturePtr);
        callback.onPictureCaptured(picture);
    }

    /**
     * Interface used to receive callbacks when a frame is being drawn.
     *
     * @hide
     */
    public interface FrameDrawingCallback {
        /**
         * Invoked during a frame drawing.
         *
         * @param frame The id of the frame being drawn.
         */
        void onFrameDraw(long frame);
    }

    /**
     * Interface used to be notified when a frame has finished rendering
     *
     * @hide
     */
    public interface FrameCompleteCallback {
        /**
         * Invoked after a frame draw
         *
         * @param frameNr The id of the frame that was drawn.
         */
        void onFrameComplete(long frameNr);
    }

    /**
     * Interface for listening to picture captures
     * @hide
     */
    public interface PictureCapturedCallback {
        /** @hide */
        void onPictureCaptured(Picture picture);
    }

    private static void validateAlpha(float alpha, String argumentName) {
        if (!(alpha >= 0.0f && alpha <= 1.0f)) {
            throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
                    + alpha + " is not in the range of 0.0f to 1.0f");
        }
    }

    private static void validatePositive(float f, String argumentName) {
        if (!(Float.isFinite(f) && f >= 0.0f)) {
            throw new IllegalArgumentException(argumentName
                    + " must be a finite positive, given=" + f);
        }
    }

    private static void validateFinite(float f, String argumentName) {
        if (!Float.isFinite(f)) {
            throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
        }
    }

    /** @hide */
    public static void invokeFunctor(long functor, boolean waitForCompletion) {
        nInvokeFunctor(functor, waitForCompletion);
    }

    /**
     * b/68769804: For low FPS experiments.
     *
     * @hide
     */
    public static void setFPSDivisor(int divisor) {
        nHackySetRTAnimationsEnabled(divisor <= 1);
    }

    /**
     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
     * called before any OpenGL context is created.
     *
     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
     * @hide
     */
    public static void setContextPriority(int priority) {
        nSetContextPriority(priority);
    }

    /**
     * Sets whether or not high contrast text rendering is enabled. The setting is global
     * but only affects content rendered after the change is made.
     *
     * @hide
     */
    public static void setHighContrastText(boolean highContrastText) {
        nSetHighContrastText(highContrastText);
    }

    /**
     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
     *
     * @hide
     */
    public static void setIsolatedProcess(boolean isIsolated) {
        nSetIsolatedProcess(isIsolated);
    }

    /**
     * If set extra graphics debugging abilities will be enabled such as dumping skp
     *
     * @hide
     */
    public static void setDebuggingEnabled(boolean enable) {
        nSetDebuggingEnabled(enable);
    }

    /** @hide */
    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
        if (srcRect == null) {
            // Empty rect means entire surface
            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap.getNativeInstance());
        } else {
            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
                    srcRect.right, srcRect.bottom, bitmap.getNativeInstance());
        }
    }

    /**
     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
     * not the RenderNode from a View.
     *
     * @hide
     **/
    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
    }

    /**
     * Invoke this method when the system is running out of memory. This
     * method will attempt to recover as much memory as possible, based on
     * the specified hint.
     *
     * @param level Hint about the amount of memory that should be trimmed,
     *              see {@link android.content.ComponentCallbacks}
     * @hide
     */
    public static void trimMemory(int level) {
        nTrimMemory(level);
    }

    /** @hide */
    public static void overrideProperty(@NonNull String name, @NonNull String value) {
        if (name == null || value == null) {
            throw new IllegalArgumentException("name and value must be non-null");
        }
        nOverrideProperty(name, value);
    }

    /**
     * Sets the directory to use as a persistent storage for threaded rendering
     * resources.
     *
     * @param cacheDir A directory the current process can write to
     * @hide
     */
    public static void setupDiskCache(File cacheDir) {
        setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
    }

    /** @hide */
    public static void setPackageName(String packageName) {
        ProcessInitializer.sInstance.setPackageName(packageName);
    }

    private static final class DestroyContextRunnable implements Runnable {
        private final long mNativeInstance;

        DestroyContextRunnable(long nativeInstance) {
            mNativeInstance = nativeInstance;
        }

        @Override
        public void run() {
            nDeleteProxy(mNativeInstance);
        }
    }

    private static class ProcessInitializer {
        static ProcessInitializer sInstance = new ProcessInitializer();

        private boolean mInitialized = false;

        private String mPackageName;
        private IGraphicsStats mGraphicsStatsService;
        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
            @Override
            public void onRotateGraphicsStatsBuffer() throws RemoteException {
                rotateBuffer();
            }
        };

        private ProcessInitializer() {
        }

        synchronized void setPackageName(String name) {
            if (mInitialized) return;
            mPackageName = name;
        }

        synchronized void init(long renderProxy) {
            if (mInitialized) return;
            mInitialized = true;

            initSched(renderProxy);
            initGraphicsStats();
        }

        private void initSched(long renderProxy) {
            try {
                int tid = nGetRenderThreadTid(renderProxy);
                ActivityManager.getService().setRenderThread(tid);
            } catch (Throwable t) {
                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
            }
        }

        private void initGraphicsStats() {
            if (mPackageName == null) return;

            try {
                IBinder binder = ServiceManager.getService("graphicsstats");
                if (binder == null) return;
                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
                requestBuffer();
            } catch (Throwable t) {
                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
            }
        }

        private void rotateBuffer() {
            nRotateProcessStatsBuffer();
            requestBuffer();
        }

        private void requestBuffer() {
            try {
                ParcelFileDescriptor pfd = mGraphicsStatsService
                        .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
                nSetProcessStatsBuffer(pfd.getFd());
                pfd.close();
            } catch (Throwable t) {
                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
            }
        }
    }

    /**
     * @hide
     */
    public static native void disableVsync();

    /**
     * Start render thread and initialize EGL or Vulkan.
     *
     * Initializing EGL involves loading and initializing the graphics driver. Some drivers take
     * several 10s of milliseconds to do this, so doing it on-demand when an app tries to render
     * its first frame adds directly to user-visible app launch latency.
     *
     * Should only be called after GraphicsEnvironment.chooseDriver().
     * @hide
     */
    public static native void preload();

    /** @hide */
    protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);

    private static native void nRotateProcessStatsBuffer();

    private static native void nSetProcessStatsBuffer(int fd);

    private static native int nGetRenderThreadTid(long nativeProxy);

    private static native long nCreateRootRenderNode();

    private static native long nCreateProxy(boolean translucent, boolean isWideGamut,
            long rootRenderNode);

    private static native void nDeleteProxy(long nativeProxy);

    private static native boolean nLoadSystemProperties(long nativeProxy);

    private static native void nSetName(long nativeProxy, String name);

    private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer);

    private static native boolean nPause(long nativeProxy);

    private static native void nSetStopped(long nativeProxy, boolean stopped);

    private static native void nSetLightGeometry(long nativeProxy,
            float lightX, float lightY, float lightZ, float lightRadius);

    private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
            float spotShadowAlpha);

    private static native void nSetOpaque(long nativeProxy, boolean opaque);

    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);

    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);

    private static native void nDestroy(long nativeProxy, long rootRenderNode);

    private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
            long animatingNode);

    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);

    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);

    private static native long nCreateTextureLayer(long nativeProxy);

    private static native void nBuildLayer(long nativeProxy, long node);

    private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmapHandle);

    private static native void nPushLayerUpdate(long nativeProxy, long layer);

    private static native void nCancelLayerUpdate(long nativeProxy, long layer);

    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);

    private static native void nDestroyHardwareResources(long nativeProxy);

    private static native void nTrimMemory(int level);

    private static native void nOverrideProperty(String name, String value);

    private static native void nFence(long nativeProxy);

    private static native void nStopDrawing(long nativeProxy);

    private static native void nNotifyFramePending(long nativeProxy);

    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
            @DumpFlags int dumpFlags);

    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
            boolean placeFront);

    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);

    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);

    private static native void nSetContentDrawBounds(long nativeProxy, int left,
            int top, int right, int bottom);

    private static native void nSetPictureCaptureCallback(long nativeProxy,
            PictureCapturedCallback callback);

    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);

    private static native void nSetFrameCompleteCallback(long nativeProxy,
            FrameCompleteCallback callback);

    private static native void nAddObserver(long nativeProxy, long nativeObserver);

    private static native void nRemoveObserver(long nativeProxy, long nativeObserver);

    private static native int nCopySurfaceInto(Surface surface,
            int srcLeft, int srcTop, int srcRight, int srcBottom, long bitmapHandle);

    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);

    private static native void nSetHighContrastText(boolean enabled);

    // For temporary experimentation b/66945974
    private static native void nHackySetRTAnimationsEnabled(boolean enabled);

    private static native void nSetDebuggingEnabled(boolean enabled);

    private static native void nSetIsolatedProcess(boolean enabled);

    private static native void nSetContextPriority(int priority);

    private static native void nAllocateBuffers(long nativeProxy);

    private static native void nSetForceDark(long nativeProxy, boolean enabled);
}
