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

Commit b4e8963a authored by Aishwarya Mallampati's avatar Aishwarya Mallampati Committed by Android (Google) Code Review
Browse files

Merge "Implementation of premium sms metrics."

parents 7f910ff6 db6a07e2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -180,6 +180,12 @@ message PersistAtoms {

    /* Unmetered networks information. */
    repeated UnmeteredNetworks unmetered_networks = 52;

    /* Outgoing Short Code SMS statistics and information. */
    repeated OutgoingShortCodeSms outgoing_short_code_sms = 53;

    /* Timestamp of last outgoing_short_code_sms pull. */
    optional int64 outgoing_short_code_sms_pull_timestamp_millis = 54;
}

// The canonical versions of the following enums live in:
@@ -516,3 +522,9 @@ message UnmeteredNetworks {
    optional int32 carrier_id = 2;
    optional int64 unmetered_networks_bitmask = 3;
}

message OutgoingShortCodeSms {
    optional int32 category = 1;
    optional int32 xml_version = 2;
    optional int32 short_code_sms_count = 3;
}
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
@@ -1861,6 +1861,12 @@ public abstract class SMSDispatcher extends Handler {
                                                trackers[0].mDestAddress, networkCountryIso));
            }

            if (smsCategory != SmsManager.SMS_CATEGORY_NOT_SHORT_CODE) {
                int xmlVersion = mSmsDispatchersController.getUsageMonitor()
                        .getShortCodeXmlFileVersion();
                mPhone.getSmsStats().onOutgoingShortCodeSms(smsCategory, xmlVersion);
            }

            if (smsCategory == SmsManager.SMS_CATEGORY_NOT_SHORT_CODE
                    || smsCategory == SmsManager.SMS_CATEGORY_FREE_SHORT_CODE
                    || smsCategory == SmsManager.SMS_CATEGORY_STANDARD_SHORT_CODE) {
+38 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -73,6 +74,8 @@ public class SmsUsageMonitor {

    private static final String SHORT_CODE_PATH = "/data/misc/sms/codes";

    private static final String SHORT_CODE_VERSION_PATH = "/data/misc/sms/metadata/version";

    /** Default checking period for SMS sent without user permission. */
    private static final int DEFAULT_SMS_CHECK_PERIOD = 60000;      // 1 minute

@@ -128,6 +131,8 @@ public class SmsUsageMonitor {
    /** Last modified time for pattern file */
    private long mPatternFileLastModified = 0;

    private int mPatternFileVersion = -1;

    private RoleManager mRoleManager;

    /** Directory for per-app SMS permission XML file. */
@@ -415,9 +420,11 @@ public class SmsUsageMonitor {
                    if (mPatternFile.exists()) {
                        if (DBG) Rlog.d(TAG, "Loading SMS Short Code patterns from file");
                        mCurrentPatternMatcher = getPatternMatcherFromFile(countryIso);
                        mPatternFileVersion = getPatternFileVersionFromFile();
                    } else {
                        if (DBG) Rlog.d(TAG, "Loading SMS Short Code patterns from resource");
                        mCurrentPatternMatcher = getPatternMatcherFromResource(countryIso);
                        mPatternFileVersion = -1;
                    }
                    mCurrentCountry = countryIso;
                }
@@ -655,6 +662,37 @@ public class SmsUsageMonitor {
        return false;
    }

    private int getPatternFileVersionFromFile() {
        File versionFile = new File(SHORT_CODE_VERSION_PATH);
        if (versionFile.exists()) {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader(versionFile));
                String version = reader.readLine();
                if (version != null) {
                    return Integer.parseInt(version);
                }
            } catch (IOException e) {
                Rlog.e(TAG, "File reader exception reading short code "
                        + "pattern file version", e);
            } finally {
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    Rlog.e(TAG, "File reader exception closing short code "
                            + "pattern file version reader", e);
                }
            }
        }
        return -1;
    }

    public int getShortCodeXmlFileVersion() {
        return mPatternFileVersion;
    }

    private static void log(String msg) {
        Rlog.d(TAG, msg);
    }
