Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4a7dbc9 authored by Nazanin Bakhshi's avatar Nazanin Bakhshi Committed by Automerger Merge Worker
Browse files

Merge "Add slidingWindowEventCounter class in telephony" am: 4ad7b629 am:...

Merge "Add slidingWindowEventCounter class in telephony" am: 4ad7b629 am: b7d2b4e3 am: d85b10d1

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/1607580

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I26502f7822b627122669fb759c558726e40f16ea
parents b0532397 d85b10d1
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import android.annotation.IntRange;
import android.util.LongArrayQueue;

import com.android.internal.annotations.VisibleForTesting;

/**
 * Tracks whether an event occurs mNumOccurrences times within the time span mWindowSizeMillis.
 * <p/>
 * Stores all events in memory, use a small number of required occurrences when using.
 */
public class SlidingWindowEventCounter {
    private final long mWindowSizeMillis;
    private final int mNumOccurrences;
    private final LongArrayQueue mTimestampQueueMillis;

    public SlidingWindowEventCounter(@IntRange(from = 1) final long windowSizeMillis,
            @IntRange(from = 2) final int numOccurrences) {
        if (windowSizeMillis <= 0) {
            throw new IllegalArgumentException("windowSizeMillis must be greater than 0");
        }
        if (numOccurrences <= 1) {
            throw new IllegalArgumentException("numOccurrences must be greater than 1");
        }

        mWindowSizeMillis = windowSizeMillis;
        mNumOccurrences = numOccurrences;
        mTimestampQueueMillis = new LongArrayQueue(numOccurrences);
    }

    /**
     * Increments the occurrence counter.
     *
     * Returns true if an event has occurred at least mNumOccurrences times within the
     * time span mWindowSizeMillis.
     * @param timestampMillis
     */
    public synchronized boolean addOccurrence(long timestampMillis) {
        mTimestampQueueMillis.addLast(timestampMillis);
        if (mTimestampQueueMillis.size() > mNumOccurrences) {
            mTimestampQueueMillis.removeFirst();
        }
        return isInWindow();
    }

    /**
     * Returns true if the conditions is satisfied.
     */
    public synchronized boolean isInWindow() {
        return (mTimestampQueueMillis.size() == mNumOccurrences)
                && mTimestampQueueMillis.peekFirst()
                + mWindowSizeMillis >= mTimestampQueueMillis.peekLast();
    }

    @VisibleForTesting
    int getNumOccurrences() {
        return mTimestampQueueMillis.size();
    }
}
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.os.SystemClock;

import org.junit.Before;
import org.junit.Test;

public class SlidingWindowEventCounterTest extends TelephonyTest {
    long mInitialTime;

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
        mInitialTime = SystemClock.elapsedRealtime();
    }

    @Test
    public void test_returnsTrue_ifEnoughEntriesInWindow() {
        SlidingWindowEventCounter counter = new SlidingWindowEventCounter(100, 3);
        for (int i = 0; i < 3; i++) {
            counter.addOccurrence(mInitialTime + i);
        }
        assertTrue(counter.isInWindow());
    }

    @Test
    public void test_returnsTrue_ifMoreThanEnoughEntriesInWindow() {
        SlidingWindowEventCounter counter = new SlidingWindowEventCounter(100, 3);
        for (int i = 0; i < 3; i++) {
            counter.addOccurrence(mInitialTime + i);
        }
        for (int i = 0; i < 3; i++) {
            counter.addOccurrence(mInitialTime + i + 50);
        }
        assertTrue(counter.isInWindow());
    }

    @Test
    public void test_returnsFalse_ifNotEnoughEntriesInWindow() {
        SlidingWindowEventCounter counter = new SlidingWindowEventCounter(100, 3);
        for (int i = 0; i < 2; i++) {
            counter.addOccurrence(mInitialTime + i);
        }
        assertFalse(counter.isInWindow());
    }

    @Test
    public void test_returnsFalse_ifEnoughEntriesButTooFarApart() {
        SlidingWindowEventCounter counter = new SlidingWindowEventCounter(100, 3);
        for (int i = 0; i < 2; i++) {
            counter.addOccurrence(mInitialTime + i);
        }
        counter.addOccurrence(mInitialTime + 101);
        counter.addOccurrence(mInitialTime + 102);
        assertFalse(counter.isInWindow());
    }
}