198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant/*
298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * Copyright (C) 2018 The Android Open Source Project
398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant *
498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * Licensed under the Apache License, Version 2.0 (the "License");
598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * you may not use this file except in compliance with the License.
698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * You may obtain a copy of the License at
798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant *
898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant *      http://www.apache.org/licenses/LICENSE-2.0
998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant *
1098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * Unless required by applicable law or agreed to in writing, software
1198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * distributed under the License is distributed on an "AS IS" BASIS,
1298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * See the License for the specific language governing permissions and
1498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant * limitations under the License.
1598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant */
1698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
1798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant#include "RateLimiter.h"
1898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant#include <utils/Timers.h>
1998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
2098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantnamespace hardware {
2198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantnamespace google {
2298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantnamespace pixelstats {
2398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantnamespace V1_0 {
2498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantnamespace implementation {
2598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
2698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant// for tests only
2798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantvoid RateLimiter::TurnBackHours(int32_t hours) {
2898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    nsecs_at_rollover_ = systemTime(SYSTEM_TIME_BOOTTIME) - s2ns(hours * 60 * 60);
2998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}
3098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
3198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant// Update the 24hr limit for all actions
3298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantvoid RateLimiter::SetOverallDailyLimit(int32_t limit) {
3398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    std::lock_guard<std::mutex> lock(lock_);
3498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    overall_limit_ = limit;
3598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}
3698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
3798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant// Returns true if you should rate limit the action reporting, false if not.
3898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant// limit: the number of times the action can occur within 24hrs.
3998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantbool RateLimiter::RateLimit(int32_t action, int32_t limit) {
4098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    std::lock_guard<std::mutex> lock(lock_);
4198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    int64_t nsecsNow = systemTime(SYSTEM_TIME_BOOTTIME);
4298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
4398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (nsecsNow < nsecs_at_rollover_) {
4498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return true;  // fail safe, rate limit.
4598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    }
4698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    int64_t elapsed = nsecsNow - nsecs_at_rollover_;
4798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    constexpr int64_t kDaySeconds = 60 * 60 * 24;
4898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (nanoseconds_to_seconds(elapsed) > kDaySeconds) {
4998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        counts_.clear();
5098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        overall_count_ = 0;
5198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        nsecs_at_rollover_ = nsecsNow;
5298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    }
5398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
5498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (++counts_[action] > limit) return true;
5598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (overall_limit_ && ++overall_count_ > overall_limit_) return true;
5698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    return false;
5798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}
5898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
5998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}  // namespace implementation
6098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}  // namespace V1_0
6198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}  // namespace pixelstats
6298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}  // namespace google
6398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}  // namespace hardware
64