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 <chrono> 20 #include <condition_variable> 21 #include <mutex> 22 #include <thread> 23 #include <unordered_map> 24 25 #include <android-base/thread_annotations.h> 26 #include <binder/IBinder.h> 27 #include <ui/GraphicBuffer.h> 28 #include <ui/Rect.h> 29 #include <utils/StrongPointer.h> 30 #include "Scheduler/IdleTimer.h" 31 32 namespace android { 33 34 class IRegionSamplingListener; 35 class Layer; 36 class Scheduler; 37 class SurfaceFlinger; 38 struct SamplingOffsetCallback; 39 40 float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride, 41 uint32_t orientation, const Rect& area); 42 43 class RegionSamplingThread : public IBinder::DeathRecipient { 44 public: 45 struct TimingTunables { 46 // debug.sf.sampling_offset_ns 47 // When asynchronously collecting sample, the offset, from zero phase in the vsync timeline 48 // at which the sampling should start. 49 std::chrono::nanoseconds mSamplingOffset; 50 // debug.sf.sampling_period_ns 51 // This is the maximum amount of time the luma recieving client 52 // should have to wait for a new luma value after a frame is updated. The inverse of this is 53 // roughly the sampling rate. Sampling system rounds up sub-vsync sampling period to vsync 54 // period. 55 std::chrono::nanoseconds mSamplingPeriod; 56 // debug.sf.sampling_timer_timeout_ns 57 // This is the interval at which the luma sampling system will check that the luma clients 58 // have up to date information. It defaults to the mSamplingPeriod. 59 std::chrono::nanoseconds mSamplingTimerTimeout; 60 }; 61 struct EnvironmentTimingTunables : TimingTunables { 62 EnvironmentTimingTunables(); 63 }; 64 explicit RegionSamplingThread(SurfaceFlinger& flinger, Scheduler& scheduler, 65 const TimingTunables& tunables); 66 explicit RegionSamplingThread(SurfaceFlinger& flinger, Scheduler& scheduler); 67 68 ~RegionSamplingThread(); 69 70 // Add a listener to receive luma notifications. The luma reported via listener will 71 // report the median luma for the layers under the stopLayerHandle, in the samplingArea region. 72 void addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, 73 const sp<IRegionSamplingListener>& listener); 74 // Remove the listener to stop receiving median luma notifications. 75 void removeListener(const sp<IRegionSamplingListener>& listener); 76 77 // Notifies sampling engine that new content is available. This will trigger a sampling 78 // pass at some point in the future. 79 void notifyNewContent(); 80 81 // Notifies the sampling engine that it has a good timing window in which to sample. 82 void notifySamplingOffset(); 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(); 101 void binderDied(const wp<IBinder>& who) override; 102 void checkForStaleLuma(); 103 104 void captureSample(); 105 void threadMain(); 106 107 SurfaceFlinger& mFlinger; 108 Scheduler& mScheduler; 109 const TimingTunables mTunables; 110 scheduler::IdleTimer mIdleTimer; 111 112 std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback; 113 114 std::thread mThread; 115 116 std::mutex mThreadControlMutex; 117 std::condition_variable_any mCondition; 118 bool mRunning GUARDED_BY(mThreadControlMutex) = true; 119 bool mSampleRequested GUARDED_BY(mThreadControlMutex) = false; 120 bool mDiscardedFrames GUARDED_BY(mThreadControlMutex) = false; 121 std::chrono::nanoseconds lastSampleTime GUARDED_BY(mThreadControlMutex); 122 123 std::mutex mSamplingMutex; 124 std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex); 125 sp<GraphicBuffer> mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr; 126 }; 127 128 } // namespace android 129