• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.metrics;
18 
19 import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ID_TABLE_VERSION;
20 import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH;
21 import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE;
22 import static com.android.internal.telephony.TelephonyStatsLog.DATA_CALL_SESSION;
23 import static com.android.internal.telephony.TelephonyStatsLog.DEVICE_TELEPHONY_PROPERTIES;
24 import static com.android.internal.telephony.TelephonyStatsLog.EMERGENCY_NUMBERS_INFO;
25 import static com.android.internal.telephony.TelephonyStatsLog.GBA_EVENT;
26 import static com.android.internal.telephony.TelephonyStatsLog.IMS_DEDICATED_BEARER_EVENT;
27 import static com.android.internal.telephony.TelephonyStatsLog.IMS_DEDICATED_BEARER_LISTENER_EVENT;
28 import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_FEATURE_TAG_STATS;
29 import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_SERVICE_DESC_STATS;
30 import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_STATS;
31 import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_TERMINATION;
32 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS;
33 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SHORT_CODE_SMS;
34 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS;
35 import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS;
36 import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT;
37 import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS;
38 import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS;
39 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONTROLLER;
40 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_INCOMING_DATAGRAM;
41 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_OUTGOING_DATAGRAM;
42 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_PROVISION;
43 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_SESSION;
44 import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_SOS_MESSAGE_RECOMMENDER;
45 import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE;
46 import static com.android.internal.telephony.TelephonyStatsLog.SIP_DELEGATE_STATS;
47 import static com.android.internal.telephony.TelephonyStatsLog.SIP_MESSAGE_RESPONSE;
48 import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_FEATURE_TAG_STATS;
49 import static com.android.internal.telephony.TelephonyStatsLog.SIP_TRANSPORT_SESSION;
50 import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY;
51 import static com.android.internal.telephony.TelephonyStatsLog.TELEPHONY_NETWORK_REQUESTS_V2;
52 import static com.android.internal.telephony.TelephonyStatsLog.UCE_EVENT_STATS;
53 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE;
54 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION;
55 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
56 
57 import android.app.StatsManager;
58 import android.content.Context;
59 import android.telephony.SubscriptionManager;
60 import android.telephony.TelephonyManager;
61 import android.util.StatsEvent;
62 
63 import com.android.internal.annotations.VisibleForTesting;
64 import com.android.internal.telephony.Phone;
65 import com.android.internal.telephony.PhoneFactory;
66 import com.android.internal.telephony.TelephonyStatsLog;
67 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
68 import com.android.internal.telephony.imsphone.ImsPhone;
69 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
70 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
71 import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
72 import com.android.internal.telephony.nano.PersistAtomsProto.EmergencyNumbersInfo;
73 import com.android.internal.telephony.nano.PersistAtomsProto.GbaEvent;
74 import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerEvent;
75 import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerListenerEvent;
76 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationFeatureTagStats;
77 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationServiceDescStats;
78 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats;
79 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
80 import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
81 import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequestsV2;
82 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
83 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
84 import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
85 import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
86 import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
87 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController;
88 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram;
89 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram;
90 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision;
91 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteSession;
92 import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteSosMessageRecommender;
93 import com.android.internal.telephony.nano.PersistAtomsProto.SipDelegateStats;
94 import com.android.internal.telephony.nano.PersistAtomsProto.SipMessageResponse;
95 import com.android.internal.telephony.nano.PersistAtomsProto.SipTransportFeatureTagStats;
96 import com.android.internal.telephony.nano.PersistAtomsProto.SipTransportSession;
97 import com.android.internal.telephony.nano.PersistAtomsProto.UceEventStats;
98 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
99 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
100 import com.android.internal.util.ConcurrentUtils;
101 import com.android.telephony.Rlog;
102 
103 import java.time.Duration;
104 import java.util.Arrays;
105 import java.util.Comparator;
106 import java.util.List;
107 import java.util.Random;
108 import java.util.Set;
109 import java.util.concurrent.ConcurrentHashMap;
110 
111 /**
112  * Implements statsd pullers for Telephony.
113  *
114  * <p>This class registers pullers to statsd, which will be called once a day to obtain telephony
115  * statistics that cannot be sent to statsd in real time.
116  */
117 public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
118     private static final String TAG = MetricsCollector.class.getSimpleName();
119 
120     /** Disables various restrictions to ease debugging during development. */
121     private static final boolean DBG = false; // STOPSHIP if true
122 
123     private static final long MILLIS_PER_HOUR = Duration.ofHours(1).toMillis();
124     private static final long MILLIS_PER_MINUTE = Duration.ofMinutes(1).toMillis();
125     private static final long MILLIS_PER_SECOND = Duration.ofSeconds(1).toMillis();
126 
127     /**
128      * Sets atom pull cool down to 23 hours to help enforcing privacy requirement.
129      *
130      * <p>Applies to certain atoms. The interval of 23 hours leaves some margin for pull operations
131      * that occur once a day.
132      */
133     private static final long MIN_COOLDOWN_MILLIS =
134             DBG ? 10L * MILLIS_PER_SECOND : 23L * MILLIS_PER_HOUR;
135 
136     /**
137      * Buckets with less than these many calls will be dropped.
138      *
139      * <p>Applies to metrics with duration fields. Currently used by voice call RAT usages.
140      */
141     private static final long MIN_CALLS_PER_BUCKET = DBG ? 0L : 5L;
142 
143     /** Bucket size in milliseconds to round call durations into. */
144     private static final long DURATION_BUCKET_MILLIS =
145             DBG ? 2L * MILLIS_PER_SECOND : 5L * MILLIS_PER_MINUTE;
146 
147     private final PersistAtomsStorage mStorage;
148     private final DeviceStateHelper mDeviceStateHelper;
149     private final StatsManager mStatsManager;
150     private final AirplaneModeStats mAirplaneModeStats;
151     private final Set<DataCallSessionStats> mOngoingDataCallStats = ConcurrentHashMap.newKeySet();
152     private static final Random sRandom = new Random();
153 
MetricsCollector(Context context)154     public MetricsCollector(Context context) {
155         this(context, new PersistAtomsStorage(context), new DeviceStateHelper(context));
156     }
157 
158     /** Allows dependency injection. Used during unit tests. */
159     @VisibleForTesting
MetricsCollector( Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper)160     public MetricsCollector(
161             Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper) {
162         mStorage = storage;
163         mDeviceStateHelper = deviceStateHelper;
164         mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
165         if (mStatsManager != null) {
166             // Most (but not all) of these are subject to cooldown specified by MIN_COOLDOWN_MILLIS.
167             registerAtom(CELLULAR_DATA_SERVICE_SWITCH);
168             registerAtom(CELLULAR_SERVICE_STATE);
169             registerAtom(SIM_SLOT_STATE);
170             registerAtom(SUPPORTED_RADIO_ACCESS_FAMILY);
171             registerAtom(VOICE_CALL_RAT_USAGE);
172             registerAtom(VOICE_CALL_SESSION);
173             registerAtom(INCOMING_SMS);
174             registerAtom(OUTGOING_SMS);
175             registerAtom(CARRIER_ID_TABLE_VERSION);
176             registerAtom(DATA_CALL_SESSION);
177             registerAtom(IMS_REGISTRATION_STATS);
178             registerAtom(IMS_REGISTRATION_TERMINATION);
179             registerAtom(TELEPHONY_NETWORK_REQUESTS_V2);
180             registerAtom(IMS_REGISTRATION_FEATURE_TAG_STATS);
181             registerAtom(RCS_CLIENT_PROVISIONING_STATS);
182             registerAtom(RCS_ACS_PROVISIONING_STATS);
183             registerAtom(SIP_DELEGATE_STATS);
184             registerAtom(SIP_TRANSPORT_FEATURE_TAG_STATS);
185             registerAtom(SIP_MESSAGE_RESPONSE);
186             registerAtom(SIP_TRANSPORT_SESSION);
187             registerAtom(DEVICE_TELEPHONY_PROPERTIES);
188             registerAtom(IMS_DEDICATED_BEARER_LISTENER_EVENT);
189             registerAtom(IMS_DEDICATED_BEARER_EVENT);
190             registerAtom(IMS_REGISTRATION_SERVICE_DESC_STATS);
191             registerAtom(UCE_EVENT_STATS);
192             registerAtom(PRESENCE_NOTIFY_EVENT);
193             registerAtom(GBA_EVENT);
194             registerAtom(PER_SIM_STATUS);
195             registerAtom(OUTGOING_SHORT_CODE_SMS);
196             registerAtom(SATELLITE_CONTROLLER);
197             registerAtom(SATELLITE_SESSION);
198             registerAtom(SATELLITE_INCOMING_DATAGRAM);
199             registerAtom(SATELLITE_OUTGOING_DATAGRAM);
200             registerAtom(SATELLITE_PROVISION);
201             registerAtom(SATELLITE_SOS_MESSAGE_RECOMMENDER);
202             registerAtom(EMERGENCY_NUMBERS_INFO);
203             Rlog.d(TAG, "registered");
204         } else {
205             Rlog.e(TAG, "could not get StatsManager, atoms not registered");
206         }
207 
208         mAirplaneModeStats = new AirplaneModeStats(context);
209     }
210 
211     /**
212      * {@inheritDoc}
213      *
214      * @return {@link StatsManager#PULL_SUCCESS} with list of atoms (potentially empty) if pull
215      *     succeeded, {@link StatsManager#PULL_SKIP} if pull was too frequent or atom ID is
216      *     unexpected.
217      */
218     @Override
onPullAtom(int atomTag, List<StatsEvent> data)219     public int onPullAtom(int atomTag, List<StatsEvent> data) {
220         switch (atomTag) {
221             case CELLULAR_DATA_SERVICE_SWITCH:
222                 return pullCellularDataServiceSwitch(data);
223             case CELLULAR_SERVICE_STATE:
224                 return pullCellularServiceState(data);
225             case SIM_SLOT_STATE:
226                 return pullSimSlotState(data);
227             case SUPPORTED_RADIO_ACCESS_FAMILY:
228                 return pullSupportedRadioAccessFamily(data);
229             case VOICE_CALL_RAT_USAGE:
230                 return pullVoiceCallRatUsages(data);
231             case VOICE_CALL_SESSION:
232                 return pullVoiceCallSessions(data);
233             case INCOMING_SMS:
234                 return pullIncomingSms(data);
235             case OUTGOING_SMS:
236                 return pullOutgoingSms(data);
237             case CARRIER_ID_TABLE_VERSION:
238                 return pullCarrierIdTableVersion(data);
239             case DATA_CALL_SESSION:
240                 return pullDataCallSession(data);
241             case IMS_REGISTRATION_STATS:
242                 return pullImsRegistrationStats(data);
243             case IMS_REGISTRATION_TERMINATION:
244                 return pullImsRegistrationTermination(data);
245             case TELEPHONY_NETWORK_REQUESTS_V2:
246                 return pullTelephonyNetworkRequestsV2(data);
247             case DEVICE_TELEPHONY_PROPERTIES:
248                 return pullDeviceTelephonyProperties(data);
249             case IMS_REGISTRATION_FEATURE_TAG_STATS:
250                 return pullImsRegistrationFeatureTagStats(data);
251             case RCS_CLIENT_PROVISIONING_STATS:
252                 return pullRcsClientProvisioningStats(data);
253             case RCS_ACS_PROVISIONING_STATS:
254                 return pullRcsAcsProvisioningStats(data);
255             case SIP_DELEGATE_STATS:
256                 return pullSipDelegateStats(data);
257             case SIP_TRANSPORT_FEATURE_TAG_STATS:
258                 return pullSipTransportFeatureTagStats(data);
259             case SIP_MESSAGE_RESPONSE:
260                 return pullSipMessageResponse(data);
261             case SIP_TRANSPORT_SESSION:
262                 return pullSipTransportSession(data);
263             case IMS_DEDICATED_BEARER_LISTENER_EVENT:
264                 return pullImsDedicatedBearerListenerEvent(data);
265             case IMS_DEDICATED_BEARER_EVENT:
266                 return pullImsDedicatedBearerEvent(data);
267             case IMS_REGISTRATION_SERVICE_DESC_STATS:
268                 return pullImsRegistrationServiceDescStats(data);
269             case UCE_EVENT_STATS:
270                 return pullUceEventStats(data);
271             case PRESENCE_NOTIFY_EVENT:
272                 return pullPresenceNotifyEvent(data);
273             case GBA_EVENT:
274                 return pullGbaEvent(data);
275             case PER_SIM_STATUS:
276                 return pullPerSimStatus(data);
277             case OUTGOING_SHORT_CODE_SMS:
278                 return pullOutgoingShortCodeSms(data);
279             case SATELLITE_CONTROLLER:
280                 return pullSatelliteController(data);
281             case SATELLITE_SESSION:
282                 return pullSatelliteSession(data);
283             case SATELLITE_INCOMING_DATAGRAM:
284                 return pullSatelliteIncomingDatagram(data);
285             case SATELLITE_OUTGOING_DATAGRAM:
286                 return pullSatelliteOutgoingDatagram(data);
287             case SATELLITE_PROVISION:
288                 return pullSatelliteProvision(data);
289             case SATELLITE_SOS_MESSAGE_RECOMMENDER:
290                 return pullSatelliteSosMessageRecommender(data);
291             case EMERGENCY_NUMBERS_INFO:
292                 return pullEmergencyNumbersInfo(data);
293             default:
294                 Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag));
295                 return StatsManager.PULL_SKIP;
296         }
297     }
298 
299     /** Returns the {@link PersistAtomsStorage} backing the puller. */
getAtomsStorage()300     public PersistAtomsStorage getAtomsStorage() {
301         return mStorage;
302     }
303 
304     /** Returns the {@link DeviceStateHelper}. */
getDeviceStateHelper()305     public DeviceStateHelper getDeviceStateHelper() {
306         return mDeviceStateHelper;
307     }
308 
309     /** Updates duration segments and calls {@link PersistAtomsStorage#flushAtoms()}. */
flushAtomsStorage()310     public void flushAtomsStorage() {
311         concludeAll();
312         mStorage.flushAtoms();
313     }
314 
315     /** Updates duration segments and calls {@link PersistAtomsStorage#clearAtoms()}. */
clearAtomsStorage()316     public void clearAtomsStorage() {
317         concludeAll();
318         mStorage.clearAtoms();
319     }
320 
321     /**
322      * Registers a {@link DataCallSessionStats} which will be pinged for on-going data calls when
323      * data call atoms are pulled.
324      */
registerOngoingDataCallStat(DataCallSessionStats call)325     public void registerOngoingDataCallStat(DataCallSessionStats call) {
326         mOngoingDataCallStats.add(call);
327     }
328 
329     /** Unregisters a {@link DataCallSessionStats} when it no longer handles an active data call. */
unregisterOngoingDataCallStat(DataCallSessionStats call)330     public void unregisterOngoingDataCallStat(DataCallSessionStats call) {
331         mOngoingDataCallStats.remove(call);
332     }
333 
concludeDataCallSessionStats()334     private void concludeDataCallSessionStats() {
335         for (DataCallSessionStats stats : mOngoingDataCallStats) {
336             stats.conclude();
337         }
338     }
339 
concludeImsStats()340     private void concludeImsStats() {
341         for (Phone phone : getPhonesIfAny()) {
342             ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
343             if (imsPhone != null) {
344                 imsPhone.getImsStats().conclude();
345             }
346         }
347     }
348 
concludeServiceStateStats()349     private void concludeServiceStateStats() {
350         for (Phone phone : getPhonesIfAny()) {
351             phone.getServiceStateTracker().getServiceStateStats().conclude();
352         }
353     }
354 
concludeRcsStats()355     private void concludeRcsStats() {
356         RcsStats rcsStats = RcsStats.getInstance();
357         if (rcsStats != null) {
358             rcsStats.concludeSipTransportFeatureTagsStat();
359             rcsStats.onFlushIncompleteRcsAcsProvisioningStats();
360             rcsStats.onFlushIncompleteImsRegistrationServiceDescStats();
361             rcsStats.onFlushIncompleteImsRegistrationFeatureTagStats();
362         }
363     }
364 
concludeAll()365     private void concludeAll() {
366         concludeDataCallSessionStats();
367         concludeImsStats();
368         concludeServiceStateStats();
369         concludeRcsStats();
370     }
371 
pullSimSlotState(List<StatsEvent> data)372     private static int pullSimSlotState(List<StatsEvent> data) {
373         SimSlotState state;
374         try {
375             state = SimSlotState.getCurrentState();
376         } catch (RuntimeException e) {
377             // UiccController has not been made yet
378             return StatsManager.PULL_SKIP;
379         }
380 
381         data.add(
382                 TelephonyStatsLog.buildStatsEvent(
383                         SIM_SLOT_STATE,
384                         state.numActiveSlots,
385                         state.numActiveSims,
386                         state.numActiveEsims));
387         return StatsManager.PULL_SUCCESS;
388     }
389 
pullSupportedRadioAccessFamily(List<StatsEvent> data)390     private static int pullSupportedRadioAccessFamily(List<StatsEvent> data) {
391         Phone[] phones = getPhonesIfAny();
392         if (phones.length == 0) {
393             return StatsManager.PULL_SKIP;
394         }
395 
396         // The bitmask is defined in android.telephony.TelephonyManager.NetworkTypeBitMask
397         long rafSupported = 0L;
398         for (Phone phone : PhoneFactory.getPhones()) {
399             rafSupported |= phone.getRadioAccessFamily();
400         }
401 
402         data.add(TelephonyStatsLog.buildStatsEvent(SUPPORTED_RADIO_ACCESS_FAMILY, rafSupported));
403         return StatsManager.PULL_SUCCESS;
404     }
405 
pullCarrierIdTableVersion(List<StatsEvent> data)406     private static int pullCarrierIdTableVersion(List<StatsEvent> data) {
407         Phone[] phones = getPhonesIfAny();
408         if (phones.length == 0) {
409             return StatsManager.PULL_SKIP;
410         } else {
411             // All phones should have the same version of the carrier ID table, so only query the
412             // first one.
413             int version = phones[0].getCarrierIdListVersion();
414             data.add(TelephonyStatsLog.buildStatsEvent(CARRIER_ID_TABLE_VERSION, version));
415             return StatsManager.PULL_SUCCESS;
416         }
417     }
418 
pullVoiceCallRatUsages(List<StatsEvent> data)419     private int pullVoiceCallRatUsages(List<StatsEvent> data) {
420         VoiceCallRatUsage[] usages = mStorage.getVoiceCallRatUsages(MIN_COOLDOWN_MILLIS);
421         if (usages != null) {
422             // sort by carrier/RAT and remove buckets with insufficient number of calls
423             Arrays.stream(usages)
424                     .sorted(
425                             Comparator.comparingLong(
426                                     usage -> ((long) usage.carrierId << 32) | usage.rat))
427                     .filter(usage -> usage.callCount >= MIN_CALLS_PER_BUCKET)
428                     .forEach(usage -> data.add(buildStatsEvent(usage)));
429             Rlog.d(
430                     TAG,
431                     String.format(
432                             "%d out of %d VOICE_CALL_RAT_USAGE pulled",
433                             data.size(), usages.length));
434             return StatsManager.PULL_SUCCESS;
435         } else {
436             Rlog.w(TAG, "VOICE_CALL_RAT_USAGE pull too frequent, skipping");
437             return StatsManager.PULL_SKIP;
438         }
439     }
440 
pullVoiceCallSessions(List<StatsEvent> data)441     private int pullVoiceCallSessions(List<StatsEvent> data) {
442         VoiceCallSession[] calls = mStorage.getVoiceCallSessions(MIN_COOLDOWN_MILLIS);
443         if (calls != null) {
444             // call session list is already shuffled when calls were inserted
445             Arrays.stream(calls).forEach(call -> data.add(buildStatsEvent(call)));
446             return StatsManager.PULL_SUCCESS;
447         } else {
448             Rlog.w(TAG, "VOICE_CALL_SESSION pull too frequent, skipping");
449             return StatsManager.PULL_SKIP;
450         }
451     }
452 
pullIncomingSms(List<StatsEvent> data)453     private int pullIncomingSms(List<StatsEvent> data) {
454         IncomingSms[] smsList = mStorage.getIncomingSms(MIN_COOLDOWN_MILLIS);
455         if (smsList != null) {
456             // SMS list is already shuffled when SMS were inserted
457             Arrays.stream(smsList).forEach(sms -> data.add(buildStatsEvent(sms)));
458             return StatsManager.PULL_SUCCESS;
459         } else {
460             Rlog.w(TAG, "INCOMING_SMS pull too frequent, skipping");
461             return StatsManager.PULL_SKIP;
462         }
463     }
464 
pullOutgoingSms(List<StatsEvent> data)465     private int pullOutgoingSms(List<StatsEvent> data) {
466         OutgoingSms[] smsList = mStorage.getOutgoingSms(MIN_COOLDOWN_MILLIS);
467         if (smsList != null) {
468             // SMS list is already shuffled when SMS were inserted
469             Arrays.stream(smsList).forEach(sms -> data.add(buildStatsEvent(sms)));
470             return StatsManager.PULL_SUCCESS;
471         } else {
472             Rlog.w(TAG, "OUTGOING_SMS pull too frequent, skipping");
473             return StatsManager.PULL_SKIP;
474         }
475     }
476 
pullDataCallSession(List<StatsEvent> data)477     private int pullDataCallSession(List<StatsEvent> data) {
478         // Include ongoing data call segments
479         concludeDataCallSessionStats();
480         DataCallSession[] dataCallSessions = mStorage.getDataCallSessions(MIN_COOLDOWN_MILLIS);
481         if (dataCallSessions != null) {
482             Arrays.stream(dataCallSessions)
483                     .forEach(dataCall -> data.add(buildStatsEvent(dataCall)));
484             return StatsManager.PULL_SUCCESS;
485         } else {
486             Rlog.w(TAG, "DATA_CALL_SESSION pull too frequent, skipping");
487             return StatsManager.PULL_SKIP;
488         }
489     }
490 
pullCellularDataServiceSwitch(List<StatsEvent> data)491     private int pullCellularDataServiceSwitch(List<StatsEvent> data) {
492         CellularDataServiceSwitch[] persistAtoms =
493                 mStorage.getCellularDataServiceSwitches(MIN_COOLDOWN_MILLIS);
494         if (persistAtoms != null) {
495             // list is already shuffled when instances were inserted
496             Arrays.stream(persistAtoms)
497                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
498             return StatsManager.PULL_SUCCESS;
499         } else {
500             Rlog.w(TAG, "CELLULAR_DATA_SERVICE_SWITCH pull too frequent, skipping");
501             return StatsManager.PULL_SKIP;
502         }
503     }
504 
pullCellularServiceState(List<StatsEvent> data)505     private int pullCellularServiceState(List<StatsEvent> data) {
506         // Include the latest durations
507         concludeServiceStateStats();
508         CellularServiceState[] persistAtoms =
509                 mStorage.getCellularServiceStates(MIN_COOLDOWN_MILLIS);
510         if (persistAtoms != null) {
511             // list is already shuffled when instances were inserted
512             Arrays.stream(persistAtoms)
513                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
514             return StatsManager.PULL_SUCCESS;
515         } else {
516             Rlog.w(TAG, "CELLULAR_SERVICE_STATE pull too frequent, skipping");
517             return StatsManager.PULL_SKIP;
518         }
519     }
520 
pullImsRegistrationStats(List<StatsEvent> data)521     private int pullImsRegistrationStats(List<StatsEvent> data) {
522         // Include the latest durations
523         concludeImsStats();
524         ImsRegistrationStats[] persistAtoms = mStorage.getImsRegistrationStats(MIN_COOLDOWN_MILLIS);
525         if (persistAtoms != null) {
526             // list is already shuffled when instances were inserted
527             Arrays.stream(persistAtoms)
528                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
529             return StatsManager.PULL_SUCCESS;
530         } else {
531             Rlog.w(TAG, "IMS_REGISTRATION_STATS pull too frequent, skipping");
532             return StatsManager.PULL_SKIP;
533         }
534     }
535 
pullImsRegistrationTermination(List<StatsEvent> data)536     private int pullImsRegistrationTermination(List<StatsEvent> data) {
537         ImsRegistrationTermination[] persistAtoms =
538                 mStorage.getImsRegistrationTerminations(MIN_COOLDOWN_MILLIS);
539         if (persistAtoms != null) {
540             // list is already shuffled when instances were inserted
541             Arrays.stream(persistAtoms)
542                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
543             return StatsManager.PULL_SUCCESS;
544         } else {
545             Rlog.w(TAG, "IMS_REGISTRATION_TERMINATION pull too frequent, skipping");
546             return StatsManager.PULL_SKIP;
547         }
548     }
549 
pullTelephonyNetworkRequestsV2(List<StatsEvent> data)550     private int pullTelephonyNetworkRequestsV2(List<StatsEvent> data) {
551         NetworkRequestsV2[] persistAtoms = mStorage.getNetworkRequestsV2(MIN_COOLDOWN_MILLIS);
552         if (persistAtoms != null) {
553             Arrays.stream(persistAtoms)
554                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
555             return StatsManager.PULL_SUCCESS;
556         } else {
557             Rlog.w(TAG, "TELEPHONY_NETWORK_REQUESTS_V2 pull too frequent, skipping");
558             return StatsManager.PULL_SKIP;
559         }
560     }
561 
pullDeviceTelephonyProperties(List<StatsEvent> data)562     private int pullDeviceTelephonyProperties(List<StatsEvent> data) {
563         Phone[] phones = getPhonesIfAny();
564         if (phones.length == 0) {
565             return StatsManager.PULL_SKIP;
566         }
567         boolean isAutoDataSwitchOn = Arrays.stream(phones)
568                 .anyMatch(phone ->
569                         phone.getSubId() != SubscriptionManager.getDefaultDataSubscriptionId()
570                                 && phone.getDataSettingsManager().isMobileDataPolicyEnabled(
571                         TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH));
572         boolean hasDedicatedManagedProfileSub = Arrays.stream(phones)
573                 .anyMatch(Phone::isManagedProfile);
574 
575         data.add(TelephonyStatsLog.buildStatsEvent(DEVICE_TELEPHONY_PROPERTIES, true,
576                 isAutoDataSwitchOn, mStorage.getAutoDataSwitchToggleCount(),
577                 hasDedicatedManagedProfileSub));
578         return StatsManager.PULL_SUCCESS;
579     }
580 
pullImsRegistrationFeatureTagStats(List<StatsEvent> data)581     private int pullImsRegistrationFeatureTagStats(List<StatsEvent> data) {
582         RcsStats.getInstance().onFlushIncompleteImsRegistrationFeatureTagStats();
583 
584         ImsRegistrationFeatureTagStats[] persistAtoms =
585                 mStorage.getImsRegistrationFeatureTagStats(MIN_COOLDOWN_MILLIS);
586         if (persistAtoms != null) {
587             Arrays.stream(persistAtoms)
588                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
589             return StatsManager.PULL_SUCCESS;
590         } else {
591             Rlog.w(TAG, "IMS_REGISTRATION_FEATURE_TAG_STATS pull too frequent, skipping");
592             return StatsManager.PULL_SKIP;
593         }
594     }
595 
pullRcsClientProvisioningStats(List<StatsEvent> data)596     private int pullRcsClientProvisioningStats(List<StatsEvent> data) {
597         RcsClientProvisioningStats[] persistAtoms =
598                 mStorage.getRcsClientProvisioningStats(MIN_COOLDOWN_MILLIS);
599         if (persistAtoms != null) {
600             Arrays.stream(persistAtoms)
601                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
602             return StatsManager.PULL_SUCCESS;
603         } else {
604             Rlog.w(TAG, "RCS_CLIENT_PROVISIONING_STATS pull too frequent, skipping");
605             return StatsManager.PULL_SKIP;
606         }
607     }
608 
pullRcsAcsProvisioningStats(List<StatsEvent> data)609     private int pullRcsAcsProvisioningStats(List<StatsEvent> data) {
610         RcsStats.getInstance().onFlushIncompleteRcsAcsProvisioningStats();
611 
612         RcsAcsProvisioningStats[] persistAtoms =
613                 mStorage.getRcsAcsProvisioningStats(MIN_COOLDOWN_MILLIS);
614         if (persistAtoms != null) {
615             Arrays.stream(persistAtoms)
616                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
617             return StatsManager.PULL_SUCCESS;
618         } else {
619             Rlog.w(TAG, "RCS_ACS_PROVISIONING_STATS pull too frequent, skipping");
620             return StatsManager.PULL_SKIP;
621         }
622     }
623 
pullSipDelegateStats(List<StatsEvent> data)624     private int pullSipDelegateStats(List<StatsEvent> data) {
625         SipDelegateStats[] persisAtoms =
626                 mStorage.getSipDelegateStats(MIN_COOLDOWN_MILLIS);
627         if (persisAtoms != null) {
628             Arrays.stream(persisAtoms)
629                     .forEach(persisAtom -> data.add(buildStatsEvent(persisAtom)));
630             return StatsManager.PULL_SUCCESS;
631         } else {
632             Rlog.w(TAG, "SIP_DELEGATE_STATS pull too frequent, skipping");
633             return StatsManager.PULL_SKIP;
634         }
635     }
636 
pullSipTransportFeatureTagStats(List<StatsEvent> data)637     private int pullSipTransportFeatureTagStats(List<StatsEvent> data) {
638         RcsStats.getInstance().concludeSipTransportFeatureTagsStat();
639 
640         SipTransportFeatureTagStats[] persisAtoms =
641                 mStorage.getSipTransportFeatureTagStats(MIN_COOLDOWN_MILLIS);
642         if (persisAtoms != null) {
643             Arrays.stream(persisAtoms)
644                     .forEach(persisAtom -> data.add(buildStatsEvent(persisAtom)));
645             return StatsManager.PULL_SUCCESS;
646         } else {
647             Rlog.w(TAG, "SIP_DELEGATE_STATS pull too frequent, skipping");
648             return StatsManager.PULL_SKIP;
649         }
650     }
651 
pullSipMessageResponse(List<StatsEvent> data)652     private int pullSipMessageResponse(List<StatsEvent> data) {
653         SipMessageResponse[] persistAtoms =
654                 mStorage.getSipMessageResponse(MIN_COOLDOWN_MILLIS);
655         if (persistAtoms != null) {
656             Arrays.stream(persistAtoms)
657                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
658             return StatsManager.PULL_SUCCESS;
659         } else {
660             Rlog.w(TAG, "RCS_SIP_MESSAGE_RESPONSE pull too frequent, skipping");
661             return StatsManager.PULL_SKIP;
662         }
663     }
664 
pullSipTransportSession(List<StatsEvent> data)665     private int pullSipTransportSession(List<StatsEvent> data) {
666         SipTransportSession[] persistAtoms =
667                 mStorage.getSipTransportSession(MIN_COOLDOWN_MILLIS);
668         if (persistAtoms != null) {
669             Arrays.stream(persistAtoms)
670                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
671             return StatsManager.PULL_SUCCESS;
672         } else {
673             Rlog.w(TAG, "RCS_SIP_TRANSPORT_SESSION pull too frequent, skipping");
674             return StatsManager.PULL_SKIP;
675         }
676     }
677 
pullImsDedicatedBearerListenerEvent(List<StatsEvent> data)678     private int pullImsDedicatedBearerListenerEvent(List<StatsEvent> data) {
679         ImsDedicatedBearerListenerEvent[] persistAtoms =
680             mStorage.getImsDedicatedBearerListenerEvent(MIN_COOLDOWN_MILLIS);
681         if (persistAtoms != null) {
682             Arrays.stream(persistAtoms)
683                 .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
684             return StatsManager.PULL_SUCCESS;
685         } else {
686             Rlog.w(TAG, "IMS_DEDICATED_BEARER_LISTENER_EVENT pull too frequent, skipping");
687             return StatsManager.PULL_SKIP;
688         }
689     }
690 
pullImsDedicatedBearerEvent(List<StatsEvent> data)691     private int pullImsDedicatedBearerEvent(List<StatsEvent> data) {
692         ImsDedicatedBearerEvent[] persistAtoms =
693             mStorage.getImsDedicatedBearerEvent(MIN_COOLDOWN_MILLIS);
694         if (persistAtoms != null) {
695             Arrays.stream(persistAtoms)
696                 .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
697             return StatsManager.PULL_SUCCESS;
698         } else {
699             Rlog.w(TAG, "IMS_DEDICATED_BEARER_EVENT pull too frequent, skipping");
700             return StatsManager.PULL_SKIP;
701         }
702     }
703 
pullImsRegistrationServiceDescStats(List<StatsEvent> data)704     private int pullImsRegistrationServiceDescStats(List<StatsEvent> data) {
705         RcsStats.getInstance().onFlushIncompleteImsRegistrationServiceDescStats();
706         ImsRegistrationServiceDescStats[] persistAtoms =
707             mStorage.getImsRegistrationServiceDescStats(MIN_COOLDOWN_MILLIS);
708         if (persistAtoms != null) {
709             Arrays.stream(persistAtoms)
710                 .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
711             return StatsManager.PULL_SUCCESS;
712         } else {
713             Rlog.w(TAG, "IMS_REGISTRATION_SERVICE_DESC_STATS pull too frequent, skipping");
714             return StatsManager.PULL_SKIP;
715         }
716     }
717 
pullUceEventStats(List<StatsEvent> data)718     private int pullUceEventStats(List<StatsEvent> data) {
719         UceEventStats[] persistAtoms = mStorage.getUceEventStats(MIN_COOLDOWN_MILLIS);
720         if (persistAtoms != null) {
721             Arrays.stream(persistAtoms)
722                 .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
723             return StatsManager.PULL_SUCCESS;
724         } else {
725             Rlog.w(TAG, "UCE_EVENT_STATS pull too frequent, skipping");
726             return StatsManager.PULL_SKIP;
727         }
728     }
729 
pullPresenceNotifyEvent(List<StatsEvent> data)730     private int pullPresenceNotifyEvent(List<StatsEvent> data) {
731         PresenceNotifyEvent[] persistAtoms = mStorage.getPresenceNotifyEvent(MIN_COOLDOWN_MILLIS);
732         if (persistAtoms != null) {
733             Arrays.stream(persistAtoms)
734                 .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
735             return StatsManager.PULL_SUCCESS;
736         } else {
737             Rlog.w(TAG, "PRESENCE_NOTIFY_EVENT pull too frequent, skipping");
738             return StatsManager.PULL_SKIP;
739         }
740     }
741 
pullGbaEvent(List<StatsEvent> data)742     private int pullGbaEvent(List<StatsEvent> data) {
743         GbaEvent[] persistAtoms = mStorage.getGbaEvent(MIN_COOLDOWN_MILLIS);
744         if (persistAtoms != null) {
745             Arrays.stream(persistAtoms)
746                 .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
747             return StatsManager.PULL_SUCCESS;
748         } else {
749             Rlog.w(TAG, "GBA_EVENT pull too frequent, skipping");
750             return StatsManager.PULL_SKIP;
751         }
752     }
753 
pullPerSimStatus(List<StatsEvent> data)754     private int pullPerSimStatus(List<StatsEvent> data) {
755         int result = StatsManager.PULL_SKIP;
756         for (Phone phone : getPhonesIfAny()) {
757             PerSimStatus perSimStatus = PerSimStatus.getCurrentState(phone);
758             if (perSimStatus == null) {
759                 continue;
760             }
761             StatsEvent statsEvent = TelephonyStatsLog.buildStatsEvent(
762                     PER_SIM_STATUS,
763                     phone.getPhoneId(), // simSlotIndex
764                     perSimStatus.carrierId, // carrierId
765                     perSimStatus.phoneNumberSourceUicc, // phoneNumberSourceUicc
766                     perSimStatus.phoneNumberSourceCarrier, // phoneNumberSourceCarrier
767                     perSimStatus.phoneNumberSourceIms, // phoneNumberSourceIms
768                     perSimStatus.advancedCallingSettingEnabled, // volteEnabled
769                     perSimStatus.voWiFiSettingEnabled, // wfcEnabled
770                     perSimStatus.voWiFiModeSetting, // wfcMode
771                     perSimStatus.voWiFiRoamingModeSetting, // wfcRoamingMode
772                     perSimStatus.vtSettingEnabled, // videoCallingEnabled
773                     perSimStatus.dataRoamingEnabled, // dataRoamingEnabled
774                     perSimStatus.preferredNetworkType, // allowedNetworksByUser
775                     perSimStatus.disabled2g, // is2gDisabled
776                     perSimStatus.pin1Enabled, // isPin1Enabled
777                     perSimStatus.minimumVoltageClass, // simVoltageClass
778                     perSimStatus.userModifiedApnTypes, // userModifiedApnTypeBitmask
779                     perSimStatus.unmeteredNetworks, // unmeteredNetworks
780                     perSimStatus.vonrEnabled); // vonrEnabled
781             data.add(statsEvent);
782             result = StatsManager.PULL_SUCCESS;
783         }
784         return result;
785     }
786 
pullOutgoingShortCodeSms(List<StatsEvent> data)787     private int pullOutgoingShortCodeSms(List<StatsEvent> data) {
788         OutgoingShortCodeSms[] outgoingShortCodeSmsList = mStorage
789                 .getOutgoingShortCodeSms(MIN_COOLDOWN_MILLIS);
790         if (outgoingShortCodeSmsList != null) {
791             // Outgoing short code SMS list is already shuffled when SMS were inserted
792             Arrays.stream(outgoingShortCodeSmsList).forEach(sms -> data.add(buildStatsEvent(sms)));
793             return StatsManager.PULL_SUCCESS;
794         } else {
795             Rlog.w(TAG, "OUTGOING_SHORT_CODE_SMS pull too frequent, skipping");
796             return StatsManager.PULL_SKIP;
797         }
798     }
799 
pullSatelliteController(List<StatsEvent> data)800     private int pullSatelliteController(List<StatsEvent> data) {
801         SatelliteController[] controllerAtoms =
802                 mStorage.getSatelliteControllerStats(MIN_COOLDOWN_MILLIS);
803         if (controllerAtoms != null) {
804             Arrays.stream(controllerAtoms)
805                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
806             return StatsManager.PULL_SUCCESS;
807         } else {
808             Rlog.w(TAG, "SATELLITE_CONTROLLER pull too frequent, skipping");
809             return StatsManager.PULL_SKIP;
810         }
811     }
812 
pullSatelliteSession(List<StatsEvent> data)813     private int pullSatelliteSession(List<StatsEvent> data) {
814         SatelliteSession[] sessionAtoms =
815                 mStorage.getSatelliteSessionStats(MIN_COOLDOWN_MILLIS);
816         if (sessionAtoms != null) {
817             Arrays.stream(sessionAtoms)
818                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
819             return StatsManager.PULL_SUCCESS;
820         } else {
821             Rlog.w(TAG, "SATELLITE_SESSION pull too frequent, skipping");
822             return StatsManager.PULL_SKIP;
823         }
824     }
825 
pullSatelliteIncomingDatagram(List<StatsEvent> data)826     private int pullSatelliteIncomingDatagram(List<StatsEvent> data) {
827         SatelliteIncomingDatagram[] incomingDatagramAtoms =
828                 mStorage.getSatelliteIncomingDatagramStats(MIN_COOLDOWN_MILLIS);
829         if (incomingDatagramAtoms != null) {
830             Arrays.stream(incomingDatagramAtoms)
831                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
832             return StatsManager.PULL_SUCCESS;
833         } else {
834             Rlog.w(TAG, "SATELLITE_INCOMING_DATAGRAM pull too frequent, skipping");
835             return StatsManager.PULL_SKIP;
836         }
837     }
838 
839 
pullSatelliteOutgoingDatagram(List<StatsEvent> data)840     private int pullSatelliteOutgoingDatagram(List<StatsEvent> data) {
841         SatelliteOutgoingDatagram[] outgoingDatagramAtoms =
842                 mStorage.getSatelliteOutgoingDatagramStats(MIN_COOLDOWN_MILLIS);
843         if (outgoingDatagramAtoms != null) {
844             Arrays.stream(outgoingDatagramAtoms)
845                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
846             return StatsManager.PULL_SUCCESS;
847         } else {
848             Rlog.w(TAG, "SATELLITE_OUTGOING_DATAGRAM pull too frequent, skipping");
849             return StatsManager.PULL_SKIP;
850         }
851     }
852 
853 
pullSatelliteProvision(List<StatsEvent> data)854     private int pullSatelliteProvision(List<StatsEvent> data) {
855         SatelliteProvision[] provisionAtoms =
856                 mStorage.getSatelliteProvisionStats(MIN_COOLDOWN_MILLIS);
857         if (provisionAtoms != null) {
858             Arrays.stream(provisionAtoms)
859                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
860             return StatsManager.PULL_SUCCESS;
861         } else {
862             Rlog.w(TAG, "SATELLITE_PROVISION pull too frequent, skipping");
863             return StatsManager.PULL_SKIP;
864         }
865     }
866 
pullSatelliteSosMessageRecommender(List<StatsEvent> data)867     private int pullSatelliteSosMessageRecommender(List<StatsEvent> data) {
868         SatelliteSosMessageRecommender[] sosMessageRecommenderAtoms =
869                 mStorage.getSatelliteSosMessageRecommenderStats(MIN_COOLDOWN_MILLIS);
870         if (sosMessageRecommenderAtoms != null) {
871             Arrays.stream(sosMessageRecommenderAtoms)
872                     .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
873             return StatsManager.PULL_SUCCESS;
874         } else {
875             Rlog.w(TAG, "SATELLITE_SOS_MESSAGE_RECOMMENDER pull too frequent, skipping");
876             return StatsManager.PULL_SKIP;
877         }
878     }
879 
pullEmergencyNumbersInfo(List<StatsEvent> data)880     private int pullEmergencyNumbersInfo(List<StatsEvent> data) {
881         boolean isDataLogged = false;
882         for (Phone phone : getPhonesIfAny()) {
883             if (phone != null) {
884                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
885                 if (tracker != null) {
886                     EmergencyNumbersInfo[] numList = tracker.getEmergencyNumbersProtoArray();
887                     Arrays.stream(numList).forEach(number -> data.add(buildStatsEvent(number)));
888                     isDataLogged = true;
889                 }
890             }
891         }
892         return isDataLogged ? StatsManager.PULL_SUCCESS : StatsManager.PULL_SKIP;
893     }
894 
895     /** Registers a pulled atom ID {@code atomId}. */
registerAtom(int atomId)896     private void registerAtom(int atomId) {
897         mStatsManager.setPullAtomCallback(atomId, /* metadata= */ null,
898                 ConcurrentUtils.DIRECT_EXECUTOR, this);
899     }
900 
buildStatsEvent(CellularDataServiceSwitch serviceSwitch)901     private static StatsEvent buildStatsEvent(CellularDataServiceSwitch serviceSwitch) {
902         return TelephonyStatsLog.buildStatsEvent(
903                 CELLULAR_DATA_SERVICE_SWITCH,
904                 serviceSwitch.ratFrom,
905                 serviceSwitch.ratTo,
906                 serviceSwitch.simSlotIndex,
907                 serviceSwitch.isMultiSim,
908                 serviceSwitch.carrierId,
909                 serviceSwitch.switchCount);
910     }
911 
buildStatsEvent(CellularServiceState state)912     private static StatsEvent buildStatsEvent(CellularServiceState state) {
913         return TelephonyStatsLog.buildStatsEvent(
914                 CELLULAR_SERVICE_STATE,
915                 state.voiceRat,
916                 state.dataRat,
917                 state.voiceRoamingType,
918                 state.dataRoamingType,
919                 state.isEndc,
920                 state.simSlotIndex,
921                 state.isMultiSim,
922                 state.carrierId,
923                 roundAndConvertMillisToSeconds(state.totalTimeMillis),
924                 state.isEmergencyOnly,
925                 state.isInternetPdnUp,
926                 state.foldState,
927                 state.overrideVoiceService,
928                 state.isDataEnabled);
929     }
930 
buildStatsEvent(VoiceCallRatUsage usage)931     private static StatsEvent buildStatsEvent(VoiceCallRatUsage usage) {
932         return TelephonyStatsLog.buildStatsEvent(
933                 VOICE_CALL_RAT_USAGE,
934                 usage.carrierId,
935                 usage.rat,
936                 roundAndConvertMillisToSeconds(usage.totalDurationMillis),
937                 usage.callCount);
938     }
939 
buildStatsEvent(VoiceCallSession session)940     private static StatsEvent buildStatsEvent(VoiceCallSession session) {
941         return TelephonyStatsLog.buildStatsEvent(
942                 VOICE_CALL_SESSION,
943                 session.bearerAtStart,
944                 session.bearerAtEnd,
945                 session.direction,
946                 // deprecated and replaced by setupDurationMillis
947                 VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN,
948                 session.setupFailed,
949                 session.disconnectReasonCode,
950                 session.disconnectExtraCode,
951                 session.disconnectExtraMessage,
952                 session.ratAtStart,
953                 session.ratAtEnd,
954                 session.ratSwitchCount,
955                 session.codecBitmask,
956                 session.concurrentCallCountAtStart,
957                 session.concurrentCallCountAtEnd,
958                 session.simSlotIndex,
959                 session.isMultiSim,
960                 session.isEsim,
961                 session.carrierId,
962                 session.srvccCompleted,
963                 session.srvccFailureCount,
964                 session.srvccCancellationCount,
965                 session.rttEnabled,
966                 session.isEmergency,
967                 session.isRoaming,
968                 // workaround: dimension required for keeping multiple pulled atoms
969                 sRandom.nextInt(),
970                 // New fields introduced in Android S
971                 session.signalStrengthAtEnd,
972                 session.bandAtEnd,
973                 session.setupDurationMillis,
974                 session.mainCodecQuality,
975                 session.videoEnabled,
976                 session.ratAtConnected,
977                 session.isMultiparty,
978                 session.callDuration,
979                 session.lastKnownRat,
980                 session.foldState,
981                 session.ratSwitchCountAfterConnected,
982                 session.handoverInProgress);
983     }
984 
buildStatsEvent(IncomingSms sms)985     private static StatsEvent buildStatsEvent(IncomingSms sms) {
986         return TelephonyStatsLog.buildStatsEvent(
987                 INCOMING_SMS,
988                 sms.smsFormat,
989                 sms.smsTech,
990                 sms.rat,
991                 sms.smsType,
992                 sms.totalParts,
993                 sms.receivedParts,
994                 sms.blocked,
995                 sms.error,
996                 sms.isRoaming,
997                 sms.simSlotIndex,
998                 sms.isMultiSim,
999                 sms.isEsim,
1000                 sms.carrierId,
1001                 sms.messageId,
1002                 sms.count,
1003                 sms.isManagedProfile);
1004     }
1005 
buildStatsEvent(OutgoingSms sms)1006     private static StatsEvent buildStatsEvent(OutgoingSms sms) {
1007         return TelephonyStatsLog.buildStatsEvent(
1008                 OUTGOING_SMS,
1009                 sms.smsFormat,
1010                 sms.smsTech,
1011                 sms.rat,
1012                 sms.sendResult,
1013                 sms.errorCode,
1014                 sms.isRoaming,
1015                 sms.isFromDefaultApp,
1016                 sms.simSlotIndex,
1017                 sms.isMultiSim,
1018                 sms.isEsim,
1019                 sms.carrierId,
1020                 sms.messageId,
1021                 sms.retryId,
1022                 sms.intervalMillis,
1023                 sms.count,
1024                 sms.sendErrorCode,
1025                 sms.networkErrorCode,
1026                 sms.isManagedProfile);
1027     }
1028 
buildStatsEvent(DataCallSession dataCallSession)1029     private static StatsEvent buildStatsEvent(DataCallSession dataCallSession) {
1030         return TelephonyStatsLog.buildStatsEvent(
1031                 DATA_CALL_SESSION,
1032                 dataCallSession.dimension,
1033                 dataCallSession.isMultiSim,
1034                 dataCallSession.isEsim,
1035                 0, // profile is deprecated, so we default to 0
1036                 dataCallSession.apnTypeBitmask,
1037                 dataCallSession.carrierId,
1038                 dataCallSession.isRoaming,
1039                 dataCallSession.ratAtEnd,
1040                 dataCallSession.oosAtEnd,
1041                 dataCallSession.ratSwitchCount,
1042                 dataCallSession.isOpportunistic,
1043                 dataCallSession.ipType,
1044                 dataCallSession.setupFailed,
1045                 dataCallSession.failureCause,
1046                 dataCallSession.suggestedRetryMillis,
1047                 dataCallSession.deactivateReason,
1048                 roundAndConvertMillisToMinutes(
1049                         dataCallSession.durationMinutes * MILLIS_PER_MINUTE),
1050                 dataCallSession.ongoing,
1051                 dataCallSession.bandAtEnd,
1052                 dataCallSession.handoverFailureCauses,
1053                 dataCallSession.handoverFailureRat,
1054                 dataCallSession.isNonDds);
1055     }
1056 
buildStatsEvent(ImsRegistrationStats stats)1057     private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) {
1058         return TelephonyStatsLog.buildStatsEvent(
1059                 IMS_REGISTRATION_STATS,
1060                 stats.carrierId,
1061                 stats.simSlotIndex,
1062                 stats.rat,
1063                 roundAndConvertMillisToSeconds(stats.registeredMillis),
1064                 roundAndConvertMillisToSeconds(stats.voiceCapableMillis),
1065                 roundAndConvertMillisToSeconds(stats.voiceAvailableMillis),
1066                 roundAndConvertMillisToSeconds(stats.smsCapableMillis),
1067                 roundAndConvertMillisToSeconds(stats.smsAvailableMillis),
1068                 roundAndConvertMillisToSeconds(stats.videoCapableMillis),
1069                 roundAndConvertMillisToSeconds(stats.videoAvailableMillis),
1070                 roundAndConvertMillisToSeconds(stats.utCapableMillis),
1071                 roundAndConvertMillisToSeconds(stats.utAvailableMillis));
1072     }
1073 
buildStatsEvent(ImsRegistrationTermination termination)1074     private static StatsEvent buildStatsEvent(ImsRegistrationTermination termination) {
1075         return TelephonyStatsLog.buildStatsEvent(
1076                 IMS_REGISTRATION_TERMINATION,
1077                 termination.carrierId,
1078                 termination.isMultiSim,
1079                 termination.ratAtEnd,
1080                 termination.setupFailed,
1081                 termination.reasonCode,
1082                 termination.extraCode,
1083                 termination.extraMessage,
1084                 termination.count);
1085     }
1086 
buildStatsEvent(NetworkRequestsV2 networkRequests)1087     private static StatsEvent buildStatsEvent(NetworkRequestsV2 networkRequests) {
1088         return TelephonyStatsLog.buildStatsEvent(
1089                 TELEPHONY_NETWORK_REQUESTS_V2,
1090                 networkRequests.carrierId,
1091                 networkRequests.capability,
1092                 networkRequests.requestCount);
1093     }
1094 
buildStatsEvent(ImsRegistrationFeatureTagStats stats)1095     private static StatsEvent buildStatsEvent(ImsRegistrationFeatureTagStats stats) {
1096         return TelephonyStatsLog.buildStatsEvent(
1097                 IMS_REGISTRATION_FEATURE_TAG_STATS,
1098                 stats.carrierId,
1099                 stats.slotId,
1100                 stats.featureTagName,
1101                 stats.registrationTech,
1102                 roundAndConvertMillisToSeconds(stats.registeredMillis));
1103     }
1104 
buildStatsEvent(RcsClientProvisioningStats stats)1105     private static StatsEvent buildStatsEvent(RcsClientProvisioningStats stats) {
1106         return TelephonyStatsLog.buildStatsEvent(
1107                 RCS_CLIENT_PROVISIONING_STATS,
1108                 stats.carrierId,
1109                 stats.slotId,
1110                 stats.event,
1111                 stats.count);
1112     }
1113 
buildStatsEvent(RcsAcsProvisioningStats stats)1114     private static StatsEvent buildStatsEvent(RcsAcsProvisioningStats stats) {
1115         return TelephonyStatsLog.buildStatsEvent(
1116                 RCS_ACS_PROVISIONING_STATS,
1117                 stats.carrierId,
1118                 stats.slotId,
1119                 stats.responseCode,
1120                 stats.responseType,
1121                 stats.isSingleRegistrationEnabled,
1122                 stats.count,
1123                 roundAndConvertMillisToSeconds(stats.stateTimerMillis));
1124     }
1125 
buildStatsEvent(SipDelegateStats stats)1126     private static StatsEvent buildStatsEvent(SipDelegateStats stats) {
1127         return TelephonyStatsLog.buildStatsEvent(
1128                 SIP_DELEGATE_STATS,
1129                 stats.dimension,
1130                 stats.carrierId,
1131                 stats.slotId,
1132                 roundAndConvertMillisToSeconds(stats.uptimeMillis),
1133                 stats.destroyReason);
1134     }
1135 
buildStatsEvent(SipTransportFeatureTagStats stats)1136     private static StatsEvent buildStatsEvent(SipTransportFeatureTagStats stats) {
1137         return TelephonyStatsLog.buildStatsEvent(
1138                 SIP_TRANSPORT_FEATURE_TAG_STATS,
1139                 stats.carrierId,
1140                 stats.slotId,
1141                 stats.featureTagName,
1142                 stats.sipTransportDeniedReason,
1143                 stats.sipTransportDeregisteredReason,
1144                 roundAndConvertMillisToSeconds(stats.associatedMillis));
1145     }
1146 
buildStatsEvent(SipMessageResponse stats)1147     private static StatsEvent buildStatsEvent(SipMessageResponse stats) {
1148         return TelephonyStatsLog.buildStatsEvent(
1149                 SIP_MESSAGE_RESPONSE,
1150                 stats.carrierId,
1151                 stats.slotId,
1152                 stats.sipMessageMethod,
1153                 stats.sipMessageResponse,
1154                 stats.sipMessageDirection,
1155                 stats.messageError,
1156                 stats.count);
1157     }
1158 
buildStatsEvent(SipTransportSession stats)1159     private static StatsEvent buildStatsEvent(SipTransportSession stats) {
1160         return TelephonyStatsLog.buildStatsEvent(
1161                 SIP_TRANSPORT_SESSION,
1162                 stats.carrierId,
1163                 stats.slotId,
1164                 stats.sessionMethod,
1165                 stats.sipMessageDirection,
1166                 stats.sipResponse,
1167                 stats.sessionCount,
1168                 stats.endedGracefullyCount);
1169     }
1170 
buildStatsEvent(ImsDedicatedBearerListenerEvent stats)1171     private static StatsEvent buildStatsEvent(ImsDedicatedBearerListenerEvent stats) {
1172         return TelephonyStatsLog.buildStatsEvent(
1173                 IMS_DEDICATED_BEARER_LISTENER_EVENT,
1174                 stats.carrierId,
1175                 stats.slotId,
1176                 stats.ratAtEnd,
1177                 stats.qci,
1178                 stats.dedicatedBearerEstablished,
1179                 stats.eventCount);
1180     }
1181 
buildStatsEvent(ImsDedicatedBearerEvent stats)1182     private static StatsEvent buildStatsEvent(ImsDedicatedBearerEvent stats) {
1183         return TelephonyStatsLog.buildStatsEvent(
1184                 IMS_DEDICATED_BEARER_EVENT,
1185                 stats.carrierId,
1186                 stats.slotId,
1187                 stats.ratAtEnd,
1188                 stats.qci,
1189                 stats.bearerState,
1190                 stats.localConnectionInfoReceived,
1191                 stats.remoteConnectionInfoReceived,
1192                 stats.hasListeners,
1193                 stats.count);
1194     }
1195 
buildStatsEvent(ImsRegistrationServiceDescStats stats)1196     private static StatsEvent buildStatsEvent(ImsRegistrationServiceDescStats stats) {
1197         return TelephonyStatsLog.buildStatsEvent(
1198                 IMS_REGISTRATION_SERVICE_DESC_STATS,
1199                 stats.carrierId,
1200                 stats.slotId,
1201                 stats.serviceIdName,
1202                 stats.serviceIdVersion,
1203                 stats.registrationTech,
1204                 roundAndConvertMillisToSeconds(stats.publishedMillis));
1205     }
1206 
buildStatsEvent(UceEventStats stats)1207     private static StatsEvent buildStatsEvent(UceEventStats stats) {
1208         return TelephonyStatsLog.buildStatsEvent(
1209                 UCE_EVENT_STATS,
1210                 stats.carrierId,
1211                 stats.slotId,
1212                 stats.type,
1213                 stats.successful,
1214                 stats.commandCode,
1215                 stats.networkResponse,
1216                 stats.count);
1217     }
1218 
buildStatsEvent(PresenceNotifyEvent stats)1219     private static StatsEvent buildStatsEvent(PresenceNotifyEvent stats) {
1220         return TelephonyStatsLog.buildStatsEvent(
1221                 PRESENCE_NOTIFY_EVENT,
1222                 stats.carrierId,
1223                 stats.slotId,
1224                 stats.reason,
1225                 stats.contentBodyReceived,
1226                 stats.rcsCapsCount,
1227                 stats.mmtelCapsCount,
1228                 stats.noCapsCount,
1229                 stats.count);
1230     }
1231 
buildStatsEvent(GbaEvent stats)1232     private static StatsEvent buildStatsEvent(GbaEvent stats) {
1233         return TelephonyStatsLog.buildStatsEvent(
1234                 GBA_EVENT,
1235                 stats.carrierId,
1236                 stats.slotId,
1237                 stats.successful,
1238                 stats.failedReason,
1239                 stats.count);
1240     }
1241 
buildStatsEvent(OutgoingShortCodeSms shortCodeSms)1242     private static StatsEvent buildStatsEvent(OutgoingShortCodeSms shortCodeSms) {
1243         return TelephonyStatsLog.buildStatsEvent(
1244                 OUTGOING_SHORT_CODE_SMS,
1245                 shortCodeSms.category,
1246                 shortCodeSms.xmlVersion,
1247                 shortCodeSms.shortCodeSmsCount);
1248     }
1249 
buildStatsEvent(SatelliteController satelliteController)1250     private static StatsEvent buildStatsEvent(SatelliteController satelliteController) {
1251         return TelephonyStatsLog.buildStatsEvent(
1252                 SATELLITE_CONTROLLER,
1253                 satelliteController.countOfSatelliteServiceEnablementsSuccess,
1254                 satelliteController.countOfSatelliteServiceEnablementsFail,
1255                 satelliteController.countOfOutgoingDatagramSuccess,
1256                 satelliteController.countOfOutgoingDatagramFail,
1257                 satelliteController.countOfIncomingDatagramSuccess,
1258                 satelliteController.countOfIncomingDatagramFail,
1259                 satelliteController.countOfDatagramTypeSosSmsSuccess,
1260                 satelliteController.countOfDatagramTypeSosSmsFail,
1261                 satelliteController.countOfDatagramTypeLocationSharingSuccess,
1262                 satelliteController.countOfDatagramTypeLocationSharingFail,
1263                 satelliteController.countOfProvisionSuccess,
1264                 satelliteController.countOfProvisionFail,
1265                 satelliteController.countOfDeprovisionSuccess,
1266                 satelliteController.countOfDeprovisionFail,
1267                 satelliteController.totalServiceUptimeSec,
1268                 satelliteController.totalBatteryConsumptionPercent,
1269                 satelliteController.totalBatteryChargedTimeSec);
1270     }
1271 
buildStatsEvent(SatelliteSession satelliteSession)1272     private static StatsEvent buildStatsEvent(SatelliteSession satelliteSession) {
1273         return TelephonyStatsLog.buildStatsEvent(
1274                 SATELLITE_SESSION,
1275                 satelliteSession.satelliteServiceInitializationResult,
1276                 satelliteSession.satelliteTechnology,
1277                 satelliteSession.count);
1278     }
1279 
buildStatsEvent(SatelliteIncomingDatagram stats)1280     private static StatsEvent buildStatsEvent(SatelliteIncomingDatagram stats) {
1281         return TelephonyStatsLog.buildStatsEvent(
1282                 SATELLITE_INCOMING_DATAGRAM,
1283                 stats.resultCode,
1284                 stats.datagramSizeBytes,
1285                 stats.datagramTransferTimeMillis);
1286     }
1287 
buildStatsEvent(SatelliteOutgoingDatagram stats)1288     private static StatsEvent buildStatsEvent(SatelliteOutgoingDatagram stats) {
1289         return TelephonyStatsLog.buildStatsEvent(
1290                 SATELLITE_OUTGOING_DATAGRAM,
1291                 stats.datagramType,
1292                 stats.resultCode,
1293                 stats.datagramSizeBytes,
1294                 stats.datagramTransferTimeMillis);
1295     }
1296 
buildStatsEvent(SatelliteProvision stats)1297     private static StatsEvent buildStatsEvent(SatelliteProvision stats) {
1298         return TelephonyStatsLog.buildStatsEvent(
1299                 SATELLITE_PROVISION,
1300                 stats.resultCode,
1301                 stats.provisioningTimeSec,
1302                 stats.isProvisionRequest,
1303                 stats.isCanceled);
1304     }
1305 
buildStatsEvent(SatelliteSosMessageRecommender stats)1306     private static StatsEvent buildStatsEvent(SatelliteSosMessageRecommender stats) {
1307         return TelephonyStatsLog.buildStatsEvent(
1308                 SATELLITE_SOS_MESSAGE_RECOMMENDER,
1309                 stats.isDisplaySosMessageSent,
1310                 stats.countOfTimerStarted,
1311                 stats.isImsRegistered,
1312                 stats.cellularServiceState,
1313                 stats.count);
1314     }
1315 
buildStatsEvent(EmergencyNumbersInfo emergencyNumber)1316     private static StatsEvent buildStatsEvent(EmergencyNumbersInfo emergencyNumber) {
1317         return TelephonyStatsLog.buildStatsEvent(
1318                 EMERGENCY_NUMBERS_INFO,
1319                 emergencyNumber.isDbVersionIgnored,
1320                 emergencyNumber.assetVersion,
1321                 emergencyNumber.otaVersion,
1322                 emergencyNumber.number,
1323                 emergencyNumber.countryIso,
1324                 emergencyNumber.mnc,
1325                 emergencyNumber.route,
1326                 emergencyNumber.urns,
1327                 emergencyNumber.serviceCategories,
1328                 emergencyNumber.sources);
1329     }
1330 
1331     /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */
getPhonesIfAny()1332     static Phone[] getPhonesIfAny() {
1333         try {
1334             return PhoneFactory.getPhones();
1335         } catch (IllegalStateException e) {
1336             // Phones have not been made yet
1337             return new Phone[0];
1338         }
1339     }
1340 
1341     /**
1342      * Rounds the duration and converts it from milliseconds to seconds.
1343      */
roundAndConvertMillisToSeconds(long valueMillis)1344     private static int roundAndConvertMillisToSeconds(long valueMillis) {
1345         long roundedValueMillis = Math.round((double) valueMillis / DURATION_BUCKET_MILLIS)
1346                 * DURATION_BUCKET_MILLIS;
1347         return (int) (roundedValueMillis / MILLIS_PER_SECOND);
1348     }
1349 
1350     /**
1351      * Rounds the duration and converts it from milliseconds to minutes.
1352      */
roundAndConvertMillisToMinutes(long valueMillis)1353     private static int roundAndConvertMillisToMinutes(long valueMillis) {
1354         long roundedValueMillis = Math.round((double) valueMillis / DURATION_BUCKET_MILLIS)
1355                 * DURATION_BUCKET_MILLIS;
1356         return (int) (roundedValueMillis / MILLIS_PER_MINUTE);
1357     }
1358 }
1359