1 /*
2  * Copyright (C) 2022 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/performance_hint.h>
20 #include <private/performance_hint_private.h>
21 
22 #include <future>
23 #include <optional>
24 #include <vector>
25 
26 #include "utils/TimeUtils.h"
27 
28 namespace android {
29 namespace uirenderer {
30 
31 namespace renderthread {
32 
33 class RenderThread;
34 
35 class HintSessionWrapper {
36 public:
37     friend class HintSessionWrapperTests;
38 
39     HintSessionWrapper(pid_t uiThreadId, pid_t renderThreadId);
40     ~HintSessionWrapper();
41 
42     void updateTargetWorkDuration(long targetDurationNanos);
43     void reportActualWorkDuration(long actualDurationNanos);
44     void sendLoadResetHint();
45     void sendLoadIncreaseHint();
46     bool init();
47     void destroy();
48     bool alive();
49     nsecs_t getLastUpdate();
50     void delayedDestroy(renderthread::RenderThread& rt, nsecs_t delay,
51                         std::shared_ptr<HintSessionWrapper> wrapperPtr);
52     // Must be called on Render thread. Otherwise can cause a race condition.
53     void setActiveFunctorThreads(std::vector<pid_t> threadIds);
54 
55 private:
56     APerformanceHintSession* mHintSession = nullptr;
57     // This needs to work concurrently for testing
58     std::optional<std::shared_future<APerformanceHintSession*>> mHintSessionFuture;
59     // This needs to work concurrently for testing
60     std::optional<std::shared_future<int>> mSetThreadsFuture;
61 
62     int mResetsSinceLastReport = 0;
63     nsecs_t mLastFrameNotification = 0;
64     nsecs_t mLastTargetWorkDuration = 0;
65 
66     pid_t mUiThreadId;
67     pid_t mRenderThreadId;
68     std::vector<pid_t> mPermanentSessionTids;
69     std::vector<pid_t> mActiveFunctorTids;
70 
71     bool mSessionValid = true;
72 
73     static constexpr nsecs_t kResetHintTimeout = 100_ms;
74     static constexpr int64_t kSanityCheckLowerBound = 100_us;
75     static constexpr int64_t kSanityCheckUpperBound = 10_s;
76     static constexpr int64_t kDefaultTargetDuration = 16666667;
77 
78     // Allows easier stub when testing
79     class HintSessionBinding {
80     public:
81         virtual ~HintSessionBinding() = default;
82         virtual void init();
83         APerformanceHintManager* (*getManager)();
84         APerformanceHintSession* (*createSessionInternal)(APerformanceHintManager* manager,
85                                                           const int32_t* tids, size_t tidCount,
86                                                           int64_t defaultTarget,
87                                                           SessionTag tag) = nullptr;
88         void (*closeSession)(APerformanceHintSession* session) = nullptr;
89         void (*updateTargetWorkDuration)(APerformanceHintSession* session,
90                                          int64_t targetDuration) = nullptr;
91         void (*reportActualWorkDuration)(APerformanceHintSession* session,
92                                          int64_t actualDuration) = nullptr;
93         void (*sendHint)(APerformanceHintSession* session, int32_t hintId) = nullptr;
94         int (*setThreads)(APerformanceHintSession* session, const pid_t* tids,
95                           size_t size) = nullptr;
96 
97     private:
98         bool mInitialized = false;
99     };
100 
101     std::shared_ptr<HintSessionBinding> mBinding;
102 };
103 
104 } /* namespace renderthread */
105 } /* namespace uirenderer */
106 } /* namespace android */
107