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

Commit 1092c70e authored by Michele Berionne's avatar Michele Berionne
Browse files

Add metrics for 5G enterprise slicing.

Bug: 178075247
Test: manual
Change-Id: Ib61171cd918fe12acab3b155756fa923efdae819
Merged-In: Ib61171cd918fe12acab3b155756fa923efdae819
(cherry picked from commit de667dc2)
parent 78cd7974
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -87,6 +87,12 @@ message PersistAtoms {

    /* Last Android build fingerprint. This usually changes after system OTA. */
    optional string build_fingerprint = 21;

    /* Summary of received network requests. */
    repeated NetworkRequests network_requests = 22;

    /* Timestamp of last network_requests pull. */
    optional int64 network_requests_pull_timestamp_millis = 23;
}

// The canonical versions of the following enums live in:
@@ -261,3 +267,9 @@ message ImsRegistrationStats {
    // Internal use only
    optional int64 last_used_millis = 10001;
}

message NetworkRequests {
    optional int32 carrier_id = 1;
    optional int32 enterprise_request_count = 2;
    optional int32 enterprise_release_count = 3;
}
+2 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony.metrics;

import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;

import static com.android.internal.telephony.TelephonyStatsLog.AIRPLANE_MODE;

@@ -113,6 +114,6 @@ public class AirplaneModeStats extends ContentObserver {
        int phoneId = dataSubId != INVALID_SUBSCRIPTION_ID
                ? SubscriptionManager.getPhoneId(dataSubId) : 0;
        Phone phone = PhoneFactory.getPhone(phoneId);
        return phone != null ? phone.getCarrierId() : INVALID_SUBSCRIPTION_ID;
        return phone != null ? phone.getCarrierId() : UNKNOWN_CARRIER_ID;
    }
}
+26 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ 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.SIM_SLOT_STATE;
import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY;
import static com.android.internal.telephony.TelephonyStatsLog.TELEPHONY_NETWORK_REQUESTS;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION;

@@ -48,6 +49,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
@@ -117,6 +119,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
            registerAtom(DATA_CALL_SESSION, POLICY_PULL_DAILY);
            registerAtom(IMS_REGISTRATION_STATS, POLICY_PULL_DAILY);
            registerAtom(IMS_REGISTRATION_TERMINATION, POLICY_PULL_DAILY);
            registerAtom(TELEPHONY_NETWORK_REQUESTS, POLICY_PULL_DAILY);

            Rlog.d(TAG, "registered");
        } else {
@@ -166,6 +169,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                return pullImsRegistrationStats(data);
            case IMS_REGISTRATION_TERMINATION:
                return pullImsRegistrationTermination(data);
            case TELEPHONY_NETWORK_REQUESTS:
                return pullTelephonyNetworkRequests(data);
            default:
                Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag));
                return StatsManager.PULL_SKIP;
