blob: 1d854a657771f6736a77a273090e9fcf20764060 [file] [log] [blame]
/*
* Copyright (c) 2011-2013 NVIDIA Corporation. All Rights Reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property and
* proprietary rights in and to this software and related documentation. Any
* use, reproduction, disclosure or distribution of this software and related
* documentation without an express license agreement from NVIDIA Corporation
* is strictly prohibited.
*/
#ifndef POWER_HAL_TIMEOUT_POKER_H
#define POWER_HAL_TIMEOUT_POKER_H
#include <stdint.h>
#include <sys/types.h>
#include <android/looper.h>
#include <utils/threads.h>
#include <utils/Errors.h>
#include <utils/List.h>
#include <utils/Looper.h>
#include <utils/Log.h>
#include "barrier.h"
#define COMMAND_SIZE 20
#define NODE_TYPE_DEFAULT 0
#define NODE_TYPE_PRIORITY 1
//It seems redundant to need both this message queue
//And the IPC threads message queue
//But I didn't see an easy way to
//run an event after a timeout on the IPC threads
using namespace android;
static int createConstraintCommand(char* command, int size, int priority, int max, int min);
class TimeoutPoker {
private:
class PokeHandler;
public:
TimeoutPoker(Barrier* readyToRun);
// Interface for requests that do not have a priority parameter.
// Uses /dev/[cpu_freq_max, cpu_freq_min, max_online_cpus,
// min_onlins_cpus, gpu_freq_max, gpu_freq_min] sysnodes which
// default to priority of 50.
int createPmQosHandle(const char* filename, int val);
int requestPmQos(const char* filename, int val);
void requestPmQosTimed(const char* filename, int val, nsecs_t timeoutNs);
// Interface for requests with a priority parameter.
// Uses /dev/constraint_[cpu_freq, onlines_cpus, gpu_freq] sysnodes.
// Command format: "max min priority timeoutMs"
int createPmQosHandle(const char* filename, int priority, int max, int min);
int requestPmQos(const char* filename, int priority, int max, int min);
void requestPmQosTimed(const char* filename, int priority, int max, int min, nsecs_t timeoutNs);
private:
class QueuedEvent {
public:
virtual ~QueuedEvent() {}
QueuedEvent() { }
virtual void run(PokeHandler * const thiz) = 0;
};
class PmQosOpenTimedEvent : public QueuedEvent {
public:
virtual ~PmQosOpenTimedEvent() {}
PmQosOpenTimedEvent(const char* node,
int val,
nsecs_t timeout) :
node(node),
val(val),
timeout(timeout) {
type = NODE_TYPE_DEFAULT;
priority = -1;
max = -1;
min = -1;
}
PmQosOpenTimedEvent(const char* node,
int priority,
int max,
int min,
nsecs_t timeout) :
node(node),
priority(priority),
max(max),
min(min),
timeout(timeout) {
type = NODE_TYPE_PRIORITY;
val = 0;
}
virtual void run(PokeHandler * const thiz) {
if (type == NODE_TYPE_PRIORITY) {
thiz->openPmQosTimed(node, priority, max, min, timeout);
} else {
thiz->openPmQosTimed(node, val, timeout);
}
}
private:
const char* node;
int val;
int priority;
int max;
int min;
int type;
nsecs_t timeout;
};
class PmQosOpenHandleEvent : public QueuedEvent {
public:
virtual ~PmQosOpenHandleEvent() {}
PmQosOpenHandleEvent(const char* node,
int val,
int* outFd,
Barrier* done) :
node(node),
val(val),
outFd(outFd),
done(done) {
type = NODE_TYPE_DEFAULT;
priority = -1;
max = -1;
min = -1;
}
PmQosOpenHandleEvent(const char* node,
int priority,
int max,
int min,
int* outFd,
Barrier* done) :
node(node),
priority(priority),
max(max),
min(min),
outFd(outFd),
done(done) {
type = NODE_TYPE_PRIORITY;
val = 0;
}
virtual void run(PokeHandler * const thiz) {
if (type == NODE_TYPE_PRIORITY) {
*outFd = thiz->createHandleForPmQosRequest(node, priority, max, min);
} else {
*outFd = thiz->createHandleForPmQosRequest(node, val);
}
done->open();
}
private:
const char* node;
int val;
int priority;
int max;
int min;
int type;
int* outFd;
Barrier* done;
};
class TimeoutEvent : public QueuedEvent {
public:
virtual ~TimeoutEvent() {}
TimeoutEvent(int pmQosFd) : pmQosFd(pmQosFd) {}
virtual void run(PokeHandler * const thiz) {
thiz->timeoutRequest(pmQosFd);
}
private:
int pmQosFd;
};
void pushEvent(QueuedEvent* event);
class PokeHandler : public MessageHandler {
class LooperThread : public Thread {
private:
Barrier* mReadyToRun;
public:
sp<Looper> mLooper;
virtual bool threadLoop();
LooperThread(Barrier* readyToRun) :
mReadyToRun(readyToRun) {}
virtual status_t readyToRun();
};
public:
sp<LooperThread> mWorker;
KeyedVector<unsigned int, QueuedEvent*> mQueuedEvents;
virtual void handleMessage(const Message& msg);
PokeHandler(TimeoutPoker* poker, Barrier* readyToRun);
int generateNewKey(void);
void sendEventDelayed(nsecs_t delay, QueuedEvent* ev);
int listenForHandleToCloseFd(int handle, int fd);
QueuedEvent* removeEventByKey(int key);
int createHandleForFd(int fd);
void timeoutRequest(int fd);
void openPmQosTimed(const char* fileName, int val, nsecs_t timeout);
int createHandleForPmQosRequest(const char* filename, int val);
int openPmQosNode(const char* filename, int val);
void openPmQosTimed(const char* fileName, int priority, int max, int min, nsecs_t timeout);
int createHandleForPmQosRequest(const char* filename, int priority, int max, int min);
int openPmQosNode(const char* filename, int prioirity, int max, int min);
private:
TimeoutPoker* mPoker;
int mKey;
bool mSpamRefresh;
mutable Mutex mEvLock;
};
sp<PokeHandler> mPokeHandler;
};
#endif