• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.graphics;
18 
19 import android.annotation.NonNull;
20 import android.os.Handler;
21 
22 import com.android.internal.util.VirtualRefBasePtr;
23 
24 import java.lang.ref.WeakReference;
25 
26 /**
27  * Provides streaming access to frame stats information from HardwareRenderer to apps.
28  *
29  * @hide
30  */
31 @android.ravenwood.annotation.RavenwoodKeepWholeClass
32 public final class HardwareRendererObserver {
33     private final long[] mFrameMetrics;
34     private final Handler mHandler;
35     private final OnFrameMetricsAvailableListener mListener;
36     private VirtualRefBasePtr mNativePtr;
37 
38     /**
39      * Interface for clients that want frame timing information for each frame rendered.
40      * @hide
41      */
42     public interface OnFrameMetricsAvailableListener {
43         /**
44          * Called when information is available for the previously rendered frame.
45          *
46          * Reports can be dropped if this callback takes too long to execute, as the report producer
47          * cannot wait for the consumer to complete.
48          *
49          * It is highly recommended that clients copy the metrics array within this method
50          * and defer additional computation or storage to another thread to avoid unnecessarily
51          * dropping reports.
52          *
53          * @param dropCountSinceLastInvocation the number of reports dropped since the last time
54          * this callback was invoked.
55          */
onFrameMetricsAvailable(int dropCountSinceLastInvocation)56         void onFrameMetricsAvailable(int dropCountSinceLastInvocation);
57     }
58 
59     /**
60      * Creates a FrameMetricsObserver
61      *
62      * @param frameMetrics the available metrics. This array is reused on every call to the listener
63      * and thus <strong>this reference should only be used within the scope of the listener callback
64      * as data is not guaranteed to be valid outside the scope of that method</strong>.
65      * @param handler the Handler to use when invoking callbacks
66      */
HardwareRendererObserver(@onNull OnFrameMetricsAvailableListener listener, @NonNull long[] frameMetrics, @NonNull Handler handler, boolean waitForPresentTime)67     public HardwareRendererObserver(@NonNull OnFrameMetricsAvailableListener listener,
68             @NonNull long[] frameMetrics, @NonNull Handler handler, boolean waitForPresentTime) {
69         if (handler == null || handler.getLooper() == null) {
70             throw new NullPointerException("handler and its looper cannot be null");
71         }
72 
73         if (handler.getLooper().getQueue() == null) {
74             throw new IllegalStateException("invalid looper, null message queue\n");
75         }
76 
77         mFrameMetrics = frameMetrics;
78         mHandler = handler;
79         mListener = listener;
80         mNativePtr = new VirtualRefBasePtr(nCreateObserver(
81                 new WeakReference<>(this), waitForPresentTime));
82     }
83 
getNativeInstance()84     /*package*/ long getNativeInstance() {
85         return mNativePtr.get();
86     }
87 
notifyDataAvailable()88     private void notifyDataAvailable() {
89         mHandler.post(() -> {
90             boolean hasMoreData = true;
91             while (hasMoreData) {
92                 // a drop count of -1 is a sentinel that no more buffers are available
93                 int dropCount = nGetNextBuffer(mNativePtr.get(), mFrameMetrics);
94                 if (dropCount >= 0) {
95                     mListener.onFrameMetricsAvailable(dropCount);
96                 } else {
97                     hasMoreData = false;
98                 }
99             }
100         });
101     }
102 
103     /**
104      * called by native
105      * @hide
106      * @return true to keep listening, false if this is a dead observer
107      */
invokeDataAvailable(WeakReference<HardwareRendererObserver> weakObserver)108     static boolean invokeDataAvailable(WeakReference<HardwareRendererObserver> weakObserver) {
109         HardwareRendererObserver observer = weakObserver.get();
110         if (observer != null) {
111             observer.notifyDataAvailable();
112             return true;
113         }
114         return false;
115     }
116 
nCreateObserver(WeakReference<HardwareRendererObserver> observer, boolean waitForPresentTime)117     private static native long nCreateObserver(WeakReference<HardwareRendererObserver> observer,
118             boolean waitForPresentTime);
nGetNextBuffer(long nativePtr, long[] data)119     private static native int nGetNextBuffer(long nativePtr, long[] data);
120 }
121