blob: 8c0340585573644b7c7e6a283c3504babb3440bb [file] [log] [blame]
/*
* Copyright (C) 2018 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 android.app.usage;
import java.util.ArrayList;
/**
* A container to keep {@link UsageEvents.Event usage events} in non-descending order of their
* {@link UsageEvents.Event#mTimeStamp timestamps}.
*
* @hide
*/
public class EventList {
private final ArrayList<UsageEvents.Event> mEvents;
/**
* Create a new event list with default capacity
*/
public EventList() {
mEvents = new ArrayList<>();
}
/**
* Returns the size of the list
* @return the number of events in the list
*/
public int size() {
return mEvents.size();
}
/**
* Removes all events from the list
*/
public void clear() {
mEvents.clear();
}
/**
* Returns the {@link UsageEvents.Event event} at the specified position in this list.
* @param index the index of the event to return, such that {@code 0 <= index < size()}
* @return The {@link UsageEvents.Event event} at position {@code index}
*/
public UsageEvents.Event get(int index) {
return mEvents.get(index);
}
/**
* Inserts the given {@link UsageEvents.Event event} into the list while keeping the list sorted
* based on the event {@link UsageEvents.Event#mTimeStamp timestamps}.
*
* @param event The event to insert
*/
public void insert(UsageEvents.Event event) {
final int size = mEvents.size();
// fast case: just append if this is the latest event
if (size == 0 || event.mTimeStamp >= mEvents.get(size - 1).mTimeStamp) {
mEvents.add(event);
return;
}
// To minimize number of elements being shifted, insert at the first occurrence of the next
// greatest timestamp in the list.
final int insertIndex = firstIndexOnOrAfter(event.mTimeStamp + 1);
mEvents.add(insertIndex, event);
}
/**
* Finds the index of the first event whose timestamp is greater than or equal to the given
* timestamp.
*
* @param timeStamp The timestamp for which to search the list.
* @return The smallest {@code index} for which {@code (get(index).mTimeStamp >= timeStamp)} is
* {@code true}, or {@link #size() size} if no such {@code index} exists.
*/
public int firstIndexOnOrAfter(long timeStamp) {
final int size = mEvents.size();
int result = size;
int lo = 0;
int hi = size - 1;
while (lo <= hi) {
final int mid = (lo + hi) >>> 1;
final long midTimeStamp = mEvents.get(mid).mTimeStamp;
if (midTimeStamp >= timeStamp) {
hi = mid - 1;
result = mid;
} else {
lo = mid + 1;
}
}
return result;
}
/**
* Merge the {@link UsageEvents.Event events} in the given {@link EventList list} into this
* list while keeping the list sorted based on the event {@link
* UsageEvents.Event#mTimeStamp timestamps}.
*
* @param events The event list to merge
*/
public void merge(EventList events) {
final int size = events.size();
for (int i = 0; i < size; i++) {
insert(events.get(i));
}
}
}