1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.os.Build;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 /**
25  * This class contains window content frame statistics. For example, a window content
26  * is rendred in frames when a view is scrolled. The frame statistics are a snapshot
27  * for the time interval from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
28  * <p>
29  * The key idea is that in order to provide a smooth user experience an application
30  * has to draw a frame at a specific time interval obtained by calling {@link
31  * #getRefreshPeriodNano()}. If the application does not render a frame every refresh
32  * period the user will see irregular UI transitions.
33  * </p>
34  * <p>
35  * An application posts a frame for presentation by synchronously rendering its contents
36  * in a buffer which is then posted or posting a buffer to which the application is
37  * asychronously rendering the content via GL. After the frame is posted and rendered
38  * (potentially asynchronosly) it is presented to the user. The time a frame was posted
39  * can be obtained via {@link #getFramePostedTimeNano(int)}, the time a frame content
40  * was rendered and ready for dsiplay (GL case) via {@link #getFrameReadyTimeNano(int)},
41  * and the time a frame was presented on the screen via {@link #getFramePresentedTimeNano(int)}.
42  * </p>
43  */
44 public final class WindowContentFrameStats extends FrameStats implements Parcelable {
45     private long[] mFramesPostedTimeNano;
46     private long[] mFramesReadyTimeNano;
47 
48     /**
49      * @hide
50      */
WindowContentFrameStats()51     public WindowContentFrameStats() {
52         /* do nothing */
53     }
54 
55     /**
56      * Initializes this isntance.
57      *
58      * @param refreshPeriodNano The display refresh period.
59      * @param framesPostedTimeNano The times in milliseconds for when the frame contents were posted.
60      * @param framesPresentedTimeNano The times in milliseconds for when the frame contents were presented.
61      * @param framesReadyTimeNano The times in milliseconds for when the frame contents were ready to be presented.
62      *
63      * @hide
64      */
65     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
init(long refreshPeriodNano, long[] framesPostedTimeNano, long[] framesPresentedTimeNano, long[] framesReadyTimeNano)66     public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
67             long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
68         mRefreshPeriodNano = refreshPeriodNano;
69         mFramesPostedTimeNano = framesPostedTimeNano;
70         mFramesPresentedTimeNano = framesPresentedTimeNano;
71         mFramesReadyTimeNano = framesReadyTimeNano;
72     }
73 
WindowContentFrameStats(Parcel parcel)74     private WindowContentFrameStats(Parcel parcel) {
75         mRefreshPeriodNano = parcel.readLong();
76         mFramesPostedTimeNano = parcel.createLongArray();
77         mFramesPresentedTimeNano = parcel.createLongArray();
78         mFramesReadyTimeNano = parcel.createLongArray();
79     }
80 
81     /**
82      * Get the time a frame at a given index was posted by the producer (e.g. the application).
83      * It is either explicitly set or defaulted to the time when the render buffer was posted.
84      * <p>
85      * <strong>Note:</strong> A frame can be posted and still it contents being rendered
86      * asynchronously in GL. To get the time the frame content was completely rendered and
87      * ready to display call {@link #getFrameReadyTimeNano(int)}.
88      * </p>
89      *
90      * @param index The frame index.
91      * @return The posted time in nanoseconds.
92      */
getFramePostedTimeNano(int index)93     public long getFramePostedTimeNano(int index) {
94         if (mFramesPostedTimeNano == null) {
95             throw new IndexOutOfBoundsException();
96         }
97         return mFramesPostedTimeNano[index];
98     }
99 
100     /**
101      * Get the time a frame at a given index was ready for presentation.
102      * <p>
103      * <strong>Note:</strong> A frame can be posted and still it contents being rendered
104      * asynchronously in GL. In such a case this is the time when the frame contents were
105      * completely rendered.
106      * </p>
107      *
108      * @param index The frame index.
109      * @return The ready time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
110      *         if the frame is not ready yet.
111      */
getFrameReadyTimeNano(int index)112     public long getFrameReadyTimeNano(int index) {
113         if (mFramesReadyTimeNano == null) {
114             throw new IndexOutOfBoundsException();
115         }
116         return mFramesReadyTimeNano[index];
117     }
118 
119     @Override
describeContents()120     public int describeContents() {
121         return 0;
122     }
123 
124     @Override
writeToParcel(Parcel parcel, int flags)125     public void writeToParcel(Parcel parcel, int flags) {
126         parcel.writeLong(mRefreshPeriodNano);
127         parcel.writeLongArray(mFramesPostedTimeNano);
128         parcel.writeLongArray(mFramesPresentedTimeNano);
129         parcel.writeLongArray(mFramesReadyTimeNano);
130     }
131 
132     @Override
toString()133     public String toString() {
134         StringBuilder builder = new StringBuilder();
135         builder.append("WindowContentFrameStats[");
136         builder.append("frameCount:" + getFrameCount());
137         builder.append(", fromTimeNano:" + getStartTimeNano());
138         builder.append(", toTimeNano:" + getEndTimeNano());
139         builder.append(']');
140         return builder.toString();
141     }
142 
143     public static final @android.annotation.NonNull Parcelable.Creator<WindowContentFrameStats> CREATOR =
144             new Creator<WindowContentFrameStats>() {
145                 @Override
146                 public WindowContentFrameStats createFromParcel(Parcel parcel) {
147                     return new WindowContentFrameStats(parcel);
148                 }
149 
150                 @Override
151                 public WindowContentFrameStats[] newArray(int size) {
152                     return new WindowContentFrameStats[size];
153                 }
154             };
155 }
156