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

Commit 03720395 authored by Rafael Higuera Silva's avatar Rafael Higuera Silva
Browse files

Add count and logic for sms metrics.

Add count field to SmsOutgoing and SmsIncoming.
Change logic when over 25 sms:
If there is a similar sms then update count
else replace the lowest count sms with the new one.

Bug: 233264472
Test: make, manual --Checking if after 25 outgoing and incoming sms, the count is updated

Change-Id: I323e2b593698af7945ad2db4f1d9ba030e1b5ea9
parent fa2b95fe
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -248,6 +248,10 @@ message IncomingSms {
    optional bool is_esim = 12;
    optional bool is_esim = 12;
    optional int32 carrier_id = 13;
    optional int32 carrier_id = 13;
    optional int64 message_id = 14;
    optional int64 message_id = 14;
    optional int32 count = 15;

    // Internal use only
    optional int32 hashCode = 10001;
}
}


message OutgoingSms {
message OutgoingSms {
@@ -265,6 +269,10 @@ message OutgoingSms {
    optional int64 message_id = 12;
    optional int64 message_id = 12;
    optional int32 retry_id = 13;
    optional int32 retry_id = 13;
    optional int64 interval_millis = 14;
    optional int64 interval_millis = 14;
    optional int32 count = 15;

    // Internal use only
    optional int32 hashCode = 10001;
}
}


message CarrierIdMismatch {
message CarrierIdMismatch {
+4 −2
Original line number Original line Diff line number Diff line
@@ -787,7 +787,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                sms.isMultiSim,
                sms.isMultiSim,
                sms.isEsim,
                sms.isEsim,
                sms.carrierId,
                sms.carrierId,
                sms.messageId);
                sms.messageId,
                sms.count);
    }
    }


    private static StatsEvent buildStatsEvent(OutgoingSms sms) {
    private static StatsEvent buildStatsEvent(OutgoingSms sms) {
@@ -806,7 +807,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                sms.carrierId,
                sms.carrierId,
                sms.messageId,
                sms.messageId,
                sms.retryId,
                sms.retryId,
                sms.intervalMillis);
                sms.intervalMillis,
                sms.count);
    }
    }


    private static StatsEvent buildStatsEvent(DataCallSession dataCallSession) {
    private static StatsEvent buildStatsEvent(DataCallSession dataCallSession) {
+95 −3
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.HandlerThread;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
import android.util.SparseIntArray;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.nano.PersistAtomsProto.CarrierIdMismatch;
import com.android.internal.telephony.nano.PersistAtomsProto.CarrierIdMismatch;
@@ -256,6 +257,7 @@ public class PersistAtomsStorage {


    /** Adds an incoming SMS to the storage. */
    /** Adds an incoming SMS to the storage. */
    public synchronized void addIncomingSms(IncomingSms sms) {
    public synchronized void addIncomingSms(IncomingSms sms) {
        sms.hashCode = SmsStats.getSmsHashCode(sms);
        mAtoms.incomingSms = insertAtRandomPlace(mAtoms.incomingSms, sms, mMaxNumSms);
        mAtoms.incomingSms = insertAtRandomPlace(mAtoms.incomingSms, sms, mMaxNumSms);
        saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
        saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);


@@ -265,6 +267,7 @@ public class PersistAtomsStorage {


    /** Adds an outgoing SMS to the storage. */
    /** Adds an outgoing SMS to the storage. */
    public synchronized void addOutgoingSms(OutgoingSms sms) {
    public synchronized void addOutgoingSms(OutgoingSms sms) {
        sms.hashCode = SmsStats.getSmsHashCode(sms);
        // Update the retry id, if needed, so that it's unique and larger than all
        // Update the retry id, if needed, so that it's unique and larger than all
        // previous ones. (this algorithm ignores the fact that some SMS atoms might
        // previous ones. (this algorithm ignores the fact that some SMS atoms might
        // be dropped due to limit in size of the array).
        // be dropped due to limit in size of the array).
@@ -1649,8 +1652,9 @@ public class PersistAtomsStorage {
    }
    }


    /**
    /**
     * Inserts a new element in a random position in an array with a maximum size, replacing the
     * Inserts a new element in a random position in an array with a maximum size.
     * least recent item if possible.
     *
     * <p>If the array is full, merge with existing item if possible or replace one item randomly.
     */
     */
    private static <T> T[] insertAtRandomPlace(T[] storage, T instance, int maxLength) {
    private static <T> T[] insertAtRandomPlace(T[] storage, T instance, int maxLength) {
        final int newLength = storage.length + 1;
        final int newLength = storage.length + 1;
@@ -1659,7 +1663,11 @@ public class PersistAtomsStorage {
        if (newLength == 1) {
        if (newLength == 1) {
            result[0] = instance;
            result[0] = instance;
        } else if (arrayFull) {
        } else if (arrayFull) {
            if (instance instanceof OutgoingSms || instance instanceof IncomingSms) {
                mergeSmsOrEvictInFullStorage(result, instance);
            } else {
                result[findItemToEvict(storage)] = instance;
                result[findItemToEvict(storage)] = instance;
            }
        } else {
        } else {
            // insert at random place (by moving the item at the random place to the end)
            // insert at random place (by moving the item at the random place to the end)
            int insertAt = sRandom.nextInt(newLength);
            int insertAt = sRandom.nextInt(newLength);
@@ -1669,6 +1677,90 @@ public class PersistAtomsStorage {
        return result;
        return result;
    }
    }


    /**
     * Merge new sms in a full storage.
     *
     * <p>If new sms is similar to old sms, merge them.
     * If not, merge 2 old similar sms and add the new sms.
     * If not, replace old sms with the lowest count.
     */
    private static <T> void mergeSmsOrEvictInFullStorage(T[] storage, T instance) {
        // key: hashCode, value: smsIndex
        SparseIntArray map = new SparseIntArray();
        int smsIndex1 = -1;
        int smsIndex2 = -1;
        int indexLowestCount = -1;
        int minCount = Integer.MAX_VALUE;

        for (int i = 0; i < storage.length; i++) {
            // If the new SMS can be merged to an existing item, merge it and return immediately.
            if (areSmsMergeable(storage[i], instance)) {
                storage[i] = mergeSms(storage[i], instance);
                return;
            }

            // Keep sms index with lowest count to evict, in case we cannot merge any 2 messages.
            int smsCount = getSmsCount(storage[i]);
            if (smsCount < minCount) {
                indexLowestCount = i;
                minCount = smsCount;
            }

            // Find any 2 messages in the storage that can be merged together.
            if (smsIndex1 != -1) {
                int smsHashCode = getSmsHashCode(storage[i]);
                if (map.indexOfKey(smsHashCode) < 0) {
                    map.append(smsHashCode, i);
                } else {
                    smsIndex1 = map.get(smsHashCode);
                    smsIndex2 = i;
                }
            }
        }

        // Merge 2 similar old sms and add the new sms
        if (smsIndex1 != -1) {
            storage[smsIndex1] = mergeSms(storage[smsIndex1], storage[smsIndex2]);
            storage[smsIndex2] = instance;
            return;
        }

        // Or replace old sms that has the lowest count
        storage[indexLowestCount] = instance;
        return;
    }

    private static <T> int getSmsHashCode(T sms) {
        return sms instanceof OutgoingSms
                ? ((OutgoingSms) sms).hashCode : ((IncomingSms) sms).hashCode;
    }

    private static <T> int getSmsCount(T sms) {
        return sms instanceof OutgoingSms
                ? ((OutgoingSms) sms).count : ((IncomingSms) sms).count;
    }

    /** Compares 2 SMS hash codes to check if they can be clubbed together in the metrics. */
    private static <T> boolean areSmsMergeable(T instance1, T instance2) {
        return getSmsHashCode(instance1) == getSmsHashCode(instance2);
    }

    /** Merges sms2 data on top of sms1 and returns the merged value. */
    private static <T> T mergeSms(T sms1, T sms2) {
        if (sms1 instanceof OutgoingSms) {
            OutgoingSms tSms1 = (OutgoingSms) sms1;
            OutgoingSms tSms2 = (OutgoingSms) sms2;
            tSms1.intervalMillis = (tSms1.intervalMillis * tSms1.count
                    + tSms2.intervalMillis * tSms2.count) / (tSms1.count + tSms2.count);
            tSms1.count += tSms2.count;
        } else if (sms1 instanceof IncomingSms) {
            IncomingSms tSms1 = (IncomingSms) sms1;
            IncomingSms tSms2 = (IncomingSms) sms2;
            tSms1.count += tSms2.count;
        }
        return sms1;
    }

    /** Returns index of the item suitable for eviction when the array is full. */
    /** Returns index of the item suitable for eviction when the array is full. */
    private static <T> int findItemToEvict(T[] array) {
    private static <T> int findItemToEvict(T[] array) {
        if (array instanceof CellularServiceState[]) {
        if (array instanceof CellularServiceState[]) {
+23 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.telephony.Rlog;
import com.android.telephony.Rlog;


import java.util.Objects;
import java.util.Random;
import java.util.Random;


/** Collects sms events per phone ID for the pulled atom. */
/** Collects sms events per phone ID for the pulled atom. */
@@ -214,6 +215,7 @@ public class SmsStats {
        // Message ID is initialized with random number, as it is not available for all incoming
        // Message ID is initialized with random number, as it is not available for all incoming
        // SMS messages (e.g. those handled by OS or error cases).
        // SMS messages (e.g. those handled by OS or error cases).
        proto.messageId = RANDOM.nextLong();
        proto.messageId = RANDOM.nextLong();
        proto.count = 1;
        return proto;
        return proto;
    }
    }


@@ -238,6 +240,7 @@ public class SmsStats {
        // in the persistent storage.
        // in the persistent storage.
        proto.retryId = 0;
        proto.retryId = 0;
        proto.intervalMillis = intervalMillis;
        proto.intervalMillis = intervalMillis;
        proto.count = 1;
        return proto;
        return proto;
    }
    }


@@ -304,6 +307,26 @@ public class SmsStats {
        }
        }
    }
    }


    /**
     * Returns a hash value to identify messages that are identical for the purpose of merging them
     * together when storage is full.
     */
    static int getSmsHashCode(OutgoingSms sms) {
        return Objects.hash(sms.smsFormat, sms.smsTech, sms.rat, sms.sendResult, sms.errorCode,
                    sms.isRoaming, sms.isFromDefaultApp, sms.simSlotIndex, sms.isMultiSim,
                    sms.isEsim, sms.carrierId);
    }

    /**
     * Returns a hash value to identify messages that are identical for the purpose of merging them
     * together when storage is full.
     */
    static int getSmsHashCode(IncomingSms sms) {
        return Objects.hash(sms.smsFormat, sms.smsTech, sms.rat, sms.smsType,
            sms.totalParts, sms.receivedParts, sms.blocked, sms.error,
            sms.isRoaming, sms.simSlotIndex, sms.isMultiSim, sms.isEsim, sms.carrierId);
    }

    private int getPhoneId() {
    private int getPhoneId() {
        Phone phone = mPhone;
        Phone phone = mPhone;
        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {