To prepare for enabling MissingNullability Metalava check this CL works on adding missing nullability issues that metalava flags if we tell it to flag new things since API 29. This is not a complete CL, mostly addresses public api and toString/equals for @SystemApi Exempt-From-Owner-Approval: Large scale nullability clean up Bug: 124515653 Test: make -j checkapi Merged-In: I109260842cfc25f06e40694997fcbb4afa02c867 Change-Id: I109260842cfc25f06e40694997fcbb4afa02c867
315 lines
11 KiB
Java
315 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2016 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.telephony;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.annotation.SystemApi;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import java.util.Arrays;
|
|
|
|
/**
|
|
* Parcelable class to store Telephony histogram.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public final class TelephonyHistogram implements Parcelable {
|
|
// Type of Telephony histogram Eg: RIL histogram will have all timing data associated with
|
|
// RIL calls. Similarly we can have any other Telephony histogram.
|
|
private final int mCategory;
|
|
|
|
// Unique Id identifying a sample within particular category of histogram
|
|
private final int mId;
|
|
|
|
// Min time taken in ms
|
|
private int mMinTimeMs;
|
|
|
|
// Max time taken in ms
|
|
private int mMaxTimeMs;
|
|
|
|
// Average time taken in ms
|
|
private int mAverageTimeMs;
|
|
|
|
// Total count of samples
|
|
private int mSampleCount;
|
|
|
|
// Array storing time taken for first #RANGE_CALCULATION_COUNT samples of histogram.
|
|
private int[] mInitialTimings;
|
|
|
|
// Total number of time ranges expected (must be greater than 1)
|
|
private final int mBucketCount;
|
|
|
|
// Array storing endpoints of range buckets. Calculated based on values of minTime & maxTime
|
|
// after totalTimeCount is #RANGE_CALCULATION_COUNT.
|
|
private final int[] mBucketEndPoints;
|
|
|
|
// Array storing counts for each time range starting from smallest value range
|
|
private final int[] mBucketCounters;
|
|
|
|
/**
|
|
* Constant for Telephony category
|
|
*/
|
|
public static final int TELEPHONY_CATEGORY_RIL = 1;
|
|
|
|
// Count of Histogram samples after which time buckets are created.
|
|
private static final int RANGE_CALCULATION_COUNT = 10;
|
|
|
|
|
|
// Constant used to indicate #initialTimings is null while parceling
|
|
private static final int ABSENT = 0;
|
|
|
|
// Constant used to indicate #initialTimings is not null while parceling
|
|
private static final int PRESENT = 1;
|
|
|
|
// Throws exception if #totalBuckets is not greater than one.
|
|
public TelephonyHistogram (int category, int id, int bucketCount) {
|
|
if (bucketCount <= 1) {
|
|
throw new IllegalArgumentException("Invalid number of buckets");
|
|
}
|
|
mCategory = category;
|
|
mId = id;
|
|
mMinTimeMs = Integer.MAX_VALUE;
|
|
mMaxTimeMs = 0;
|
|
mAverageTimeMs = 0;
|
|
mSampleCount = 0;
|
|
mInitialTimings = new int[RANGE_CALCULATION_COUNT];
|
|
mBucketCount = bucketCount;
|
|
mBucketEndPoints = new int[bucketCount - 1];
|
|
mBucketCounters = new int[bucketCount];
|
|
}
|
|
|
|
public TelephonyHistogram(TelephonyHistogram th) {
|
|
mCategory = th.getCategory();
|
|
mId = th.getId();
|
|
mMinTimeMs = th.getMinTime();
|
|
mMaxTimeMs = th.getMaxTime();
|
|
mAverageTimeMs = th.getAverageTime();
|
|
mSampleCount = th.getSampleCount();
|
|
mInitialTimings = th.getInitialTimings();
|
|
mBucketCount = th.getBucketCount();
|
|
mBucketEndPoints = th.getBucketEndPoints();
|
|
mBucketCounters = th.getBucketCounters();
|
|
}
|
|
|
|
public int getCategory() {
|
|
return mCategory;
|
|
}
|
|
|
|
public int getId() {
|
|
return mId;
|
|
}
|
|
|
|
public int getMinTime() {
|
|
return mMinTimeMs;
|
|
}
|
|
|
|
public int getMaxTime() {
|
|
return mMaxTimeMs;
|
|
}
|
|
|
|
public int getAverageTime() {
|
|
return mAverageTimeMs;
|
|
}
|
|
|
|
public int getSampleCount () {
|
|
return mSampleCount;
|
|
}
|
|
|
|
private int[] getInitialTimings() {
|
|
return mInitialTimings;
|
|
}
|
|
|
|
public int getBucketCount() {
|
|
return mBucketCount;
|
|
}
|
|
|
|
public int[] getBucketEndPoints() {
|
|
if (mSampleCount > 1 && mSampleCount < 10) {
|
|
int[] tempEndPoints = new int[mBucketCount - 1];
|
|
calculateBucketEndPoints(tempEndPoints);
|
|
return tempEndPoints;
|
|
} else {
|
|
return getDeepCopyOfArray(mBucketEndPoints);
|
|
}
|
|
}
|
|
|
|
public int[] getBucketCounters() {
|
|
if (mSampleCount > 1 && mSampleCount < 10) {
|
|
int[] tempEndPoints = new int[mBucketCount - 1];
|
|
int[] tempBucketCounters = new int[mBucketCount];
|
|
calculateBucketEndPoints(tempEndPoints);
|
|
for (int j = 0; j < mSampleCount; j++) {
|
|
addToBucketCounter(tempEndPoints, tempBucketCounters, mInitialTimings[j]);
|
|
}
|
|
return tempBucketCounters;
|
|
} else {
|
|
return getDeepCopyOfArray(mBucketCounters);
|
|
}
|
|
}
|
|
|
|
private int[] getDeepCopyOfArray(int[] array) {
|
|
int[] clone = new int[array.length];
|
|
System.arraycopy(array, 0, clone, 0, array.length);
|
|
return clone;
|
|
}
|
|
|
|
private void addToBucketCounter(int[] bucketEndPoints, int[] bucketCounters, int time) {
|
|
int i;
|
|
for (i = 0; i < bucketEndPoints.length; i++) {
|
|
if (time <= bucketEndPoints[i]) {
|
|
bucketCounters[i]++;
|
|
return;
|
|
}
|
|
}
|
|
bucketCounters[i]++;
|
|
}
|
|
|
|
private void calculateBucketEndPoints(int[] bucketEndPoints) {
|
|
for (int i = 1; i < mBucketCount; i++) {
|
|
int endPt = mMinTimeMs + (i * (mMaxTimeMs - mMinTimeMs)) / mBucketCount;
|
|
bucketEndPoints[i - 1] = endPt;
|
|
}
|
|
}
|
|
|
|
// Add new value of time taken
|
|
// This function updates minTime, maxTime, averageTime & totalTimeCount every time it is
|
|
// called. initialTimings[] is updated if totalTimeCount <= #RANGE_CALCULATION_COUNT. When
|
|
// totalTimeCount = RANGE_CALCULATION_COUNT, based on the min, max time & the number of buckets
|
|
// expected, bucketEndPoints[] would be calculated. Then bucketCounters[] would be filled up
|
|
// using values stored in initialTimings[]. Thereafter bucketCounters[] will always be updated.
|
|
public void addTimeTaken(int time) {
|
|
// Initialize all fields if its first entry or if integer overflow is going to occur while
|
|
// trying to calculate averageTime
|
|
if (mSampleCount == 0 || (mSampleCount == Integer.MAX_VALUE)) {
|
|
if (mSampleCount == 0) {
|
|
mMinTimeMs = time;
|
|
mMaxTimeMs = time;
|
|
mAverageTimeMs = time;
|
|
} else {
|
|
mInitialTimings = new int[RANGE_CALCULATION_COUNT];
|
|
}
|
|
mSampleCount = 1;
|
|
Arrays.fill(mInitialTimings, 0);
|
|
mInitialTimings[0] = time;
|
|
Arrays.fill(mBucketEndPoints, 0);
|
|
Arrays.fill(mBucketCounters, 0);
|
|
} else {
|
|
if (time < mMinTimeMs) {
|
|
mMinTimeMs = time;
|
|
}
|
|
if (time > mMaxTimeMs) {
|
|
mMaxTimeMs = time;
|
|
}
|
|
long totalTime = ((long)mAverageTimeMs) * mSampleCount + time;
|
|
mAverageTimeMs = (int)(totalTime/++mSampleCount);
|
|
|
|
if (mSampleCount < RANGE_CALCULATION_COUNT) {
|
|
mInitialTimings[mSampleCount - 1] = time;
|
|
} else if (mSampleCount == RANGE_CALCULATION_COUNT) {
|
|
mInitialTimings[mSampleCount - 1] = time;
|
|
|
|
// Calculate bucket endpoints based on bucketCount expected
|
|
calculateBucketEndPoints(mBucketEndPoints);
|
|
|
|
// Use values stored in initialTimings[] to update bucketCounters
|
|
for (int j = 0; j < RANGE_CALCULATION_COUNT; j++) {
|
|
addToBucketCounter(mBucketEndPoints, mBucketCounters, mInitialTimings[j]);
|
|
}
|
|
mInitialTimings = null;
|
|
} else {
|
|
addToBucketCounter(mBucketEndPoints, mBucketCounters, time);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public String toString() {
|
|
String basic = " Histogram id = " + mId + " Time(ms): min = " + mMinTimeMs + " max = "
|
|
+ mMaxTimeMs + " avg = " + mAverageTimeMs + " Count = " + mSampleCount;
|
|
if (mSampleCount < RANGE_CALCULATION_COUNT) {
|
|
return basic;
|
|
} else {
|
|
StringBuffer intervals = new StringBuffer(" Interval Endpoints:");
|
|
for (int i = 0; i < mBucketEndPoints.length; i++) {
|
|
intervals.append(" " + mBucketEndPoints[i]);
|
|
}
|
|
intervals.append(" Interval counters:");
|
|
for (int i = 0; i < mBucketCounters.length; i++) {
|
|
intervals.append(" " + mBucketCounters[i]);
|
|
}
|
|
return basic + intervals;
|
|
}
|
|
}
|
|
|
|
public static final @android.annotation.NonNull Parcelable.Creator<TelephonyHistogram> CREATOR =
|
|
new Parcelable.Creator<TelephonyHistogram> () {
|
|
|
|
@Override
|
|
public TelephonyHistogram createFromParcel(Parcel in) {
|
|
return new TelephonyHistogram(in);
|
|
}
|
|
|
|
@Override
|
|
public TelephonyHistogram[] newArray(int size) {
|
|
return new TelephonyHistogram[size];
|
|
}
|
|
};
|
|
|
|
public TelephonyHistogram(Parcel in) {
|
|
mCategory = in.readInt();
|
|
mId = in.readInt();
|
|
mMinTimeMs = in.readInt();
|
|
mMaxTimeMs = in.readInt();
|
|
mAverageTimeMs = in.readInt();
|
|
mSampleCount = in.readInt();
|
|
if (in.readInt() == PRESENT) {
|
|
mInitialTimings = new int[RANGE_CALCULATION_COUNT];
|
|
in.readIntArray(mInitialTimings);
|
|
}
|
|
mBucketCount = in.readInt();
|
|
mBucketEndPoints = new int[mBucketCount - 1];
|
|
in.readIntArray(mBucketEndPoints);
|
|
mBucketCounters = new int[mBucketCount];
|
|
in.readIntArray(mBucketCounters);
|
|
}
|
|
|
|
public void writeToParcel(Parcel out, int flags) {
|
|
out.writeInt(mCategory);
|
|
out.writeInt(mId);
|
|
out.writeInt(mMinTimeMs);
|
|
out.writeInt(mMaxTimeMs);
|
|
out.writeInt(mAverageTimeMs);
|
|
out.writeInt(mSampleCount);
|
|
if (mInitialTimings == null) {
|
|
out.writeInt(ABSENT);
|
|
} else {
|
|
out.writeInt(PRESENT);
|
|
out.writeIntArray(mInitialTimings);
|
|
}
|
|
out.writeInt(mBucketCount);
|
|
out.writeIntArray(mBucketEndPoints);
|
|
out.writeIntArray(mBucketCounters);
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
}
|