106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe/*
206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * Copyright (C) 2016 The Android Open Source Project
306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe *
406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * Licensed under the Apache License, Version 2.0 (the "License");
506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * you may not use this file except in compliance with the License.
606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * You may obtain a copy of the License at
706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe *
806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe *      http://www.apache.org/licenses/LICENSE-2.0
906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe *
1006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * Unless required by applicable law or agreed to in writing, software
1106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * distributed under the License is distributed on an "AS IS" BASIS,
1206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * See the License for the specific language governing permissions and
1406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * limitations under the License.
1506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe */
1606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawepackage android.telephony;
1706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
1806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padaweimport android.annotation.SystemApi;
1906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padaweimport android.os.Parcel;
2006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padaweimport android.os.Parcelable;
2106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
2206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padaweimport java.util.ArrayList;
2306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padaweimport java.util.Arrays;
2406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padaweimport java.util.List;
2506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
2606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe/**
2706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * Parcelable class to store Telephony histogram.
2806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe * @hide
2906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe */
3006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe@SystemApi
3106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawepublic final class TelephonyHistogram implements Parcelable {
3206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Type of Telephony histogram Eg: RIL histogram will have all timing data associated with
3306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // RIL calls. Similarly we can have any other Telephony histogram.
340680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private final int mCategory;
3506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
3606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Unique Id identifying a sample within particular category of histogram
370680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private final int mId;
3806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
3906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Min time taken in ms
400680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private int mMinTimeMs;
4106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
4206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Max time taken in ms
430680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private int mMaxTimeMs;
4406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
4506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Average time taken in ms
460680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private int mAverageTimeMs;
4706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
4806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Total count of samples
490680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private int mSampleCount;
5006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
5106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Array storing time taken for first #RANGE_CALCULATION_COUNT samples of histogram.
520680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private int[] mInitialTimings;
5306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
5406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Total number of time ranges expected (must be greater than 1)
550680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private final int mBucketCount;
5606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
5706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Array storing endpoints of range buckets. Calculated based on values of minTime & maxTime
5806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // after totalTimeCount is #RANGE_CALCULATION_COUNT.
590680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private final int[] mBucketEndPoints;
6006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
6106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Array storing counts for each time range starting from smallest value range
620680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private final int[] mBucketCounters;
6306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
6406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    /**
6506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe     * Constant for Telephony category
6606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe     */
6706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public static final int TELEPHONY_CATEGORY_RIL = 1;
6806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
6906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Count of Histogram samples after which time buckets are created.
7006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    private static final int RANGE_CALCULATION_COUNT = 10;
7106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
7206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
7306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Constant used to indicate #initialTimings is null while parceling
7406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    private static final int ABSENT = 0;
7506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
7606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Constant used to indicate #initialTimings is not null while parceling
7706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    private static final int PRESENT = 1;
7806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
7906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Throws exception if #totalBuckets is not greater than one.
8006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public TelephonyHistogram (int category, int id, int bucketCount) {
8106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        if (bucketCount <= 1) {
8206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            throw new IllegalArgumentException("Invalid number of buckets");
8306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        }
840680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mCategory = category;
850680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mId = id;
860680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mMinTimeMs = Integer.MAX_VALUE;
870680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mMaxTimeMs = 0;
880680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mAverageTimeMs = 0;
890680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mSampleCount = 0;
900680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mInitialTimings = new int[RANGE_CALCULATION_COUNT];
910680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketCount = bucketCount;
920680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketEndPoints = new int[bucketCount - 1];
930680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketCounters = new int[bucketCount];
9406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
9506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
9606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public TelephonyHistogram(TelephonyHistogram th) {
970680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mCategory = th.getCategory();
980680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mId = th.getId();
990680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mMinTimeMs = th.getMinTime();
1000680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mMaxTimeMs = th.getMaxTime();
1010680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mAverageTimeMs = th.getAverageTime();
1020680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mSampleCount = th.getSampleCount();
1030680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mInitialTimings = th.getInitialTimings();
1040680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketCount = th.getBucketCount();
1050680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketEndPoints = th.getBucketEndPoints();
1060680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketCounters = th.getBucketCounters();
10706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
10806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
10906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getCategory() {
1100680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mCategory;
11106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
11206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
11306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getId() {
1140680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mId;
11506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
11606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
11706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getMinTime() {
1180680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mMinTimeMs;
11906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
12006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
12106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getMaxTime() {
1220680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mMaxTimeMs;
12306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
12406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
12506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getAverageTime() {
1260680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mAverageTimeMs;
12706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
12806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
12906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getSampleCount () {
1300680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mSampleCount;
13106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
13206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
13306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    private int[] getInitialTimings() {
1340680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mInitialTimings;
13506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
13606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
13706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int getBucketCount() {
1380680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        return mBucketCount;
13906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
14006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
14106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int[] getBucketEndPoints() {
1420680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        if (mSampleCount > 1 && mSampleCount < 10) {
1430680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            int[] tempEndPoints = new int[mBucketCount - 1];
1440680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            calculateBucketEndPoints(tempEndPoints);
1450680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            return tempEndPoints;
1460680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        } else {
1470680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            return getDeepCopyOfArray(mBucketEndPoints);
1480680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        }
14906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
15006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
15106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int[] getBucketCounters() {
1520680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        if (mSampleCount > 1 && mSampleCount < 10) {
1530680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            int[] tempEndPoints = new int[mBucketCount - 1];
1540680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            int[] tempBucketCounters = new int[mBucketCount];
1550680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            calculateBucketEndPoints(tempEndPoints);
1560680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            for (int j = 0; j < mSampleCount; j++) {
1570680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                addToBucketCounter(tempEndPoints, tempBucketCounters, mInitialTimings[j]);
1580680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            }
1590680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            return tempBucketCounters;
1600680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        } else {
1610680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            return getDeepCopyOfArray(mBucketCounters);
1620680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        }
16306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
16406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
16506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    private int[] getDeepCopyOfArray(int[] array) {
16606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        int[] clone = new int[array.length];
16706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        System.arraycopy(array, 0, clone, 0, array.length);
16806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        return clone;
16906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
17006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
1710680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private void addToBucketCounter(int[] bucketEndPoints, int[] bucketCounters, int time) {
17206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        int i;
17306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        for (i = 0; i < bucketEndPoints.length; i++) {
17406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            if (time <= bucketEndPoints[i]) {
17506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                bucketCounters[i]++;
17606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                return;
17706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
17806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        }
17906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        bucketCounters[i]++;
18006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
18106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
1820680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    private void calculateBucketEndPoints(int[] bucketEndPoints) {
1830680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        for (int i = 1; i < mBucketCount; i++) {
1840680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            int endPt = mMinTimeMs + (i * (mMaxTimeMs - mMinTimeMs)) / mBucketCount;
1850680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            bucketEndPoints[i - 1] = endPt;
1860680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        }
1870680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe    }
1880680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe
18906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // Add new value of time taken
19006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // This function updates minTime, maxTime, averageTime & totalTimeCount every time it is
19106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // called. initialTimings[] is updated if totalTimeCount <= #RANGE_CALCULATION_COUNT. When
19206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // totalTimeCount = RANGE_CALCULATION_COUNT, based on the min, max time & the number of buckets
19306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // expected, bucketEndPoints[] would be calculated. Then bucketCounters[] would be filled up
19406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    // using values stored in initialTimings[]. Thereafter bucketCounters[] will always be updated.
19506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public void addTimeTaken(int time) {
19606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        // Initialize all fields if its first entry or if integer overflow is going to occur while
19706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        // trying to calculate averageTime
1980680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        if (mSampleCount == 0 || (mSampleCount == Integer.MAX_VALUE)) {
1990680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            if (mSampleCount == 0) {
2000680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mMinTimeMs = time;
2010680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mMaxTimeMs = time;
2020680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mAverageTimeMs = time;
20306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            } else {
2040680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mInitialTimings = new int[RANGE_CALCULATION_COUNT];
20506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
2060680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            mSampleCount = 1;
2070680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            Arrays.fill(mInitialTimings, 0);
2080680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            mInitialTimings[0] = time;
2090680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            Arrays.fill(mBucketEndPoints, 0);
2100680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            Arrays.fill(mBucketCounters, 0);
21106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        } else {
2120680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            if (time < mMinTimeMs) {
2130680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mMinTimeMs = time;
21406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
2150680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            if (time > mMaxTimeMs) {
2160680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mMaxTimeMs = time;
21706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
2180680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            long totalTime = ((long)mAverageTimeMs) * mSampleCount + time;
2190680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            mAverageTimeMs = (int)(totalTime/++mSampleCount);
22006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
2210680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            if (mSampleCount < RANGE_CALCULATION_COUNT) {
2220680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mInitialTimings[mSampleCount - 1] = time;
2230680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            } else if (mSampleCount == RANGE_CALCULATION_COUNT) {
2240680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mInitialTimings[mSampleCount - 1] = time;
22506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
22606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                // Calculate bucket endpoints based on bucketCount expected
2270680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                calculateBucketEndPoints(mBucketEndPoints);
22806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
22906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                // Use values stored in initialTimings[] to update bucketCounters
23006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                for (int j = 0; j < RANGE_CALCULATION_COUNT; j++) {
2310680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                    addToBucketCounter(mBucketEndPoints, mBucketCounters, mInitialTimings[j]);
23206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                }
2330680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                mInitialTimings = null;
23406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            } else {
2350680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                addToBucketCounter(mBucketEndPoints, mBucketCounters, time);
23606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
23706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
23806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        }
23906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
24006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
24106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public String toString() {
2420680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        String basic = " Histogram id = " + mId + " Time(ms): min = " + mMinTimeMs + " max = "
2430680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                + mMaxTimeMs + " avg = " + mAverageTimeMs + " Count = " + mSampleCount;
2440680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        if (mSampleCount < RANGE_CALCULATION_COUNT) {
24506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            return basic;
24606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        } else {
24706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            StringBuffer intervals = new StringBuffer(" Interval Endpoints:");
2480680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            for (int i = 0; i < mBucketEndPoints.length; i++) {
2490680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                intervals.append(" " + mBucketEndPoints[i]);
25006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
25106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            intervals.append(" Interval counters:");
2520680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            for (int i = 0; i < mBucketCounters.length; i++) {
2530680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe                intervals.append(" " + mBucketCounters[i]);
25406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            }
25506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            return basic + intervals;
25606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        }
25706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
25806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
25906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public static final Parcelable.Creator<TelephonyHistogram> CREATOR =
26006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            new Parcelable.Creator<TelephonyHistogram> () {
26106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
26206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                @Override
26306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                public TelephonyHistogram createFromParcel(Parcel in) {
26406e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                    return new TelephonyHistogram(in);
26506e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                }
26606e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
26706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                @Override
26806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                public TelephonyHistogram[] newArray(int size) {
26906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                    return new TelephonyHistogram[size];
27006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe                }
27106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            };
27206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
27306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public TelephonyHistogram(Parcel in) {
2740680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mCategory = in.readInt();
2750680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mId = in.readInt();
2760680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mMinTimeMs = in.readInt();
2770680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mMaxTimeMs = in.readInt();
2780680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mAverageTimeMs = in.readInt();
2790680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mSampleCount = in.readInt();
28006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        if (in.readInt() == PRESENT) {
2810680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            mInitialTimings = new int[RANGE_CALCULATION_COUNT];
2820680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            in.readIntArray(mInitialTimings);
28306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        }
2840680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketCount = in.readInt();
2850680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketEndPoints = new int[mBucketCount - 1];
2860680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        in.readIntArray(mBucketEndPoints);
2870680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        mBucketCounters = new int[mBucketCount];
2880680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        in.readIntArray(mBucketCounters);
28906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
29006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
29106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public void writeToParcel(Parcel out, int flags) {
2920680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mCategory);
2930680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mId);
2940680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mMinTimeMs);
2950680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mMaxTimeMs);
2960680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mAverageTimeMs);
2970680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mSampleCount);
2980680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        if (mInitialTimings == null) {
29906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            out.writeInt(ABSENT);
30006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        } else {
30106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe            out.writeInt(PRESENT);
3020680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe            out.writeIntArray(mInitialTimings);
30306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        }
3040680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeInt(mBucketCount);
3050680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeIntArray(mBucketEndPoints);
3060680f73f3d61c6fb31dc82ca81c58f7f6f1c39f8Sanket Padawe        out.writeIntArray(mBucketCounters);
30706e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
30806e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe
30906e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    @Override
31006e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    public int describeContents() {
31106e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe        return 0;
31206e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe    }
31306e1ae1a51b9fb8c65e610c22f86380c60a803a0Sanket Padawe}
314