@@ -373,6 +378,18 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
        }
    }

    private int pullTelephonyNetworkRequests(List<StatsEvent> data) {
        NetworkRequests[] persistAtoms = mStorage.getNetworkRequests(MIN_COOLDOWN_MILLIS);
        if (persistAtoms != null) {
            Arrays.stream(persistAtoms)
                    .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
            return StatsManager.PULL_SUCCESS;
        } else {
            Rlog.w(TAG, "TELEPHONY_NETWORK_REQUESTS 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);
@@ -583,6 +600,15 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                .build();
    }

    private static StatsEvent buildStatsEvent(NetworkRequests networkRequests) {
        return StatsEvent.newBuilder()
                .setAtomId(TELEPHONY_NETWORK_REQUESTS)
                .writeInt(networkRequests.carrierId)
                .writeInt(networkRequests.enterpriseRequestCount)
                .writeInt(networkRequests.enterpriseReleaseCount)
                .build();
    }

    /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */
    private static Phone[] getPhonesIfAny() {
        try {
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 com.android.internal.telephony.metrics;

import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests;


/** Metrics for the network requests. */
public class NetworkRequestsStats {
    private NetworkRequestsStats() { }

    /** Generate metrics when enterprise network request occurs. */
    public static void addEnterpriseRequest(int subId) {
        NetworkRequests networkRequests = new NetworkRequests();
        networkRequests.carrierId = getCarrierId(subId);
        networkRequests.enterpriseRequestCount = 1;

        PersistAtomsStorage storage = PhoneFactory.getMetricsCollector().getAtomsStorage();
        storage.addNetworkRequests(networkRequests);
    }

    /** Generate metrics when enterprise network release occurs. */
    public static void addEnterpriseRelease(int subId) {
        NetworkRequests networkRequests = new NetworkRequests();
        networkRequests.carrierId = getCarrierId(subId);
        networkRequests.enterpriseReleaseCount = 1;

        PersistAtomsStorage storage = PhoneFactory.getMetricsCollector().getAtomsStorage();
        storage.addNetworkRequests(networkRequests);
    }

    /** Returns the carrier ID of the given subscription id. */
    private static int getCarrierId(int subId) {
        int phoneId = SubscriptionManager.getPhoneId(subId);
        Phone phone = PhoneFactory.getPhone(phoneId);
        return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID;
    }
}
+49 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms;
import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
@@ -299,6 +300,20 @@ public class PersistAtomsStorage {
        }
    }

    /** Adds a new {@link NetworkRequests} to the storage. */
    public synchronized void addNetworkRequests(NetworkRequests networkRequests) {
        NetworkRequests existingMetrics = find(networkRequests);
        if (existingMetrics != null) {
            existingMetrics.enterpriseRequestCount += networkRequests.enterpriseRequestCount;
            existingMetrics.enterpriseReleaseCount += networkRequests.enterpriseReleaseCount;
        } else {
            int newLength = mAtoms.networkRequests.length + 1;
            mAtoms.networkRequests = Arrays.copyOf(mAtoms.networkRequests, newLength);
            mAtoms.networkRequests[newLength - 1] = networkRequests;
        }
        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}.
@@ -465,6 +480,23 @@ public class PersistAtomsStorage {
        }
    }

    /**
     * Returns and clears the network requests if last pulled longer than {@code
     * minIntervalMillis} ago, otherwise returns {@code null}.
     */
    @Nullable
    public synchronized NetworkRequests[] getNetworkRequests(long minIntervalMillis) {
        if (getWallTimeMillis() - mAtoms.networkRequestsPullTimestampMillis > minIntervalMillis) {
            mAtoms.networkRequestsPullTimestampMillis = getWallTimeMillis();
            NetworkRequests[] previousNetworkRequests = mAtoms.networkRequests;
            mAtoms.networkRequests = new NetworkRequests[0];
            saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
            return previousNetworkRequests;
        } else {
            return null;
        }
    }

    /** Loads {@link PersistAtoms} from a file in private storage. */
    private PersistAtoms loadAtomsFromFile() {
        try {
@@ -515,6 +547,7 @@ public class PersistAtomsStorage {
                            atoms.imsRegistrationTermination,
                            ImsRegistrationTermination.class,
                            MAX_NUM_IMS_REGISTRATION_TERMINATIONS);
            atoms.networkRequests = sanitizeAtoms(atoms.networkRequests, NetworkRequests.class);
            // out of caution, sanitize also the timestamps
            atoms.voiceCallRatUsagePullTimestampMillis =
                    sanitizeTimestamp(atoms.voiceCallRatUsagePullTimestampMillis);
@@ -534,6 +567,8 @@ public class PersistAtomsStorage {
                    sanitizeTimestamp(atoms.imsRegistrationStatsPullTimestampMillis);
            atoms.imsRegistrationTerminationPullTimestampMillis =
                    sanitizeTimestamp(atoms.imsRegistrationTerminationPullTimestampMillis);
            atoms.networkRequestsPullTimestampMillis =
                    sanitizeTimestamp(atoms.networkRequestsPullTimestampMillis);
            return atoms;
        } catch (NoSuchFileException e) {
            Rlog.d(TAG, "PersistAtoms file not found");
@@ -656,6 +691,19 @@ public class PersistAtomsStorage {
        return null;
    }

    /**
     * Returns the network requests event that has the same carrier id as the given one,
     * or {@code null} if it does not exist.
     */
    private @Nullable NetworkRequests find(NetworkRequests key) {
        for (NetworkRequests item : mAtoms.networkRequests) {
            if (item.carrierId == key.carrierId) {
                return item;
            }
        }
        return null;
    }

    /**
     * Inserts a new element in a random position in an array with a maximum size, replacing the
     * least recent item if possible.
@@ -745,6 +793,7 @@ public class PersistAtomsStorage {
        atoms.cellularDataServiceSwitchPullTimestampMillis = currentTime;
        atoms.imsRegistrationStatsPullTimestampMillis = currentTime;
        atoms.imsRegistrationTerminationPullTimestampMillis = currentTime;
        atoms.networkRequestsPullTimestampMillis = currentTime;
        Rlog.d(TAG, "created new PersistAtoms");
        return atoms;
    }