• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 #pragma once
18 
19 #include <android-base/thread_annotations.h>
20 #include <binder/IBinder.h>
21 #include <renderengine/ExternalTexture.h>
22 #include <ui/GraphicBuffer.h>
23 #include <ui/Rect.h>
24 #include <utils/StrongPointer.h>
25 
26 #include <chrono>
27 #include <condition_variable>
28 #include <mutex>
29 #include <thread>
30 #include <unordered_map>
31 
32 #include "Scheduler/OneShotTimer.h"
33 
34 namespace android {
35 
36 class IRegionSamplingListener;
37 class Layer;
38 class Scheduler;
39 class SurfaceFlinger;
40 struct SamplingOffsetCallback;
41 
42 float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
43                  uint32_t orientation, const Rect& area);
44 
45 class RegionSamplingThread : public IBinder::DeathRecipient {
46 public:
47     struct TimingTunables {
48         // debug.sf.sampling_duration_ns
49         // When asynchronously collecting sample, the duration, at which the sampling should start
50         // before a vsync
51         std::chrono::nanoseconds mSamplingDuration;
52         // debug.sf.sampling_period_ns
53         // This is the maximum amount of time the luma recieving client
54         // should have to wait for a new luma value after a frame is updated. The inverse of this is
55         // roughly the sampling rate. Sampling system rounds up sub-vsync sampling period to vsync
56         // period.
57         std::chrono::nanoseconds mSamplingPeriod;
58         // debug.sf.sampling_timer_timeout_ns
59         // This is the interval at which the luma sampling system will check that the luma clients
60         // have up to date information. It defaults to the mSamplingPeriod.
61         std::chrono::nanoseconds mSamplingTimerTimeout;
62     };
63     struct EnvironmentTimingTunables : TimingTunables {
64         EnvironmentTimingTunables();
65     };
66     explicit RegionSamplingThread(SurfaceFlinger& flinger, const TimingTunables& tunables);
67     explicit RegionSamplingThread(SurfaceFlinger& flinger);
68 
69     ~RegionSamplingThread();
70 
71     // Add a listener to receive luma notifications. The luma reported via listener will
72     // report the median luma for the layers under the stopLayerHandle, in the samplingArea region.
73     void addListener(const Rect& samplingArea, const wp<Layer>& stopLayer,
74                      const sp<IRegionSamplingListener>& listener);
75     // Remove the listener to stop receiving median luma notifications.
76     void removeListener(const sp<IRegionSamplingListener>& listener);
77 
78     // Notifies sampling engine that composition is done and new content is
79     // available, and the deadline for the sampling work on the main thread to
80     // be completed without eating the budget of another frame.
81     void onCompositionComplete(
82             std::optional<std::chrono::steady_clock::time_point> samplingDeadline);
83 
84 private:
85     struct Descriptor {
86         Rect area = Rect::EMPTY_RECT;
87         wp<Layer> stopLayer;
88         sp<IRegionSamplingListener> listener;
89     };
90 
91     struct WpHash {
operatorWpHash92         size_t operator()(const wp<IBinder>& p) const {
93             return std::hash<IBinder*>()(p.unsafe_get());
94         }
95     };
96     std::vector<float> sampleBuffer(
97             const sp<GraphicBuffer>& buffer, const Point& leftTop,
98             const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation);
99 
100     void doSample(std::optional<std::chrono::steady_clock::time_point> samplingDeadline);
101     void binderDied(const wp<IBinder>& who) override;
102     void checkForStaleLuma();
103 
104     void captureSample();
105     void threadMain();
106 
107     SurfaceFlinger& mFlinger;
108     const TimingTunables mTunables;
109     scheduler::OneShotTimer mIdleTimer;
110 
111     std::thread mThread;
112 
113     std::mutex mThreadControlMutex;
114     std::condition_variable_any mCondition;
115     bool mRunning GUARDED_BY(mThreadControlMutex) = true;
116     bool mSampleRequested GUARDED_BY(mThreadControlMutex) = false;
117     std::optional<std::chrono::steady_clock::time_point> mSampleRequestTime
118             GUARDED_BY(mThreadControlMutex);
119     std::chrono::steady_clock::time_point mLastSampleTime GUARDED_BY(mThreadControlMutex);
120 
121     std::mutex mSamplingMutex;
122     std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex);
123     std::shared_ptr<renderengine::ExternalTexture> mCachedBuffer GUARDED_BY(mSamplingMutex) =
124             nullptr;
125 };
126 
127 } // namespace android
128