blob: 864d28f806993078ed2e482d54cacdfe83ffdc40 [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <aidl/android/hardware/power/BnPowerHintSession.h>
#include <aidl/android/hardware/power/WorkDuration.h>
#include <utils/Looper.h>
#include <utils/Thread.h>
#include <mutex>
#include <unordered_map>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
using aidl::android::hardware::power::BnPowerHintSession;
using aidl::android::hardware::power::WorkDuration;
using ::android::Message;
using ::android::MessageHandler;
using ::android::sp;
using std::chrono::milliseconds;
using std::chrono::nanoseconds;
using std::chrono::steady_clock;
using std::chrono::time_point;
struct AppHintDesc {
AppHintDesc(int32_t tgid, int32_t uid, std::vector<int> threadIds)
: tgid(tgid),
uid(uid),
threadIds(std::move(threadIds)),
duration(0LL),
current_min(0),
is_active(true),
update_count(0),
integral_error(0),
previous_error(0) {}
std::string toString() const;
const int32_t tgid;
const int32_t uid;
const std::vector<int> threadIds;
nanoseconds duration;
int current_min;
// status
std::atomic<bool> is_active;
// pid
uint64_t update_count;
int64_t integral_error;
int64_t previous_error;
};
class PowerHintSession : public BnPowerHintSession {
public:
explicit PowerHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds,
int64_t durationNanos);
~PowerHintSession();
ndk::ScopedAStatus close() override;
ndk::ScopedAStatus pause() override;
ndk::ScopedAStatus resume() override;
ndk::ScopedAStatus updateTargetWorkDuration(int64_t targetDurationNanos) override;
ndk::ScopedAStatus reportActualWorkDuration(
const std::vector<WorkDuration> &actualDurations) override;
bool isActive();
bool isTimeout();
void wakeup();
void setStale();
// Is this hint session for a user application
bool isAppSession();
const std::vector<int> &getTidList() const;
int getUclampMin();
void dumpToStream(std::ostream &stream);
void updateWorkPeriod(const std::vector<WorkDuration> &actualDurations);
time_point<steady_clock> getEarlyBoostTime();
time_point<steady_clock> getStaleTime();
private:
class StaleTimerHandler : public MessageHandler {
public:
StaleTimerHandler(PowerHintSession *session)
: mSession(session), mIsMonitoring(false), mIsSessionDead(false) {}
void updateTimer();
void updateTimer(time_point<steady_clock> staleTime);
void handleMessage(const Message &message) override;
void setSessionDead();
private:
PowerHintSession *mSession;
std::mutex mClosedLock;
std::mutex mMessageLock;
std::atomic<time_point<steady_clock>> mStaleTime;
std::atomic<bool> mIsMonitoring;
bool mIsSessionDead;
};
class EarlyBoostHandler : public MessageHandler {
public:
EarlyBoostHandler(PowerHintSession *session)
: mSession(session), mIsMonitoring(false), mIsSessionDead(false) {}
void updateTimer(time_point<steady_clock> boostTime);
void handleMessage(const Message &message) override;
void setSessionDead();
private:
PowerHintSession *mSession;
std::mutex mBoostLock;
std::mutex mMessageLock;
std::atomic<time_point<steady_clock>> mBoostTime;
std::atomic<bool> mIsMonitoring;
bool mIsSessionDead;
};
private:
void updateUniveralBoostMode();
int setSessionUclampMin(int32_t min);
std::string getIdString() const;
AppHintDesc *mDescriptor = nullptr;
sp<StaleTimerHandler> mStaleTimerHandler;
sp<EarlyBoostHandler> mEarlyBoostHandler;
std::atomic<time_point<steady_clock>> mLastUpdatedTime;
sp<MessageHandler> mPowerManagerHandler;
std::mutex mSessionLock;
std::atomic<bool> mSessionClosed = false;
// These 3 variables are for earlyboost work period estimation.
int64_t mLastStartedTimeNs;
int64_t mLastDurationNs;
int64_t mWorkPeriodNs;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl