blob: 1d854a657771f6736a77a273090e9fcf20764060 [file] [log] [blame]
Aaron Klingb2b3dd02015-11-12 09:25:04 -06001/*
2 * Copyright (c) 2011-2013 NVIDIA Corporation. All Rights Reserved.
3 *
4 * NVIDIA Corporation and its licensors retain all intellectual property and
5 * proprietary rights in and to this software and related documentation. Any
6 * use, reproduction, disclosure or distribution of this software and related
7 * documentation without an express license agreement from NVIDIA Corporation
8 * is strictly prohibited.
9 */
10#ifndef POWER_HAL_TIMEOUT_POKER_H
11#define POWER_HAL_TIMEOUT_POKER_H
12
13#include <stdint.h>
14#include <sys/types.h>
15
16#include <android/looper.h>
17#include <utils/threads.h>
18#include <utils/Errors.h>
19#include <utils/List.h>
20#include <utils/Looper.h>
21#include <utils/Log.h>
22
23#include "barrier.h"
24
25#define COMMAND_SIZE 20
26#define NODE_TYPE_DEFAULT 0
27#define NODE_TYPE_PRIORITY 1
28
29//It seems redundant to need both this message queue
30//And the IPC threads message queue
31//But I didn't see an easy way to
32//run an event after a timeout on the IPC threads
33
34using namespace android;
35
36static int createConstraintCommand(char* command, int size, int priority, int max, int min);
37
38class TimeoutPoker {
39private:
40 class PokeHandler;
41
42
43public:
44 TimeoutPoker(Barrier* readyToRun);
45
46 // Interface for requests that do not have a priority parameter.
47 // Uses /dev/[cpu_freq_max, cpu_freq_min, max_online_cpus,
48 // min_onlins_cpus, gpu_freq_max, gpu_freq_min] sysnodes which
49 // default to priority of 50.
50 int createPmQosHandle(const char* filename, int val);
51 int requestPmQos(const char* filename, int val);
52 void requestPmQosTimed(const char* filename, int val, nsecs_t timeoutNs);
53
54 // Interface for requests with a priority parameter.
55 // Uses /dev/constraint_[cpu_freq, onlines_cpus, gpu_freq] sysnodes.
56 // Command format: "max min priority timeoutMs"
57 int createPmQosHandle(const char* filename, int priority, int max, int min);
58 int requestPmQos(const char* filename, int priority, int max, int min);
59 void requestPmQosTimed(const char* filename, int priority, int max, int min, nsecs_t timeoutNs);
60
61private:
62
63 class QueuedEvent {
64 public:
65 virtual ~QueuedEvent() {}
66 QueuedEvent() { }
67
68 virtual void run(PokeHandler * const thiz) = 0;
69 };
70
71 class PmQosOpenTimedEvent : public QueuedEvent {
72 public:
73 virtual ~PmQosOpenTimedEvent() {}
74 PmQosOpenTimedEvent(const char* node,
75 int val,
76 nsecs_t timeout) :
77 node(node),
78 val(val),
79 timeout(timeout) {
80 type = NODE_TYPE_DEFAULT;
81 priority = -1;
82 max = -1;
83 min = -1;
84 }
85
86 PmQosOpenTimedEvent(const char* node,
87 int priority,
88 int max,
89 int min,
90 nsecs_t timeout) :
91 node(node),
92 priority(priority),
93 max(max),
94 min(min),
95 timeout(timeout) {
96 type = NODE_TYPE_PRIORITY;
97 val = 0;
98 }
99
100 virtual void run(PokeHandler * const thiz) {
101 if (type == NODE_TYPE_PRIORITY) {
102 thiz->openPmQosTimed(node, priority, max, min, timeout);
103 } else {
104 thiz->openPmQosTimed(node, val, timeout);
105 }
106 }
107
108 private:
109 const char* node;
110 int val;
111 int priority;
112 int max;
113 int min;
114 int type;
115 nsecs_t timeout;
116 };
117
118 class PmQosOpenHandleEvent : public QueuedEvent {
119 public:
120 virtual ~PmQosOpenHandleEvent() {}
121 PmQosOpenHandleEvent(const char* node,
122 int val,
123 int* outFd,
124 Barrier* done) :
125 node(node),
126 val(val),
127 outFd(outFd),
128 done(done) {
129 type = NODE_TYPE_DEFAULT;
130 priority = -1;
131 max = -1;
132 min = -1;
133 }
134
135 PmQosOpenHandleEvent(const char* node,
136 int priority,
137 int max,
138 int min,
139 int* outFd,
140 Barrier* done) :
141 node(node),
142 priority(priority),
143 max(max),
144 min(min),
145 outFd(outFd),
146 done(done) {
147 type = NODE_TYPE_PRIORITY;
148 val = 0;
149 }
150
151 virtual void run(PokeHandler * const thiz) {
152 if (type == NODE_TYPE_PRIORITY) {
153 *outFd = thiz->createHandleForPmQosRequest(node, priority, max, min);
154 } else {
155 *outFd = thiz->createHandleForPmQosRequest(node, val);
156 }
157 done->open();
158 }
159
160 private:
161 const char* node;
162 int val;
163 int priority;
164 int max;
165 int min;
166 int type;
167 int* outFd;
168 Barrier* done;
169 };
170
171 class TimeoutEvent : public QueuedEvent {
172 public:
173 virtual ~TimeoutEvent() {}
174 TimeoutEvent(int pmQosFd) : pmQosFd(pmQosFd) {}
175
176 virtual void run(PokeHandler * const thiz) {
177 thiz->timeoutRequest(pmQosFd);
178 }
179
180 private:
181 int pmQosFd;
182 };
183
184 void pushEvent(QueuedEvent* event);
185
186 class PokeHandler : public MessageHandler {
187 class LooperThread : public Thread {
188 private:
189 Barrier* mReadyToRun;
190 public:
191 sp<Looper> mLooper;
192 virtual bool threadLoop();
193 LooperThread(Barrier* readyToRun) :
194 mReadyToRun(readyToRun) {}
195 virtual status_t readyToRun();
196 };
197 public:
198
199 sp<LooperThread> mWorker;
200
201 KeyedVector<unsigned int, QueuedEvent*> mQueuedEvents;
202
203 virtual void handleMessage(const Message& msg);
204 PokeHandler(TimeoutPoker* poker, Barrier* readyToRun);
205 int generateNewKey(void);
206 void sendEventDelayed(nsecs_t delay, QueuedEvent* ev);
207 int listenForHandleToCloseFd(int handle, int fd);
208 QueuedEvent* removeEventByKey(int key);
209 int createHandleForFd(int fd);
210 void timeoutRequest(int fd);
211
212 void openPmQosTimed(const char* fileName, int val, nsecs_t timeout);
213 int createHandleForPmQosRequest(const char* filename, int val);
214 int openPmQosNode(const char* filename, int val);
215
216 void openPmQosTimed(const char* fileName, int priority, int max, int min, nsecs_t timeout);
217 int createHandleForPmQosRequest(const char* filename, int priority, int max, int min);
218 int openPmQosNode(const char* filename, int prioirity, int max, int min);
219
220 private:
221 TimeoutPoker* mPoker;
222 int mKey;
223
224 bool mSpamRefresh;
225 mutable Mutex mEvLock;
226 };
227
228 sp<PokeHandler> mPokeHandler;
229};
230
231#endif