/*
 * Copyright (C) 2014 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.view;

import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * This class contains window content frame statistics. For example, a window content
 * is rendred in frames when a view is scrolled. The frame statistics are a snapshot
 * for the time interval from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
 * <p>
 * The key idea is that in order to provide a smooth user experience an application
 * has to draw a frame at a specific time interval obtained by calling {@link
 * #getRefreshPeriodNano()}. If the application does not render a frame every refresh
 * period the user will see irregular UI transitions.
 * </p>
 * <p>
 * An application posts a frame for presentation by synchronously rendering its contents
 * in a buffer which is then posted or posting a buffer to which the application is
 * asychronously rendering the content via GL. After the frame is posted and rendered
 * (potentially asynchronosly) it is presented to the user. The time a frame was posted
 * can be obtained via {@link #getFramePostedTimeNano(int)}, the time a frame content
 * was rendered and ready for dsiplay (GL case) via {@link #getFrameReadyTimeNano(int)},
 * and the time a frame was presented on the screen via {@link #getFramePresentedTimeNano(int)}.
 * </p>
 */
public final class WindowContentFrameStats extends FrameStats implements Parcelable {
    private long[] mFramesPostedTimeNano;
    private long[] mFramesReadyTimeNano;

    /**
     * @hide
     */
    public WindowContentFrameStats() {
        /* do nothing */
    }

    /**
     * Initializes this isntance.
     *
     * @param refreshPeriodNano The display refresh period.
     * @param framesPostedTimeNano The times in milliseconds for when the frame contents were posted.
     * @param framesPresentedTimeNano The times in milliseconds for when the frame contents were presented.
     * @param framesReadyTimeNano The times in milliseconds for when the frame contents were ready to be presented.
     *
     * @hide
     */
    @UnsupportedAppUsage
    public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
            long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
        mRefreshPeriodNano = refreshPeriodNano;
        mFramesPostedTimeNano = framesPostedTimeNano;
        mFramesPresentedTimeNano = framesPresentedTimeNano;
        mFramesReadyTimeNano = framesReadyTimeNano;
    }

    private WindowContentFrameStats(Parcel parcel) {
        mRefreshPeriodNano = parcel.readLong();
        mFramesPostedTimeNano = parcel.createLongArray();
        mFramesPresentedTimeNano = parcel.createLongArray();
        mFramesReadyTimeNano = parcel.createLongArray();
    }

    /**
     * Get the time a frame at a given index was posted by the producer (e.g. the application).
     * It is either explicitly set or defaulted to the time when the render buffer was posted.
     * <p>
     * <strong>Note:</strong> A frame can be posted and still it contents being rendered
     * asynchronously in GL. To get the time the frame content was completely rendered and
     * ready to display call {@link #getFrameReadyTimeNano(int)}.
     * </p>
     *
     * @param index The frame index.
     * @return The posted time in nanoseconds.
     */
    public long getFramePostedTimeNano(int index) {
        if (mFramesPostedTimeNano == null) {
            throw new IndexOutOfBoundsException();
        }
        return mFramesPostedTimeNano[index];
    }

    /**
     * Get the time a frame at a given index was ready for presentation.
     * <p>
     * <strong>Note:</strong> A frame can be posted and still it contents being rendered
     * asynchronously in GL. In such a case this is the time when the frame contents were
     * completely rendered.
     * </p>
     *
     * @param index The frame index.
     * @return The ready time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
     *         if the frame is not ready yet.
     */
    public long getFrameReadyTimeNano(int index) {
        if (mFramesReadyTimeNano == null) {
            throw new IndexOutOfBoundsException();
        }
        return mFramesReadyTimeNano[index];
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeLong(mRefreshPeriodNano);
        parcel.writeLongArray(mFramesPostedTimeNano);
        parcel.writeLongArray(mFramesPresentedTimeNano);
        parcel.writeLongArray(mFramesReadyTimeNano);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("WindowContentFrameStats[");
        builder.append("frameCount:" + getFrameCount());
        builder.append(", fromTimeNano:" + getStartTimeNano());
        builder.append(", toTimeNano:" + getEndTimeNano());
        builder.append(']');
        return builder.toString();
    }

    public static final @android.annotation.NonNull Parcelable.Creator<WindowContentFrameStats> CREATOR =
            new Creator<WindowContentFrameStats>() {
                @Override
                public WindowContentFrameStats createFromParcel(Parcel parcel) {
                    return new WindowContentFrameStats(parcel);
                }

                @Override
                public WindowContentFrameStats[] newArray(int size) {
                    return new WindowContentFrameStats[size];
                }
            };
}