+26 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_
import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_TERMINATION;
import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SHORT_CODE_SMS;
import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS;
import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS;
@@ -69,6 +70,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTerm
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequestsV2;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
@@ -176,6 +178,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
            registerAtom(PRESENCE_NOTIFY_EVENT, POLICY_PULL_DAILY);
            registerAtom(GBA_EVENT, POLICY_PULL_DAILY);
            registerAtom(PER_SIM_STATUS, null);
            registerAtom(OUTGOING_SHORT_CODE_SMS, POLICY_PULL_DAILY);

            Rlog.d(TAG, "registered");
        } else {
@@ -251,6 +254,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                return pullGbaEvent(data);
            case PER_SIM_STATUS:
                return pullPerSimStatus(data);
            case OUTGOING_SHORT_CODE_SMS:
                return pullOutgoingShortCodeSms(data);
            default:
                Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag));
                return StatsManager.PULL_SKIP;
@@ -692,6 +697,19 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
        return result;
    }

    private int pullOutgoingShortCodeSms(List<StatsEvent> data) {
        OutgoingShortCodeSms[] outgoingShortCodeSmsList = mStorage
                .getOutgoingShortCodeSms(MIN_COOLDOWN_MILLIS);
        if (outgoingShortCodeSmsList != null) {
            // Outgoing short code SMS list is already shuffled when SMS were inserted
            Arrays.stream(outgoingShortCodeSmsList).forEach(sms -> data.add(buildStatsEvent(sms)));
            return StatsManager.PULL_SUCCESS;
        } else {
            Rlog.w(TAG, "OUTGOING_SHORT_CODE_SMS pull too frequent, skipping");
            return StatsManager.PULL_SKIP;
        }
    }

    /** Registers a pulled atom ID {@code atomId} with optional {@code policy} for pulling. */
    private void registerAtom(int atomId, @Nullable StatsManager.PullAtomMetadata policy) {
        mStatsManager.setPullAtomCallback(atomId, policy, ConcurrentUtils.DIRECT_EXECUTOR, this);
@@ -1025,6 +1043,14 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                stats.count);
    }

    private static StatsEvent buildStatsEvent(OutgoingShortCodeSms shortCodeSms) {
        return TelephonyStatsLog.buildStatsEvent(
                OUTGOING_SHORT_CODE_SMS,
                shortCodeSms.category,
                shortCodeSms.xmlVersion,
                shortCodeSms.shortCodeSmsCount);
    }

    /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */
    private static Phone[] getPhonesIfAny() {
        try {
+57 −1
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTerm
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequestsV2;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms;
import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
@@ -159,6 +160,10 @@ public class PersistAtomsStorage {
    /** Maximum number of GBA Event to store between pulls. */
    private final int mMaxNumGbaEventStats;


     /** Maximum number of outgoing short code sms to store between pulls. */
    private final int mMaxOutgoingShortCodeSms;

    /** Stores persist atoms and persist states of the puller. */
    @VisibleForTesting protected PersistAtoms mAtoms;

@@ -207,6 +212,7 @@ public class PersistAtomsStorage {
            mMaxNumUceEventStats = 5;
            mMaxNumPresenceNotifyEventStats = 10;
            mMaxNumGbaEventStats = 5;
            mMaxOutgoingShortCodeSms = 5;
        } else {
            mMaxNumVoiceCallSessions = 50;
            mMaxNumSms = 25;
@@ -229,6 +235,7 @@ public class PersistAtomsStorage {
            mMaxNumUceEventStats = 25;
            mMaxNumPresenceNotifyEventStats = 50;
            mMaxNumGbaEventStats = 10;
            mMaxOutgoingShortCodeSms = 10;
        }

        mAtoms = loadAtomsFromFile();
@@ -655,6 +662,18 @@ public class PersistAtomsStorage {
        }
    }

    /** Adds an outgoing short code sms to the storage. */
    public synchronized void addOutgoingShortCodeSms(OutgoingShortCodeSms shortCodeSms) {
        OutgoingShortCodeSms existingOutgoingShortCodeSms = find(shortCodeSms);
        if (existingOutgoingShortCodeSms != null) {
            existingOutgoingShortCodeSms.shortCodeSmsCount += 1;
        } else {
            mAtoms.outgoingShortCodeSms = insertAtRandomPlace(mAtoms.outgoingShortCodeSms,
                    shortCodeSms, mMaxOutgoingShortCodeSms);
        }
        saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
    }

    /**
     * Returns and clears the voice call sessions if last pulled longer than {@code
     * minIntervalMillis} ago, otherwise returns {@code null}.
@@ -1174,6 +1193,24 @@ public class PersistAtomsStorage {
        return bitmask;
    }

    /**
     * Returns and clears the OutgoingShortCodeSms if last pulled longer than {@code
     * minIntervalMillis} ago, otherwise returns {@code null}.
     */
    @Nullable
    public synchronized OutgoingShortCodeSms[] getOutgoingShortCodeSms(long minIntervalMillis) {
        if ((getWallTimeMillis() - mAtoms.outgoingShortCodeSmsPullTimestampMillis)
                > minIntervalMillis) {
            mAtoms.outgoingShortCodeSmsPullTimestampMillis = getWallTimeMillis();
            OutgoingShortCodeSms[] previousOutgoingShortCodeSms = mAtoms.outgoingShortCodeSms;
            mAtoms.outgoingShortCodeSms = new OutgoingShortCodeSms[0];
            saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
            return previousOutgoingShortCodeSms;
        } else {
            return null;
        }
    }

    /** Saves {@link PersistAtoms} to a file in private storage immediately. */
    public synchronized void flushAtoms() {
        saveAtomsToFile(0);
@@ -1309,6 +1346,8 @@ public class PersistAtomsStorage {
                            atoms.unmeteredNetworks,
                            UnmeteredNetworks.class
                    );
            atoms.outgoingShortCodeSms = sanitizeAtoms(atoms.outgoingShortCodeSms,
                    OutgoingShortCodeSms.class, mMaxOutgoingShortCodeSms);

            // out of caution, sanitize also the timestamps
            atoms.voiceCallRatUsagePullTimestampMillis =
@@ -1357,6 +1396,8 @@ public class PersistAtomsStorage {
                    sanitizeTimestamp(atoms.presenceNotifyEventPullTimestampMillis);
            atoms.gbaEventPullTimestampMillis =
                    sanitizeTimestamp(atoms.gbaEventPullTimestampMillis);
            atoms.outgoingShortCodeSmsPullTimestampMillis =
                    sanitizeTimestamp(atoms.outgoingShortCodeSmsPullTimestampMillis);

            return atoms;
        } catch (NoSuchFileException e) {
@@ -1724,6 +1765,20 @@ public class PersistAtomsStorage {
        return null;
    }

    /**
     * Returns OutgoingShortCodeSms atom that has same category, xmlVersion as the given one,
     * or {@code null} if it does not exist.
     */
    private @Nullable OutgoingShortCodeSms find(OutgoingShortCodeSms key) {
        for (OutgoingShortCodeSms shortCodeSms : mAtoms.outgoingShortCodeSms) {
            if (shortCodeSms.category == key.category
                    && shortCodeSms.xmlVersion == key.xmlVersion) {
                return shortCodeSms;
            }
        }
        return null;
    }

    /**
     * Inserts a new element in a random position in an array with a maximum size.
     *
@@ -1969,6 +2024,7 @@ public class PersistAtomsStorage {
        atoms.uceEventStatsPullTimestampMillis = currentTime;
        atoms.presenceNotifyEventPullTimestampMillis = currentTime;
        atoms.gbaEventPullTimestampMillis = currentTime;
        atoms.outgoingShortCodeSmsPullTimestampMillis = currentTime;

        Rlog.d(TAG, "created new PersistAtoms");
        return atoms;
Loading