1c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren/*
2c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * Copyright (C) 2016 The Android Open Source Project
3c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren *
4c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * Licensed under the Apache License, Version 2.0 (the "License");
5c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * you may not use this file except in compliance with the License.
6c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * You may obtain a copy of the License at
7c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren *
8c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren *      http://www.apache.org/licenses/LICENSE-2.0
9c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren *
10c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * Unless required by applicable law or agreed to in writing, software
11c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * distributed under the License is distributed on an "AS IS" BASIS,
12c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * See the License for the specific language governing permissions and
14c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * limitations under the License
15c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren */
16c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
17c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wrenpackage com.android.server.notification;
18c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
19c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
20c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren/**
21c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * Exponentially weighted moving average estimator for event rate.
22c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren *
23c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren * {@hide}
24c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren */
25c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wrenpublic class RateEstimator {
26c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    private static final double RATE_ALPHA = 0.8;
27c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    private static final double MINIMUM_DT = 0.0005;
28fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak    private Long mLastEventTime;
29888b7a8faf7d6c2aa4272bebeb875eac9a2ff21cChris Wren    private double mInterarrivalTime;
30c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
31888b7a8faf7d6c2aa4272bebeb875eac9a2ff21cChris Wren    public RateEstimator() {
32888b7a8faf7d6c2aa4272bebeb875eac9a2ff21cChris Wren        // assume something generous if we have no information
33888b7a8faf7d6c2aa4272bebeb875eac9a2ff21cChris Wren        mInterarrivalTime = 1000.0;
34888b7a8faf7d6c2aa4272bebeb875eac9a2ff21cChris Wren    }
35c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
36fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak    /** Update the estimate to account for an event that just happened. */
37c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    public float update(long now) {
38fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        float rate;
39fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        if (mLastEventTime == null) {
40fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak            // No last event time, rate is zero.
41fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak            rate = 0f;
42fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        } else {
43fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak            // Calculate the new inter-arrival time based on last event time.
44888b7a8faf7d6c2aa4272bebeb875eac9a2ff21cChris Wren            mInterarrivalTime = getInterarrivalEstimate(now);
45fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak            rate = (float) (1.0 / mInterarrivalTime);
46fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        }
47c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren        mLastEventTime = now;
48fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        return rate;
49c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    }
50c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
51c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    /** @return the estimated rate if there were a new event right now. */
52c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    public float getRate(long now) {
53fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        if (mLastEventTime == null) {
54fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak            return 0f;
55fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        }
56c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren        return (float) (1.0 / getInterarrivalEstimate(now));
57c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    }
58c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren
59c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    /** @return the average inter-arrival time if there were a new event right now. */
60c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    private double getInterarrivalEstimate(long now) {
61c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren        double dt = ((double) (now - mLastEventTime)) / 1000.0;
62c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren        dt = Math.max(dt, MINIMUM_DT);
63fd303327083fdf309b9d8a15343f9eb70c014b11Tony Mak        // a*iat_old + (1-a)*(t_now-t_last)
64c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren        return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt);
65c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren    }
66c8673a88fed53715d2295a535535c7ce7acbe7b6Chris Wren}
67