| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 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 |  | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 19 | #include <chrono> | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 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> | 
| Kevin DuBois | 4efd1f5 | 2019-04-29 10:09:43 -0700 | [diff] [blame] | 27 | #include <ui/GraphicBuffer.h> | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 28 | #include <ui/Rect.h> | 
|  | 29 | #include <utils/StrongPointer.h> | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 30 | #include "Scheduler/IdleTimer.h" | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 31 |  | 
|  | 32 | namespace android { | 
|  | 33 |  | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 34 | class IRegionSamplingListener; | 
|  | 35 | class Layer; | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 36 | class Scheduler; | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 37 | class SurfaceFlinger; | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 38 | struct SamplingOffsetCallback; | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 39 |  | 
| Kevin DuBois | b325c93 | 2019-05-21 08:34:09 -0700 | [diff] [blame] | 40 | float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride, | 
|  | 41 | uint32_t orientation, const Rect& area); | 
| Kevin DuBois | bb27bcd | 2019-04-02 14:34:35 -0700 | [diff] [blame] | 42 |  | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 43 | class RegionSamplingThread : public IBinder::DeathRecipient { | 
|  | 44 | public: | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 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 |  | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 68 | ~RegionSamplingThread(); | 
|  | 69 |  | 
| Kevin DuBois | 7cbcc37 | 2019-02-25 14:53:28 -0800 | [diff] [blame] | 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. | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 72 | void addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, | 
|  | 73 | const sp<IRegionSamplingListener>& listener); | 
| Kevin DuBois | 7cbcc37 | 2019-02-25 14:53:28 -0800 | [diff] [blame] | 74 | // Remove the listener to stop receiving median luma notifications. | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 75 | void removeListener(const sp<IRegionSamplingListener>& listener); | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 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(); | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 83 |  | 
| Kevin DuBois | 7cbcc37 | 2019-02-25 14:53:28 -0800 | [diff] [blame] | 84 | private: | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 85 | struct Descriptor { | 
|  | 86 | Rect area = Rect::EMPTY_RECT; | 
|  | 87 | wp<Layer> stopLayer; | 
|  | 88 | sp<IRegionSamplingListener> listener; | 
|  | 89 | }; | 
|  | 90 |  | 
|  | 91 | struct WpHash { | 
|  | 92 | size_t operator()(const wp<IBinder>& p) const { | 
|  | 93 | return std::hash<IBinder*>()(p.unsafe_get()); | 
|  | 94 | } | 
|  | 95 | }; | 
| Kevin DuBois | 7cbcc37 | 2019-02-25 14:53:28 -0800 | [diff] [blame] | 96 | std::vector<float> sampleBuffer( | 
|  | 97 | const sp<GraphicBuffer>& buffer, const Point& leftTop, | 
| Kevin DuBois | b325c93 | 2019-05-21 08:34:09 -0700 | [diff] [blame] | 98 | const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation); | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 99 |  | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 100 | void doSample(); | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 101 | void binderDied(const wp<IBinder>& who) override; | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 102 | void checkForStaleLuma(); | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 103 |  | 
| Kevin DuBois | 26afc78 | 2019-05-06 16:46:45 -0700 | [diff] [blame] | 104 | void captureSample(); | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 105 | void threadMain(); | 
|  | 106 |  | 
|  | 107 | SurfaceFlinger& mFlinger; | 
| Kevin DuBois | 413287f | 2019-02-25 08:46:47 -0800 | [diff] [blame] | 108 | Scheduler& mScheduler; | 
|  | 109 | const TimingTunables mTunables; | 
|  | 110 | scheduler::IdleTimer mIdleTimer; | 
|  | 111 |  | 
|  | 112 | std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback; | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 113 |  | 
| Kevin DuBois | 26afc78 | 2019-05-06 16:46:45 -0700 | [diff] [blame] | 114 | std::thread mThread; | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 115 |  | 
| Kevin DuBois | 26afc78 | 2019-05-06 16:46:45 -0700 | [diff] [blame] | 116 | std::mutex mThreadControlMutex; | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 117 | std::condition_variable_any mCondition; | 
| Kevin DuBois | 26afc78 | 2019-05-06 16:46:45 -0700 | [diff] [blame] | 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); | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 122 |  | 
| Kevin DuBois | 26afc78 | 2019-05-06 16:46:45 -0700 | [diff] [blame] | 123 | std::mutex mSamplingMutex; | 
|  | 124 | std::unordered_map<wp<IBinder>, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex); | 
|  | 125 | sp<GraphicBuffer> mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr; | 
| Dan Stoza | ec46008 | 2018-12-17 15:35:09 -0800 | [diff] [blame] | 126 | }; | 
|  | 127 |  | 
|  | 128 | } // namespace android |