• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.server.stats.pull;
18 
19 import static android.app.AppOpsManager.OP_FLAG_SELF;
20 import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
21 import static android.app.AppProtoEnums.HOSTING_COMPONENT_TYPE_EMPTY;
22 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
23 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
24 import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_PASSTHROUGH;
25 import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_UNSUPPORTED;
26 import static android.hardware.graphics.common.Hdr.DOLBY_VISION;
27 import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
28 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
29 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
30 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
31 import static android.net.NetworkStats.METERED_YES;
32 import static android.net.NetworkTemplate.MATCH_ETHERNET;
33 import static android.net.NetworkTemplate.MATCH_MOBILE;
34 import static android.net.NetworkTemplate.MATCH_PROXY;
35 import static android.net.NetworkTemplate.MATCH_WIFI;
36 import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
37 import static android.net.NetworkTemplate.OEM_MANAGED_PAID;
38 import static android.net.NetworkTemplate.OEM_MANAGED_PRIVATE;
39 import static android.os.Debug.getIonHeapsSizeKb;
40 import static android.os.Process.INVALID_UID;
41 import static android.os.Process.LAST_SHARED_APPLICATION_GID;
42 import static android.os.Process.SYSTEM_UID;
43 import static android.os.Process.getUidForPid;
44 import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
45 import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
46 import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
47 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
48 import static android.util.MathUtils.constrain;
49 import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID;
50 
51 import static com.android.internal.os.ProcfsMemoryUtil.getProcessCmdlines;
52 import static com.android.internal.os.ProcfsMemoryUtil.readCmdlineFromProcfs;
53 import static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
54 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
55 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__GESTURE_SHORTCUT_TYPE__TRIPLE_TAP;
56 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__HARDWARE_SHORTCUT_TYPE__VOLUME_KEY;
57 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__QS_SHORTCUT_TYPE__QUICK_SETTINGS;
58 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__A11Y_BUTTON;
59 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__A11Y_FLOATING_MENU;
60 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__A11Y_GESTURE;
61 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__UNKNOWN_TYPE;
62 import static com.android.internal.util.FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC;
63 import static com.android.internal.util.FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC;
64 import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_CPU;
65 import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_IO;
66 import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_MEMORY;
67 import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_UNKNOWN;
68 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__GEO;
69 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
70 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY;
71 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN;
72 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
73 import static com.android.server.stats.Flags.accumulateNetworkStatsSinceBoot;
74 import static com.android.server.stats.Flags.addMobileBytesTransferByProcStatePuller;
75 import static com.android.server.stats.Flags.addPressureStallInformationPuller;
76 import static com.android.server.stats.Flags.applyNetworkStatsPollRateLimit;
77 import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
78 import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
79 import static com.android.server.stats.pull.netstats.NetworkStatsUtils.fromPublicNetworkStats;
80 import static com.android.server.stats.pull.netstats.NetworkStatsUtils.isAddEntriesSupported;
81 
82 import static libcore.io.IoUtils.closeQuietly;
83 
84 import static java.lang.Math.min;
85 import static java.util.concurrent.TimeUnit.HOURS;
86 import static java.util.concurrent.TimeUnit.MICROSECONDS;
87 
88 import android.annotation.NonNull;
89 import android.annotation.Nullable;
90 import android.annotation.UserIdInt;
91 import android.app.ActivityManagerInternal;
92 import android.app.AppOpsManager;
93 import android.app.AppOpsManager.HistoricalOp;
94 import android.app.AppOpsManager.HistoricalOps;
95 import android.app.AppOpsManager.HistoricalOpsRequest;
96 import android.app.AppOpsManager.HistoricalPackageOps;
97 import android.app.AppOpsManager.HistoricalUidOps;
98 import android.app.INotificationManager;
99 import android.app.PendingIntentStats;
100 import android.app.ProcessMemoryState;
101 import android.app.RuntimeAppOpAccessMessage;
102 import android.app.StatsManager;
103 import android.app.StatsManager.PullAtomMetadata;
104 import android.app.usage.NetworkStatsManager;
105 import android.bluetooth.BluetoothActivityEnergyInfo;
106 import android.bluetooth.BluetoothAdapter;
107 import android.bluetooth.UidTraffic;
108 import android.content.ContentResolver;
109 import android.content.Context;
110 import android.content.pm.ApplicationInfo;
111 import android.content.pm.IncrementalStatesInfo;
112 import android.content.pm.PackageInfo;
113 import android.content.pm.PackageManager;
114 import android.content.pm.PackageManagerInternal;
115 import android.content.pm.PermissionInfo;
116 import android.content.pm.UserInfo;
117 import android.hardware.biometrics.BiometricsProtoEnums;
118 import android.hardware.display.DisplayManager;
119 import android.hardware.face.FaceManager;
120 import android.hardware.fingerprint.FingerprintManager;
121 import android.health.connect.HealthConnectManager;
122 import android.media.AudioManager;
123 import android.media.MediaDrm;
124 import android.media.UnsupportedSchemeException;
125 import android.net.ConnectivityManager;
126 import android.net.Network;
127 import android.net.NetworkRequest;
128 import android.net.NetworkStats;
129 import android.net.NetworkTemplate;
130 import android.net.wifi.WifiManager;
131 import android.os.AsyncTask;
132 import android.os.BatteryManager;
133 import android.os.BatteryProperty;
134 import android.os.BatteryStats;
135 import android.os.BatteryStatsInternal;
136 import android.os.BatteryStatsManager;
137 import android.os.BatteryUsageStats;
138 import android.os.Binder;
139 import android.os.Build;
140 import android.os.Bundle;
141 import android.os.CoolingDevice;
142 import android.os.Environment;
143 import android.os.IStoraged;
144 import android.os.IThermalEventListener;
145 import android.os.IThermalService;
146 import android.os.OutcomeReceiver;
147 import android.os.ParcelFileDescriptor;
148 import android.os.Parcelable;
149 import android.os.RemoteException;
150 import android.os.ServiceManager;
151 import android.os.ServiceSpecificException;
152 import android.os.StatFs;
153 import android.os.SynchronousResultReceiver;
154 import android.os.SystemClock;
155 import android.os.SystemProperties;
156 import android.os.Temperature;
157 import android.os.Trace;
158 import android.os.UserHandle;
159 import android.os.UserManager;
160 import android.os.connectivity.WifiActivityEnergyInfo;
161 import android.os.incremental.IncrementalManager;
162 import android.os.storage.DiskInfo;
163 import android.os.storage.StorageManager;
164 import android.os.storage.VolumeInfo;
165 import android.provider.DeviceConfig;
166 import android.provider.Settings;
167 import android.security.metrics.CrashStats;
168 import android.security.metrics.IKeystoreMetrics;
169 import android.security.metrics.KeyCreationWithAuthInfo;
170 import android.security.metrics.KeyCreationWithGeneralInfo;
171 import android.security.metrics.KeyCreationWithPurposeAndModesInfo;
172 import android.security.metrics.KeyOperationWithGeneralInfo;
173 import android.security.metrics.KeyOperationWithPurposeAndModesInfo;
174 import android.security.metrics.Keystore2AtomWithOverflow;
175 import android.security.metrics.KeystoreAtom;
176 import android.security.metrics.KeystoreAtomPayload;
177 import android.security.metrics.RkpErrorStats;
178 import android.security.metrics.StorageStats;
179 import android.stats.storage.StorageEnums;
180 import android.telephony.ModemActivityInfo;
181 import android.telephony.SubscriptionInfo;
182 import android.telephony.SubscriptionManager;
183 import android.telephony.TelephonyManager;
184 import android.text.TextUtils;
185 import android.util.ArrayMap;
186 import android.util.ArraySet;
187 import android.util.Log;
188 import android.util.Pair;
189 import android.util.Slog;
190 import android.util.SparseArray;
191 import android.util.SparseIntArray;
192 import android.util.StatsEvent;
193 import android.util.proto.ProtoOutputStream;
194 import android.uwb.UwbActivityEnergyInfo;
195 import android.uwb.UwbManager;
196 import android.view.Display;
197 
198 import com.android.internal.annotations.GuardedBy;
199 import com.android.internal.app.procstats.IProcessStats;
200 import com.android.internal.app.procstats.ProcessStats;
201 import com.android.internal.app.procstats.StatsEventOutput;
202 import com.android.internal.os.BackgroundThread;
203 import com.android.internal.os.BinderCallsStats.ExportedCallStat;
204 import com.android.internal.os.KernelAllocationStats;
205 import com.android.internal.os.KernelCpuBpfTracking;
206 import com.android.internal.os.KernelCpuThreadReader;
207 import com.android.internal.os.KernelCpuThreadReaderDiff;
208 import com.android.internal.os.KernelCpuThreadReaderSettingsObserver;
209 import com.android.internal.os.KernelCpuTotalBpfMapReader;
210 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
211 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
212 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
213 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
214 import com.android.internal.os.KernelSingleProcessCpuThreadReader.ProcessCpuUsage;
215 import com.android.internal.os.LooperStats;
216 import com.android.internal.os.PowerProfile;
217 import com.android.internal.os.ProcessCpuTracker;
218 import com.android.internal.os.ProcfsMemoryUtil;
219 import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot;
220 import com.android.internal.os.SelectedProcessCpuThreadReader;
221 import com.android.internal.os.StoragedUidIoStatsReader;
222 import com.android.internal.util.CollectionUtils;
223 import com.android.internal.util.FrameworkStatsLog;
224 import com.android.role.RoleManagerLocal;
225 import com.android.server.BinderCallsStatsService;
226 import com.android.server.LocalManagerRegistry;
227 import com.android.server.LocalServices;
228 import com.android.server.SystemService;
229 import com.android.server.SystemServiceManager;
230 import com.android.server.am.MemoryStatUtil.MemoryStat;
231 import com.android.server.health.HealthServiceWrapper;
232 import com.android.server.notification.NotificationManagerService;
233 import com.android.server.pinner.PinnerService;
234 import com.android.server.pinner.PinnerService.PinnedFileStats;
235 import com.android.server.pm.UserManagerInternal;
236 import com.android.server.power.stats.KernelWakelockReader;
237 import com.android.server.power.stats.KernelWakelockStats;
238 import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
239 import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
240 import com.android.server.stats.pull.netstats.NetworkStatsAccumulator;
241 import com.android.server.stats.pull.netstats.NetworkStatsExt;
242 import com.android.server.stats.pull.netstats.SubInfo;
243 import com.android.server.stats.pull.psi.PsiData;
244 import com.android.server.stats.pull.psi.PsiExtractor;
245 import com.android.server.storage.DiskStatsFileLogger;
246 import com.android.server.storage.DiskStatsLoggingService;
247 import com.android.server.timezonedetector.MetricsTimeZoneDetectorState;
248 import com.android.server.timezonedetector.TimeZoneDetectorInternal;
249 
250 import libcore.io.IoUtils;
251 
252 import org.json.JSONArray;
253 import org.json.JSONException;
254 import org.json.JSONObject;
255 
256 import java.io.ByteArrayOutputStream;
257 import java.io.File;
258 import java.io.FileOutputStream;
259 import java.io.IOException;
260 import java.io.InputStream;
261 import java.security.NoSuchAlgorithmException;
262 import java.time.Instant;
263 import java.time.temporal.ChronoUnit;
264 import java.util.ArrayList;
265 import java.util.Arrays;
266 import java.util.HashSet;
267 import java.util.List;
268 import java.util.Map;
269 import java.util.MissingResourceException;
270 import java.util.NoSuchElementException;
271 import java.util.Random;
272 import java.util.Set;
273 import java.util.UUID;
274 import java.util.concurrent.CompletableFuture;
275 import java.util.concurrent.ExecutionException;
276 import java.util.concurrent.Executor;
277 import java.util.concurrent.ThreadLocalRandom;
278 import java.util.concurrent.TimeUnit;
279 import java.util.concurrent.TimeoutException;
280 import java.util.concurrent.atomic.AtomicInteger;
281 import java.util.function.Function;
282 
283 /**
284  * SystemService containing PullAtomCallbacks that are registered with statsd.
285  *
286  * @hide
287  */
288 public class StatsPullAtomService extends SystemService {
289     private static final String TAG = "StatsPullAtomService";
290     private static final boolean DEBUG = true;
291 
292     // Random seed stable for StatsPullAtomService life cycle - can be used for stable sampling
293     private static final int RANDOM_SEED = new Random().nextInt();
294 
295     private static final int DIMENSION_KEY_SIZE_HARD_LIMIT = 800;
296     private static final int DIMENSION_KEY_SIZE_SOFT_LIMIT = 500;
297     private static final long APP_OPS_SAMPLING_INITIALIZATION_DELAY_MILLIS = 45000;
298     private static final int APP_OPS_SIZE_ESTIMATE = 2000;
299 
300     private static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
301     /**
302      * How long to wait on an individual subsystem to return its stats.
303      */
304     private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
305     private static final long MILLIS_PER_SEC = 1000;
306     private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
307 
308     /**
309      * The default bucket duration used when query a snapshot from NetworkStatsService.
310      * The value should be sync with NetworkStatsService#DefaultNetworkStatsSettings#getUidConfig.
311      */
312     private static final long NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS = HOURS.toMillis(2);
313 
314     /**
315      * Polling NetworkStats is a heavy operation and it should be done sparingly. Atom pulls may
316      * happen in bursts, but these should be infrequent. The poll rate limit ensures that data is
317      * sufficiently fresh (i.e. not stale) while reducing system load during atom pull bursts.
318      */
319     private static final long NETSTATS_POLL_RATE_LIMIT_MS = 15000;
320 
321     private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
322     private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED;
323     private static final String COMMON_PERMISSION_PREFIX = "android.permission.";
324     private static final String APP_OPS_TARGET_COLLECTION_SIZE = "app_ops_target_collection_size";
325     private static final String DANGEROUS_PERMISSION_STATE_SAMPLE_RATE =
326             "dangerous_permission_state_sample_rate";
327 
328     /** Parameters relating to ProcStats data upload. */
329     // Maximum shards to use when generating StatsEvent objects from ProcStats.
330     private static final int MAX_PROCSTATS_SHARDS = 5;
331     // Should match MAX_PAYLOAD_SIZE in StatsEvent, minus a small amount for overhead/metadata.
332     private static final int MAX_PROCSTATS_SHARD_SIZE = 48 * 1024; // 48 KB
333     // In ProcessStats, we measure the size of a raw ProtoOutputStream, before compaction. This
334     // typically runs 35-45% larger than the compacted size that will be written to StatsEvent.
335     // Hence, we can allow a little more room in each shard before moving to the next. Make this
336     // 20% as a conservative estimate.
337     private static final int MAX_PROCSTATS_RAW_SHARD_SIZE = (int) (MAX_PROCSTATS_SHARD_SIZE * 1.20);
338 
339     /**
340      * Threshold to filter out small CPU times at frequency per UID. Those small values appear
341      * because of more precise accounting in a BPF program. Discarding them reduces the data by at
342      * least 20% with negligible error.
343      */
344     private static final int MIN_CPU_TIME_PER_UID_FREQ = 10;
345 
346     /** Number of entries in CpuCyclesPerUidCluster atom stored in an array for each cluster. */
347     private static final int CPU_CYCLES_PER_UID_CLUSTER_VALUES = 3;
348 
349     private final Object mThermalLock = new Object();
350     @GuardedBy("mThermalLock")
351     private IThermalService mThermalService;
352 
353     private final Object mStoragedLock = new Object();
354     @GuardedBy("mStoragedLock")
355     private IStoraged mStorageService;
356 
357     private final Object mNotificationStatsLock = new Object();
358     @GuardedBy("mNotificationStatsLock")
359     private INotificationManager mNotificationManagerService;
360 
361     @GuardedBy("mProcStatsLock")
362     private IProcessStats mProcessStatsService;
363 
364     @GuardedBy("mProcessCpuTimeLock")
365     private ProcessCpuTracker mProcessCpuTracker;
366 
367     @GuardedBy("mDebugElapsedClockLock")
368     private long mDebugElapsedClockPreviousValue = 0;
369     @GuardedBy("mDebugElapsedClockLock")
370     private long mDebugElapsedClockPullCount = 0;
371 
372     @GuardedBy("mDebugFailingElapsedClockLock")
373     private long mDebugFailingElapsedClockPreviousValue = 0;
374     @GuardedBy("mDebugFailingElapsedClockLock")
375     private long mDebugFailingElapsedClockPullCount = 0;
376 
377     private final Context mContext;
378     private StatsManager mStatsManager;
379     private StorageManager mStorageManager;
380     private WifiManager mWifiManager;
381     private TelephonyManager mTelephony;
382     private UwbManager mUwbManager;
383     private SubscriptionManager mSubscriptionManager;
384 
385     /**
386      * NetworkStatsManager initialization happens from one thread before any worker thread
387      * is going to access the networkStatsManager instance:
388      * - @initNetworkStatsManager() - initialization happens no worker thread to access are
389      *   active yet
390      * - @initAndRegisterNetworkStatsPullers Network stats dependant pullers can only be
391      *   initialized after service is ready. Worker thread is spawn here only after the
392      *   initialization is completed in a thread safe way (no async access expected)
393      */
394     private NetworkStatsManager mNetworkStatsManager = null;
395 
396     @GuardedBy("mKernelWakelockLock")
397     private KernelWakelockReader mKernelWakelockReader;
398     @GuardedBy("mKernelWakelockLock")
399     private KernelWakelockStats mTmpWakelockStats;
400 
401     @GuardedBy("mDiskIoLock")
402     private StoragedUidIoStatsReader mStoragedUidIoStatsReader;
403 
404     // Disables throttler on CPU time readers.
405     @GuardedBy("mCpuTimePerUidLock")
406     private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
407     @GuardedBy("mCpuTimePerUidFreqLock")
408     private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
409     @GuardedBy("mCpuActiveTimeLock")
410     private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
411     @GuardedBy("mClusterTimeLock")
412     private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
413 
414     @GuardedBy("mProcStatsLock")
415     private File mBaseDir;
416 
417     @GuardedBy("mHealthHalLock")
418     private HealthServiceWrapper mHealthService;
419 
420     @Nullable
421     @GuardedBy("mCpuTimePerThreadFreqLock")
422     private KernelCpuThreadReaderDiff mKernelCpuThreadReader;
423 
424     private StatsPullAtomCallbackImpl mStatsCallbackImpl;
425 
426     @GuardedBy("mAttributedAppOpsLock")
427     private int mAppOpsSamplingRate = 0;
428     private final Object mDangerousAppOpsListLock = new Object();
429     @GuardedBy("mDangerousAppOpsListLock")
430     private final ArraySet<Integer> mDangerousAppOpsList = new ArraySet<>();
431 
432     // Baselines that stores list of NetworkStats right after initializing, with associated
433     // information. This is used to calculate difference when pulling BytesTransfer atoms.
434     @NonNull
435     @GuardedBy("mDataBytesTransferLock")
436     private final ArrayList<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>();
437 
438     // Accumulates NetworkStats from initialization till the present moment.
439     // It is necessary to accumulate stats internally, because NetworkStats persists data for a
440     // limited amount of time, after which diff becomes incorrect without accumulation.
441     @NonNull
442     @GuardedBy("mDataBytesTransferLock")
443     private final ArrayList<NetworkStatsAccumulator> mNetworkStatsAccumulators =
444             new ArrayList<>();
445 
446     @GuardedBy("mDataBytesTransferLock")
447     private long mLastNetworkStatsPollTime = -NETSTATS_POLL_RATE_LIMIT_MS;
448 
449     // Listener for monitoring subscriptions changed event.
450     private StatsSubscriptionsListener mStatsSubscriptionsListener;
451     // List that stores SubInfo of subscriptions that ever appeared since boot.
452     @GuardedBy("mDataBytesTransferLock")
453     private final ArrayList<SubInfo> mHistoricalSubs = new ArrayList<>();
454 
455     private SelectedProcessCpuThreadReader mSurfaceFlingerProcessCpuThreadReader;
456 
457     // Only access via getIKeystoreMetricsService
458     @GuardedBy("mKeystoreLock")
459     private IKeystoreMetrics mIKeystoreMetrics;
460 
461     private AggregatedMobileDataStatsPuller mAggregatedMobileDataStatsPuller = null;
462 
463     /**
464      * Whether or not to enable the new puller with aggregation by process state per uid on a
465      * system server side.
466      */
467     public static final boolean ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER =
468                 addMobileBytesTransferByProcStatePuller();
469 
470     // Whether or not to enable the new puller with pressure stall information.
471     public static final boolean ENABLE_PRESSURE_STALL_INFORMATION_PULLER =
472                 addPressureStallInformationPuller();
473 
474     // Puller locks
475     private final Object mDataBytesTransferLock = new Object();
476     private final Object mBluetoothBytesTransferLock = new Object();
477     private final Object mKernelWakelockLock = new Object();
478     private final Object mCpuTimePerClusterFreqLock = new Object();
479     private final Object mCpuTimePerUidLock = new Object();
480     private final Object mCpuTimePerUidFreqLock = new Object();
481     private final Object mCpuActiveTimeLock = new Object();
482     private final Object mCpuClusterTimeLock = new Object();
483     private final Object mWifiActivityInfoLock = new Object();
484     private final Object mModemActivityInfoLock = new Object();
485     private final Object mBluetoothActivityInfoLock = new Object();
486     private final Object mUwbActivityInfoLock = new Object();
487     private final Object mSystemElapsedRealtimeLock = new Object();
488     private final Object mSystemUptimeLock = new Object();
489     private final Object mProcessMemoryStateLock = new Object();
490     private final Object mProcessMemoryHighWaterMarkLock = new Object();
491     private final Object mSystemIonHeapSizeLock = new Object();
492     private final Object mIonHeapSizeLock = new Object();
493     private final Object mProcessSystemIonHeapSizeLock = new Object();
494     private final Object mTemperatureLock = new Object();
495     private final Object mCooldownDeviceLock = new Object();
496     private final Object mBinderCallsStatsLock = new Object();
497     private final Object mBinderCallsStatsExceptionsLock = new Object();
498     private final Object mLooperStatsLock = new Object();
499     private final Object mDiskStatsLock = new Object();
500     private final Object mDirectoryUsageLock = new Object();
501     private final Object mAppSizeLock = new Object();
502     private final Object mCategorySizeLock = new Object();
503     private final Object mNumBiometricsEnrolledLock = new Object();
504     private final Object mProcStatsLock = new Object();
505     private final Object mDiskIoLock = new Object();
506     private final Object mPowerProfileLock = new Object();
507     private final Object mProcessCpuTimeLock = new Object();
508     private final Object mCpuTimePerThreadFreqLock = new Object();
509     private final Object mDeviceCalculatedPowerUseLock = new Object();
510     private final Object mDebugElapsedClockLock = new Object();
511     private final Object mDebugFailingElapsedClockLock = new Object();
512     private final Object mBuildInformationLock = new Object();
513     private final Object mRoleHolderLock = new Object();
514     private final Object mTimeZoneDataInfoLock = new Object();
515     private final Object mTimeZoneDetectionInfoLock = new Object();
516     private final Object mExternalStorageInfoLock = new Object();
517     private final Object mAppsOnExternalStorageInfoLock = new Object();
518     private final Object mFaceSettingsLock = new Object();
519     private final Object mAppOpsLock = new Object();
520     private final Object mRuntimeAppOpAccessMessageLock = new Object();
521     private final Object mNotificationRemoteViewsLock = new Object();
522     private final Object mDangerousPermissionStateLock = new Object();
523     private final Object mHealthHalLock = new Object();
524     private final Object mAttributedAppOpsLock = new Object();
525     private final Object mSettingsStatsLock = new Object();
526     private final Object mInstalledIncrementalPackagesLock = new Object();
527     private final Object mKeystoreLock = new Object();
528 
StatsPullAtomService(Context context)529     public StatsPullAtomService(Context context) {
530         super(context);
531         mContext = context;
532     }
533 
534     private final class StatsPullAtomServiceInternalImpl extends StatsPullAtomServiceInternal {
535 
536         @Override
noteUidProcessState(int uid, int state)537         public void noteUidProcessState(int uid, int state) {
538             if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER
539                     && mAggregatedMobileDataStatsPuller != null) {
540                 final long elapsedRealtime = SystemClock.elapsedRealtime();
541                 final long uptime = SystemClock.uptimeMillis();
542                 mAggregatedMobileDataStatsPuller.noteUidProcessState(uid, state, elapsedRealtime,
543                         uptime);
544             }
545         }
546     }
547 
initializeNativePullers()548     private native void initializeNativePullers();
549 
550     /**
551      * Use of this StatsPullAtomCallbackImpl means we avoid one class per tagId, which we would
552      * get if we used lambdas.
553      *
554      * The pull methods are intentionally left to be package private to avoid the creation
555      * of synthetic methods to save unnecessary bytecode.
556      */
557     private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
558         @Override
onPullAtom(int atomTag, List<StatsEvent> data)559         public int onPullAtom(int atomTag, List<StatsEvent> data) {
560             if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
561                 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StatsPull-" + atomTag);
562             }
563             try {
564                 switch (atomTag) {
565                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE:
566                         if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER
567                                 && mAggregatedMobileDataStatsPuller != null) {
568                             return mAggregatedMobileDataStatsPuller.pullDataBytesTransfer(data);
569                         }
570                     case FrameworkStatsLog.WIFI_BYTES_TRANSFER:
571                     case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG:
572                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER:
573                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
574                     case FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG:
575                     case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
576                     case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
577                     case FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER:
578                         synchronized (mDataBytesTransferLock) {
579                             return pullDataBytesTransferLocked(atomTag, data);
580                         }
581                     case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER:
582                         synchronized (mBluetoothBytesTransferLock) {
583                             return pullBluetoothBytesTransferLocked(atomTag, data);
584                         }
585                     case FrameworkStatsLog.KERNEL_WAKELOCK:
586                         synchronized (mKernelWakelockLock) {
587                             return pullKernelWakelockLocked(atomTag, data);
588                         }
589                     case FrameworkStatsLog.CPU_TIME_PER_CLUSTER_FREQ:
590                         synchronized (mCpuTimePerClusterFreqLock) {
591                             return pullCpuTimePerClusterFreqLocked(atomTag, data);
592                         }
593                     case FrameworkStatsLog.CPU_TIME_PER_UID:
594                         synchronized (mCpuTimePerUidLock) {
595                             return pullCpuTimePerUidLocked(atomTag, data);
596                         }
597                     case FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER:
598                         // Use the same lock as CPU_TIME_PER_UID_FREQ because data is pulled from
599                         // the same source.
600                         synchronized (mCpuTimePerUidFreqLock) {
601                             return pullCpuCyclesPerUidClusterLocked(atomTag, data);
602                         }
603                     case FrameworkStatsLog.CPU_TIME_PER_UID_FREQ:
604                         synchronized (mCpuTimePerUidFreqLock) {
605                             return pullCpuTimePerUidFreqLocked(atomTag, data);
606                         }
607                     case FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER:
608                         return pullCpuCyclesPerThreadGroupCluster(atomTag, data);
609                     case FrameworkStatsLog.CPU_ACTIVE_TIME:
610                         synchronized (mCpuActiveTimeLock) {
611                             return pullCpuActiveTimeLocked(atomTag, data);
612                         }
613                     case FrameworkStatsLog.CPU_CLUSTER_TIME:
614                         synchronized (mCpuClusterTimeLock) {
615                             return pullCpuClusterTimeLocked(atomTag, data);
616                         }
617                     case FrameworkStatsLog.WIFI_ACTIVITY_INFO:
618                         synchronized (mWifiActivityInfoLock) {
619                             return pullWifiActivityInfoLocked(atomTag, data);
620                         }
621                     case FrameworkStatsLog.MODEM_ACTIVITY_INFO:
622                         synchronized (mModemActivityInfoLock) {
623                             return pullModemActivityInfoLocked(atomTag, data);
624                         }
625                     case FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO:
626                         synchronized (mBluetoothActivityInfoLock) {
627                             return pullBluetoothActivityInfoLocked(atomTag, data);
628                         }
629                     case FrameworkStatsLog.UWB_ACTIVITY_INFO:
630                         synchronized (mUwbActivityInfoLock) {
631                             return pullUwbActivityInfoLocked(atomTag, data);
632                         }
633                     case FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME:
634                         synchronized (mSystemElapsedRealtimeLock) {
635                             return pullSystemElapsedRealtimeLocked(atomTag, data);
636                         }
637                     case FrameworkStatsLog.SYSTEM_UPTIME:
638                         synchronized (mSystemUptimeLock) {
639                             return pullSystemUptimeLocked(atomTag, data);
640                         }
641                     case FrameworkStatsLog.PROCESS_MEMORY_STATE:
642                         synchronized (mProcessMemoryStateLock) {
643                             return pullProcessMemoryStateLocked(atomTag, data);
644                         }
645                     case FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK:
646                         synchronized (mProcessMemoryHighWaterMarkLock) {
647                             return pullProcessMemoryHighWaterMarkLocked(atomTag, data);
648                         }
649                     case FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT:
650                         return pullProcessMemorySnapshot(atomTag, data);
651                     case FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE:
652                         synchronized (mSystemIonHeapSizeLock) {
653                             return pullSystemIonHeapSizeLocked(atomTag, data);
654                         }
655                     case FrameworkStatsLog.ION_HEAP_SIZE:
656                         synchronized (mIonHeapSizeLock) {
657                             return pullIonHeapSizeLocked(atomTag, data);
658                         }
659                     case FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE:
660                         synchronized (mProcessSystemIonHeapSizeLock) {
661                             return pullProcessSystemIonHeapSizeLocked(atomTag, data);
662                         }
663                     case FrameworkStatsLog.PROCESS_DMABUF_MEMORY:
664                         return pullProcessDmabufMemory(atomTag, data);
665                     case FrameworkStatsLog.SYSTEM_MEMORY:
666                         return pullSystemMemory(atomTag, data);
667                     case FrameworkStatsLog.VMSTAT:
668                         return pullVmStat(atomTag, data);
669                     case FrameworkStatsLog.TEMPERATURE:
670                         synchronized (mTemperatureLock) {
671                             return pullTemperatureLocked(atomTag, data);
672                         }
673                     case FrameworkStatsLog.COOLING_DEVICE:
674                         synchronized (mCooldownDeviceLock) {
675                             return pullCooldownDeviceLocked(atomTag, data);
676                         }
677                     case FrameworkStatsLog.BINDER_CALLS:
678                         synchronized (mBinderCallsStatsLock) {
679                             return pullBinderCallsStatsLocked(atomTag, data);
680                         }
681                     case FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS:
682                         synchronized (mBinderCallsStatsExceptionsLock) {
683                             return pullBinderCallsStatsExceptionsLocked(atomTag, data);
684                         }
685                     case FrameworkStatsLog.LOOPER_STATS:
686                         synchronized (mLooperStatsLock) {
687                             return pullLooperStatsLocked(atomTag, data);
688                         }
689                     case FrameworkStatsLog.DISK_STATS:
690                         synchronized (mDiskStatsLock) {
691                             return pullDiskStatsLocked(atomTag, data);
692                         }
693                     case FrameworkStatsLog.DIRECTORY_USAGE:
694                         synchronized (mDirectoryUsageLock) {
695                             return pullDirectoryUsageLocked(atomTag, data);
696                         }
697                     case FrameworkStatsLog.APP_SIZE:
698                         synchronized (mAppSizeLock) {
699                             return pullAppSizeLocked(atomTag, data);
700                         }
701                     case FrameworkStatsLog.CATEGORY_SIZE:
702                         synchronized (mCategorySizeLock) {
703                             return pullCategorySizeLocked(atomTag, data);
704                         }
705                     case FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED:
706                         synchronized (mNumBiometricsEnrolledLock) {
707                             return pullNumBiometricsEnrolledLocked(
708                                     BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data);
709                         }
710                     case FrameworkStatsLog.NUM_FACES_ENROLLED:
711                         synchronized (mNumBiometricsEnrolledLock) {
712                             return pullNumBiometricsEnrolledLocked(
713                                     BiometricsProtoEnums.MODALITY_FACE, atomTag, data);
714                         }
715                     case FrameworkStatsLog.PROC_STATS:
716                         synchronized (mProcStatsLock) {
717                             return pullProcStatsLocked(atomTag, data);
718                         }
719                     case FrameworkStatsLog.PROC_STATS_PKG_PROC:
720                         synchronized (mProcStatsLock) {
721                             return pullProcStatsLocked(atomTag, data);
722                         }
723                     case FrameworkStatsLog.PROCESS_STATE:
724                         synchronized (mProcStatsLock) {
725                             return pullProcessStateLocked(atomTag, data);
726                         }
727                     case FrameworkStatsLog.PROCESS_ASSOCIATION:
728                         synchronized (mProcStatsLock) {
729                             return pullProcessAssociationLocked(atomTag, data);
730                         }
731                     case FrameworkStatsLog.DISK_IO:
732                         synchronized (mDiskIoLock) {
733                             return pullDiskIOLocked(atomTag, data);
734                         }
735                     case FrameworkStatsLog.POWER_PROFILE:
736                         synchronized (mPowerProfileLock) {
737                             return pullPowerProfileLocked(atomTag, data);
738                         }
739                     case FrameworkStatsLog.PROCESS_CPU_TIME:
740                         synchronized (mProcessCpuTimeLock) {
741                             return pullProcessCpuTimeLocked(atomTag, data);
742                         }
743                     case FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ:
744                         synchronized (mCpuTimePerThreadFreqLock) {
745                             return pullCpuTimePerThreadFreqLocked(atomTag, data);
746                         }
747                     case FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE:
748                         synchronized (mDeviceCalculatedPowerUseLock) {
749                             return pullDeviceCalculatedPowerUseLocked(atomTag, data);
750                         }
751                     case FrameworkStatsLog.DEBUG_ELAPSED_CLOCK:
752                         synchronized (mDebugElapsedClockLock) {
753                             return pullDebugElapsedClockLocked(atomTag, data);
754                         }
755                     case FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK:
756                         synchronized (mDebugFailingElapsedClockLock) {
757                             return pullDebugFailingElapsedClockLocked(atomTag, data);
758                         }
759                     case FrameworkStatsLog.BUILD_INFORMATION:
760                         synchronized (mBuildInformationLock) {
761                             return pullBuildInformationLocked(atomTag, data);
762                         }
763                     case FrameworkStatsLog.ROLE_HOLDER:
764                         synchronized (mRoleHolderLock) {
765                             return pullRoleHolderLocked(atomTag, data);
766                         }
767                     case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE:
768                         // fall-through - same call covers two cases
769                     case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED:
770                         synchronized (mDangerousPermissionStateLock) {
771                             return pullDangerousPermissionStateLocked(atomTag, data);
772                         }
773                     case FrameworkStatsLog.TIME_ZONE_DATA_INFO:
774                         synchronized (mTimeZoneDataInfoLock) {
775                             return pullTimeZoneDataInfoLocked(atomTag, data);
776                         }
777                     case FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE:
778                         synchronized (mTimeZoneDetectionInfoLock) {
779                             return pullTimeZoneDetectorStateLocked(atomTag, data);
780                         }
781                     case FrameworkStatsLog.EXTERNAL_STORAGE_INFO:
782                         synchronized (mExternalStorageInfoLock) {
783                             return pullExternalStorageInfoLocked(atomTag, data);
784                         }
785                     case FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO:
786                         synchronized (mAppsOnExternalStorageInfoLock) {
787                             return pullAppsOnExternalStorageInfoLocked(atomTag, data);
788                         }
789                     case FrameworkStatsLog.FACE_SETTINGS:
790                         synchronized (mFaceSettingsLock) {
791                             return pullFaceSettingsLocked(atomTag, data);
792                         }
793                     case FrameworkStatsLog.APP_OPS:
794                         synchronized (mAppOpsLock) {
795                             return pullAppOpsLocked(atomTag, data);
796                         }
797                     case FrameworkStatsLog.RUNTIME_APP_OP_ACCESS:
798                         synchronized (mRuntimeAppOpAccessMessageLock) {
799                             return pullRuntimeAppOpAccessMessageLocked(atomTag, data);
800                         }
801                     case FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS:
802                         synchronized (mNotificationRemoteViewsLock) {
803                             return pullNotificationRemoteViewsLocked(atomTag, data);
804                         }
805                     case FrameworkStatsLog.BATTERY_LEVEL:
806                     case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY:
807                     case FrameworkStatsLog.FULL_BATTERY_CAPACITY:
808                     case FrameworkStatsLog.BATTERY_VOLTAGE:
809                     case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
810                     case FrameworkStatsLog.BATTERY_HEALTH:
811                         synchronized (mHealthHalLock) {
812                             return pullHealthHalLocked(atomTag, data);
813                         }
814                     case FrameworkStatsLog.ATTRIBUTED_APP_OPS:
815                         synchronized (mAttributedAppOpsLock) {
816                             return pullAttributedAppOpsLocked(atomTag, data);
817                         }
818                     case FrameworkStatsLog.SETTING_SNAPSHOT:
819                         synchronized (mSettingsStatsLock) {
820                             return pullSettingsStatsLocked(atomTag, data);
821                         }
822                     case FrameworkStatsLog.INSTALLED_INCREMENTAL_PACKAGE:
823                         synchronized (mInstalledIncrementalPackagesLock) {
824                             return pullInstalledIncrementalPackagesLocked(atomTag, data);
825                         }
826                     case FrameworkStatsLog.KEYSTORE2_STORAGE_STATS:
827                     case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO:
828                     case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO:
829                     case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO:
830                     case FrameworkStatsLog.KEYSTORE2_ATOM_WITH_OVERFLOW:
831                     case FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO:
832                     case FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO:
833                     case FrameworkStatsLog.RKP_ERROR_STATS:
834                     case FrameworkStatsLog.KEYSTORE2_CRASH_STATS:
835                         return pullKeystoreAtoms(atomTag, data);
836                     case FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS:
837                         return pullAccessibilityShortcutStatsLocked(data);
838                     case FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS:
839                         return pullAccessibilityFloatingMenuStatsLocked(atomTag, data);
840                     case FrameworkStatsLog.MEDIA_CAPABILITIES:
841                         return pullMediaCapabilitiesStats(atomTag, data);
842                     case FrameworkStatsLog.PINNED_FILE_SIZES_PER_PACKAGE:
843                         return pullSystemServerPinnerStats(atomTag, data);
844                     case FrameworkStatsLog.PENDING_INTENTS_PER_PACKAGE:
845                         return pullPendingIntentsPerPackage(atomTag, data);
846                     case FrameworkStatsLog.HDR_CAPABILITIES:
847                         return pullHdrCapabilities(atomTag, data);
848                     case FrameworkStatsLog.CACHED_APPS_HIGH_WATERMARK:
849                         return pullCachedAppsHighWatermark(atomTag, data);
850                     case FrameworkStatsLog.PRESSURE_STALL_INFORMATION:
851                         return pullPressureStallInformation(atomTag, data);
852                     default:
853                         throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
854                 }
855             } finally {
856                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
857             }
858         }
859     }
860 
861     @Override
onStart()862     public void onStart() {
863         if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) {
864             LocalServices.addService(StatsPullAtomServiceInternal.class,
865                     new StatsPullAtomServiceInternalImpl());
866         }
867     }
868 
869     @Override
onBootPhase(int phase)870     public void onBootPhase(int phase) {
871         super.onBootPhase(phase);
872         if (phase == PHASE_SYSTEM_SERVICES_READY) {
873             BackgroundThread.getHandler().post(() -> {
874                 initializeNativePullers(); // Initialize pullers that need JNI.
875                 initializePullersState();
876                 registerPullers();
877                 registerEventListeners();
878             });
879         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
880             initNetworkStatsManager();
881             BackgroundThread.getHandler().post(() -> {
882                 // Network stats related pullers can only be initialized after service is ready.
883                 initAndRegisterNetworkStatsPullers();
884                 // For services that are not ready at boot phase PHASE_SYSTEM_SERVICES_READY
885                 initAndRegisterDeferredPullers();
886             });
887         }
888     }
889 
890     // We do not hold locks within this function because it is guaranteed to be called before the
891     // pullers are ever run, as the pullers are not yet registered with statsd.
initializePullersState()892     void initializePullersState() {
893         // Get Context Managers
894         mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER);
895         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
896         mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
897         mSubscriptionManager = (SubscriptionManager)
898                 mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
899         mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager);
900         mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
901 
902         // Initialize DiskIO
903         mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();
904 
905         // Initialize PROC_STATS
906         mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_pull");
907         mBaseDir.mkdirs();
908 
909         // Disables throttler on CPU time readers.
910         mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(false);
911         mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(false);
912         mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(false);
913         mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(false);
914 
915         // Initialize state for KERNEL_WAKELOCK
916         mKernelWakelockReader = new KernelWakelockReader();
917         mTmpWakelockStats = new KernelWakelockStats();
918 
919         // Used for CPU_TIME_PER_THREAD_FREQ
920         mKernelCpuThreadReader =
921                 KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
922 
923         // Initialize HealthService
924         try {
925             mHealthService = HealthServiceWrapper.create(null);
926         } catch (RemoteException | NoSuchElementException e) {
927             Slog.e(TAG, "failed to initialize healthHalWrapper");
928         }
929 
930         // Initialize list of AppOps related to DangerousPermissions
931         PackageManager pm = mContext.getPackageManager();
932         for (int op = 0; op < AppOpsManager._NUM_OP; op++) {
933             String perm = AppOpsManager.opToPermission(op);
934             if (perm == null) {
935                 continue;
936             } else {
937                 PermissionInfo permInfo;
938                 try {
939                     permInfo = pm.getPermissionInfo(perm, 0);
940                     if (permInfo.getProtection() == PROTECTION_DANGEROUS) {
941                         mDangerousAppOpsList.add(op);
942                     }
943                 } catch (PackageManager.NameNotFoundException exception) {
944                     continue;
945                 }
946             }
947         }
948 
949         mSurfaceFlingerProcessCpuThreadReader =
950                 new SelectedProcessCpuThreadReader("/system/bin/surfaceflinger");
951 
952         getIKeystoreMetricsService();
953     }
954 
registerEventListeners()955     void registerEventListeners() {
956         final ConnectivityManager connectivityManager =
957                 (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
958         // Default NetworkRequest should cover all transport types.
959         final NetworkRequest request = new NetworkRequest.Builder().build();
960         connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
961 
962         // Enable push notifications of throttling from vendor thermal
963         // management subsystem via thermalservice.
964         IThermalService thermalService = getIThermalService();
965         if (thermalService != null) {
966             try {
967                 thermalService.registerThermalEventListener(new ThermalEventListener());
968                 Slog.i(TAG, "register thermal listener successfully");
969             } catch (RemoteException e) {
970                 Slog.i(TAG, "failed to register thermal listener");
971             }
972         }
973     }
974 
registerPullers()975     void registerPullers() {
976         if (DEBUG) {
977             Slog.d(TAG, "Registering pullers with statsd");
978         }
979         mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
980         registerBluetoothBytesTransfer();
981         registerKernelWakelock();
982         registerCpuTimePerClusterFreq();
983         registerCpuTimePerUid();
984         registerCpuCyclesPerUidCluster();
985         registerCpuTimePerUidFreq();
986         registerCpuCyclesPerThreadGroupCluster();
987         registerCpuActiveTime();
988         registerCpuClusterTime();
989         registerWifiActivityInfo();
990         registerModemActivityInfo();
991         registerBluetoothActivityInfo();
992         registerSystemElapsedRealtime();
993         registerSystemUptime();
994         registerProcessMemoryState();
995         registerProcessMemoryHighWaterMark();
996         registerProcessMemorySnapshot();
997         registerSystemIonHeapSize();
998         registerIonHeapSize();
999         registerProcessSystemIonHeapSize();
1000         registerSystemMemory();
1001         registerProcessDmabufMemory();
1002         registerVmStat();
1003         registerTemperature();
1004         registerCoolingDevice();
1005         registerBinderCallsStats();
1006         registerBinderCallsStatsExceptions();
1007         registerLooperStats();
1008         registerDiskStats();
1009         registerDirectoryUsage();
1010         registerAppSize();
1011         registerCategorySize();
1012         registerNumFingerprintsEnrolled();
1013         registerNumFacesEnrolled();
1014         registerProcStats();
1015         registerProcStatsPkgProc();
1016         registerProcessState();
1017         registerProcessAssociation();
1018         registerDiskIO();
1019         registerPowerProfile();
1020         registerProcessCpuTime();
1021         registerCpuTimePerThreadFreq();
1022         registerDeviceCalculatedPowerUse();
1023         registerDebugElapsedClock();
1024         registerDebugFailingElapsedClock();
1025         registerBuildInformation();
1026         registerRoleHolder();
1027         registerTimeZoneDataInfo();
1028         registerTimeZoneDetectorState();
1029         registerExternalStorageInfo();
1030         registerAppsOnExternalStorageInfo();
1031         registerFaceSettings();
1032         registerAppOps();
1033         registerAttributedAppOps();
1034         registerRuntimeAppOpAccessMessage();
1035         registerNotificationRemoteViews();
1036         registerDangerousPermissionState();
1037         registerDangerousPermissionStateSampled();
1038         registerBatteryLevel();
1039         registerRemainingBatteryCapacity();
1040         registerFullBatteryCapacity();
1041         registerBatteryVoltage();
1042         registerBatteryCycleCount();
1043         registerBatteryHealth();
1044         registerSettingsStats();
1045         registerInstalledIncrementalPackages();
1046         registerKeystoreStorageStats();
1047         registerKeystoreKeyCreationWithGeneralInfo();
1048         registerKeystoreKeyCreationWithAuthInfo();
1049         registerKeystoreKeyCreationWithPurposeModesInfo();
1050         registerKeystoreAtomWithOverflow();
1051         registerKeystoreKeyOperationWithPurposeAndModesInfo();
1052         registerKeystoreKeyOperationWithGeneralInfo();
1053         registerRkpErrorStats();
1054         registerKeystoreCrashStats();
1055         registerAccessibilityShortcutStats();
1056         registerAccessibilityFloatingMenuStats();
1057         registerMediaCapabilitiesStats();
1058         registerPendingIntentsPerPackagePuller();
1059         registerPinnerServiceStats();
1060         registerHdrCapabilitiesPuller();
1061         registerCachedAppsHighWatermarkPuller();
1062         if (ENABLE_PRESSURE_STALL_INFORMATION_PULLER) {
1063             registerPressureStallInformation();
1064         }
1065     }
1066 
initMobileDataStatsPuller()1067     private void initMobileDataStatsPuller() {
1068         if (DEBUG) {
1069             Slog.d(TAG,
1070                     "ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER = "
1071                             + ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER);
1072         }
1073         if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) {
1074             mAggregatedMobileDataStatsPuller =
1075                     new AggregatedMobileDataStatsPuller(
1076                             mContext.getSystemService(NetworkStatsManager.class));
1077         }
1078     }
1079 
1080     /**
1081      * Calling getNetworkStatsManager() before PHASE_THIRD_PARTY_APPS_CAN_START is unexpected
1082      * Callers use before PHASE_THIRD_PARTY_APPS_CAN_START stage is not legit
1083      */
1084     @NonNull
getNetworkStatsManager()1085     private NetworkStatsManager getNetworkStatsManager() {
1086         if (mNetworkStatsManager == null) {
1087             throw new IllegalStateException("NetworkStatsManager is not ready");
1088         }
1089         return mNetworkStatsManager;
1090     }
1091 
initNetworkStatsManager()1092     private void initNetworkStatsManager() {
1093         mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
1094     }
1095 
initAndRegisterNetworkStatsPullers()1096     private void initAndRegisterNetworkStatsPullers() {
1097         if (DEBUG) {
1098             Slog.d(TAG, "Registering NetworkStats pullers with statsd");
1099         }
1100 
1101         boolean canQueryTypeProxy = canQueryNetworkStatsForTypeProxy();
1102 
1103         // Initialize NetworkStats baselines.
1104         synchronized (mDataBytesTransferLock) {
1105             mNetworkStatsBaselines.addAll(
1106                     collectNetworkStatsSnapshotForAtomLocked(
1107                             FrameworkStatsLog.WIFI_BYTES_TRANSFER));
1108             mNetworkStatsBaselines.addAll(
1109                     collectNetworkStatsSnapshotForAtomLocked(
1110                             FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG));
1111             mNetworkStatsBaselines.addAll(
1112                     collectNetworkStatsSnapshotForAtomLocked(
1113                             FrameworkStatsLog.MOBILE_BYTES_TRANSFER));
1114             mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked(
1115                     FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG));
1116             mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked(
1117                     FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED));
1118             mNetworkStatsBaselines.addAll(
1119                     collectNetworkStatsSnapshotForAtomLocked(
1120                             FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER));
1121             mNetworkStatsBaselines.addAll(
1122                     collectNetworkStatsSnapshotForAtomLocked(
1123                             FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER));
1124             if (canQueryTypeProxy) {
1125                 mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked(
1126                         FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG));
1127             }
1128         }
1129 
1130         // Listen to subscription changes to record historical subscriptions that activated before
1131         // pulling, this is used by {@code DATA_USAGE_BYTES_TRANSFER}.
1132         mSubscriptionManager.addOnSubscriptionsChangedListener(
1133                 BackgroundThread.getExecutor(), mStatsSubscriptionsListener);
1134 
1135         registerWifiBytesTransfer();
1136         registerWifiBytesTransferBackground();
1137         registerMobileBytesTransfer();
1138         registerMobileBytesTransferBackground();
1139         if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) {
1140             initMobileDataStatsPuller();
1141             registerMobileBytesTransferByProcState();
1142         }
1143         registerBytesTransferByTagAndMetered();
1144         registerDataUsageBytesTransfer();
1145         registerOemManagedBytesTransfer();
1146         if (canQueryTypeProxy) {
1147             registerProxyBytesTransferBackground();
1148         }
1149     }
1150 
registerMobileBytesTransferByProcState()1151     private void registerMobileBytesTransferByProcState() {
1152         final int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE;
1153         PullAtomMetadata metadata =
1154                 new PullAtomMetadata.Builder().setAdditiveFields(new int[] {3, 4, 5, 6}).build();
1155         mStatsManager.setPullAtomCallback(tagId, metadata, DIRECT_EXECUTOR, mStatsCallbackImpl);
1156     }
1157 
initAndRegisterDeferredPullers()1158     private void initAndRegisterDeferredPullers() {
1159         mUwbManager = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)
1160             ? mContext.getSystemService(UwbManager.class) : null;
1161 
1162         registerUwbActivityInfo();
1163     }
1164 
getIThermalService()1165     private IThermalService getIThermalService() {
1166         synchronized (mThermalLock) {
1167             if (mThermalService == null) {
1168                 mThermalService = IThermalService.Stub.asInterface(
1169                         ServiceManager.getService(Context.THERMAL_SERVICE));
1170                 if (mThermalService != null) {
1171                     try {
1172                         mThermalService.asBinder().linkToDeath(() -> {
1173                             synchronized (mThermalLock) {
1174                                 mThermalService = null;
1175                             }
1176                         }, /* flags */ 0);
1177                     } catch (RemoteException e) {
1178                         Slog.e(TAG, "linkToDeath with thermalService failed", e);
1179                         mThermalService = null;
1180                     }
1181                 }
1182             }
1183             return mThermalService;
1184         }
1185     }
1186 
getIKeystoreMetricsService()1187     private IKeystoreMetrics getIKeystoreMetricsService() {
1188         synchronized (mKeystoreLock) {
1189             if (mIKeystoreMetrics == null) {
1190                 mIKeystoreMetrics = IKeystoreMetrics.Stub.asInterface(
1191                         ServiceManager.getService("android.security.metrics"));
1192                 if (mIKeystoreMetrics != null) {
1193                     try {
1194                         mIKeystoreMetrics.asBinder().linkToDeath(() -> {
1195                             synchronized (mKeystoreLock) {
1196                                 mIKeystoreMetrics = null;
1197                             }
1198                         }, /* flags */ 0);
1199                     } catch (RemoteException e) {
1200                         Slog.e(TAG, "linkToDeath with IKeystoreMetrics failed", e);
1201                         mIKeystoreMetrics = null;
1202                     }
1203                 }
1204             }
1205             return mIKeystoreMetrics;
1206         }
1207     }
1208 
getIStoragedService()1209     private IStoraged getIStoragedService() {
1210         synchronized (mStoragedLock) {
1211             if (mStorageService == null) {
1212                 mStorageService = IStoraged.Stub.asInterface(
1213                         ServiceManager.getService("storaged"));
1214             }
1215             if (mStorageService != null) {
1216                 try {
1217                     mStorageService.asBinder().linkToDeath(() -> {
1218                         synchronized (mStoragedLock) {
1219                             mStorageService = null;
1220                         }
1221                     }, /* flags */ 0);
1222                 } catch (RemoteException e) {
1223                     Slog.e(TAG, "linkToDeath with storagedService failed", e);
1224                     mStorageService = null;
1225                 }
1226             }
1227         }
1228         return mStorageService;
1229     }
1230 
getINotificationManagerService()1231     private INotificationManager getINotificationManagerService() {
1232         synchronized (mNotificationStatsLock) {
1233             if (mNotificationManagerService == null) {
1234                 mNotificationManagerService = INotificationManager.Stub.asInterface(
1235                         ServiceManager.getService(Context.NOTIFICATION_SERVICE));
1236             }
1237             if (mNotificationManagerService != null) {
1238                 try {
1239                     mNotificationManagerService.asBinder().linkToDeath(() -> {
1240                         synchronized (mNotificationStatsLock) {
1241                             mNotificationManagerService = null;
1242                         }
1243                     }, /* flags */ 0);
1244                 } catch (RemoteException e) {
1245                     Slog.e(TAG, "linkToDeath with notificationManager failed", e);
1246                     mNotificationManagerService = null;
1247                 }
1248             }
1249         }
1250         return mNotificationManagerService;
1251     }
1252 
getIProcessStatsService()1253     private IProcessStats getIProcessStatsService() {
1254         synchronized (mProcStatsLock) {
1255             if (mProcessStatsService == null) {
1256                 mProcessStatsService = IProcessStats.Stub.asInterface(
1257                         ServiceManager.getService(ProcessStats.SERVICE_NAME));
1258             }
1259             if (mProcessStatsService != null) {
1260                 try {
1261                     mProcessStatsService.asBinder().linkToDeath(() -> {
1262                         synchronized (mProcStatsLock) {
1263                             mProcessStatsService = null;
1264                         }
1265                     }, /* flags */ 0);
1266                 } catch (RemoteException e) {
1267                     Slog.e(TAG, "linkToDeath with ProcessStats failed", e);
1268                     mProcessStatsService = null;
1269                 }
1270             }
1271         }
1272         return mProcessStatsService;
1273     }
1274 
registerWifiBytesTransfer()1275     private void registerWifiBytesTransfer() {
1276         int tagId = FrameworkStatsLog.WIFI_BYTES_TRANSFER;
1277         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1278                 .setAdditiveFields(new int[]{2, 3, 4, 5})
1279                 .build();
1280         mStatsManager.setPullAtomCallback(
1281                 tagId,
1282                 metadata,
1283                 DIRECT_EXECUTOR,
1284                 mStatsCallbackImpl
1285         );
1286     }
1287 
1288     @GuardedBy("mDataBytesTransferLock")
1289     @NonNull
collectNetworkStatsSnapshotForAtomLocked(int atomTag)1290     private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtomLocked(int atomTag) {
1291         List<NetworkStatsExt> ret = new ArrayList<>();
1292         switch (atomTag) {
1293             case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
1294                 final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked(
1295                         TRANSPORT_WIFI);
1296                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
1297                         new int[]{TRANSPORT_WIFI}, /*slicedByFgbg=*/false));
1298                 break;
1299             }
1300             case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
1301                 final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked(
1302                         TRANSPORT_WIFI);
1303                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
1304                         new int[]{TRANSPORT_WIFI}, /*slicedByFgbg=*/true));
1305                 break;
1306             }
1307             case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: {
1308                 final NetworkStats stats =
1309                         getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR);
1310                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
1311                         new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
1312                 break;
1313             }
1314             case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
1315                 final NetworkStats stats =
1316                         getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR);
1317                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
1318                         new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true));
1319                 break;
1320             }
1321             case FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG: {
1322                 final NetworkStats stats = getUidNetworkStatsSnapshotForTemplateLocked(
1323                         new NetworkTemplate.Builder(MATCH_PROXY).build(),  /*includeTags=*/false);
1324                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
1325                         new int[]{TRANSPORT_BLUETOOTH},
1326                         /*slicedByFgbg=*/true, /*slicedByTag=*/false,
1327                         /*slicedByMetered=*/false, TelephonyManager.NETWORK_TYPE_UNKNOWN,
1328                         /*subInfo=*/null, OEM_MANAGED_ALL, /*isTypeProxy=*/true));
1329                 break;
1330             }
1331             case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
1332                 final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplateLocked(
1333                         new NetworkTemplate.Builder(MATCH_WIFI).build(), /*includeTags=*/true);
1334                 final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplateLocked(
1335                         new NetworkTemplate.Builder(MATCH_MOBILE)
1336                                 .setMeteredness(METERED_YES).build(), /*includeTags=*/true);
1337                 final NetworkStats stats = wifiStats.add(cellularStats);
1338                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
1339                         new int[]{TRANSPORT_WIFI, TRANSPORT_CELLULAR},
1340                         /*slicedByFgbg=*/false, /*slicedByTag=*/true,
1341                         /*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN,
1342                         /*subInfo=*/null, OEM_MANAGED_ALL, /*isTypeProxy=*/false));
1343                 break;
1344             }
1345             case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: {
1346                 for (final SubInfo subInfo : mHistoricalSubs) {
1347                     ret.addAll(getDataUsageBytesTransferSnapshotForSubLocked(subInfo));
1348                 }
1349                 break;
1350             }
1351             case FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER: {
1352                 ret.addAll(getDataUsageBytesTransferSnapshotForOemManagedLocked());
1353                 break;
1354             }
1355             default:
1356                 throw new IllegalArgumentException("Unknown atomTag " + atomTag);
1357         }
1358         return ret;
1359     }
1360 
1361     @GuardedBy("mDataBytesTransferLock")
pullDataBytesTransferLocked(int atomTag, @NonNull List<StatsEvent> pulledData)1362     private int pullDataBytesTransferLocked(int atomTag, @NonNull List<StatsEvent> pulledData) {
1363         final List<NetworkStatsExt> current = collectNetworkStatsSnapshotForAtomLocked(atomTag);
1364 
1365         if (current == null) {
1366             Slog.e(TAG, "current snapshot is null for " + atomTag + ", return.");
1367             return StatsManager.PULL_SKIP;
1368         }
1369 
1370         for (final NetworkStatsExt item : current) {
1371             final NetworkStatsExt baseline = CollectionUtils.find(mNetworkStatsBaselines,
1372                     it -> it.hasSameSlicing(item));
1373 
1374             // No matched baseline indicates error has occurred during initialization stage,
1375             // skip reporting anything since the snapshot is invalid.
1376             if (baseline == null) {
1377                 Slog.e(TAG, "baseline is null for " + atomTag + ", return.");
1378                 return StatsManager.PULL_SKIP;
1379             }
1380 
1381             final NetworkStatsExt diff = new NetworkStatsExt(
1382                     removeEmptyEntries(item.stats.subtract(baseline.stats)), item.transports,
1383                     item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType,
1384                     item.subInfo, item.oemManaged, item.isTypeProxy);
1385 
1386             // If no diff, skip.
1387             if (!diff.stats.iterator().hasNext()) continue;
1388 
1389             switch (atomTag) {
1390                 case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
1391                     addBytesTransferByTagAndMeteredAtoms(diff, pulledData);
1392                     break;
1393                 case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
1394                     addDataUsageBytesTransferAtoms(diff, pulledData);
1395                     break;
1396                 case FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER:
1397                     addOemDataUsageBytesTransferAtoms(diff, pulledData);
1398                     break;
1399                 default:
1400                     addNetworkStats(atomTag, pulledData, diff);
1401             }
1402         }
1403         return StatsManager.PULL_SUCCESS;
1404     }
1405 
1406     @NonNull
removeEmptyEntries(NetworkStats stats)1407     private static NetworkStats removeEmptyEntries(NetworkStats stats) {
1408         final ArrayList<NetworkStats.Entry> entries = new ArrayList<>();
1409         for (NetworkStats.Entry e : stats) {
1410             if (e.getRxBytes() != 0 || e.getRxPackets() != 0 || e.getTxBytes() != 0
1411                     || e.getTxPackets() != 0 || e.getOperations() != 0) {
1412                 entries.add(e);
1413             }
1414         }
1415         if (isAddEntriesSupported()) {
1416             return new NetworkStats(0, entries.size()).addEntries(entries);
1417         } else {
1418             NetworkStats outputStats = new NetworkStats(0L, 1);
1419             for (NetworkStats.Entry e : entries) {
1420                 outputStats = outputStats.addEntry(e);
1421             }
1422             return outputStats;
1423         }
1424     }
1425 
addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStatsExt statsExt)1426     private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret,
1427             @NonNull NetworkStatsExt statsExt) {
1428         for (NetworkStats.Entry entry : statsExt.stats) {
1429             StatsEvent statsEvent;
1430             if (statsExt.slicedByFgbg) {
1431                 // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom.
1432                 statsEvent = FrameworkStatsLog.buildStatsEvent(
1433                         atomTag, entry.getUid(),
1434                         (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(),
1435                         entry.getTxBytes(), entry.getTxPackets());
1436             } else {
1437                 // MobileBytesTransfer atom or WifiBytesTransfer atom.
1438                 statsEvent = FrameworkStatsLog.buildStatsEvent(
1439                         atomTag, entry.getUid(), entry.getRxBytes(),
1440                         entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets());
1441             }
1442             ret.add(statsEvent);
1443         }
1444     }
1445 
addBytesTransferByTagAndMeteredAtoms(@onNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData)1446     private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt,
1447             @NonNull List<StatsEvent> pulledData) {
1448         // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
1449         // 5G NSA mode means the primary cell is LTE with a secondary connection to an
1450         // NR cell. To mitigate risk, NetworkStats is currently storing this state as
1451         // a fake RAT type rather than storing the boolean separately.
1452         final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA;
1453 
1454         for (NetworkStats.Entry entry : statsExt.stats) {
1455             pulledData.add(FrameworkStatsLog.buildStatsEvent(
1456                     FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(),
1457                     entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(),
1458                     entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(),
1459                     entry.getTxPackets(),
1460                     is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType));
1461         }
1462     }
1463 
addDataUsageBytesTransferAtoms(@onNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData)1464     private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
1465             @NonNull List<StatsEvent> pulledData) {
1466 
1467         // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
1468         // 5G NSA mode means the primary cell is LTE with a secondary connection to an
1469         // NR cell. To mitigate risk, NetworkStats is currently storing this state as
1470         // a fake RAT type rather than storing the boolean separately.
1471         final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA;
1472         // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with.
1473         final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR;
1474 
1475         for (NetworkStats.Entry entry : statsExt.stats) {
1476             pulledData.add(FrameworkStatsLog.buildStatsEvent(
1477                     FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER,
1478                     entry.getSet(), entry.getRxBytes(), entry.getRxPackets(),
1479                     entry.getTxBytes(), entry.getTxPackets(),
1480                     is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType,
1481                     // Fill information about subscription, these cannot be null since invalid data
1482                     // would be filtered when adding into subInfo list.
1483                     statsExt.subInfo.mcc, statsExt.subInfo.mnc, statsExt.subInfo.carrierId,
1484                     statsExt.subInfo.isOpportunistic
1485                             ? DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC
1486                             : DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC,
1487                     isNR));
1488         }
1489     }
1490 
addOemDataUsageBytesTransferAtoms(@onNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData)1491     private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
1492             @NonNull List<StatsEvent> pulledData) {
1493         final int oemManaged = statsExt.oemManaged;
1494         for (final int transport : statsExt.transports) {
1495             for (NetworkStats.Entry entry : statsExt.stats) {
1496                 pulledData.add(FrameworkStatsLog.buildStatsEvent(
1497                         FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(),
1498                         (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(),
1499                         entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()));
1500             }
1501         }
1502     }
1503 
1504     @GuardedBy("mDataBytesTransferLock")
1505     @NonNull
getDataUsageBytesTransferSnapshotForOemManagedLocked()1506     private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManagedLocked() {
1507         final List<Pair<Integer, Integer>> matchRulesAndTransports = List.of(
1508                 new Pair(MATCH_ETHERNET, TRANSPORT_ETHERNET),
1509                 new Pair(MATCH_MOBILE, TRANSPORT_CELLULAR),
1510                 new Pair(MATCH_WIFI, TRANSPORT_WIFI)
1511         );
1512         final int[] oemManagedTypes = new int[]{OEM_MANAGED_PAID | OEM_MANAGED_PRIVATE,
1513                 OEM_MANAGED_PAID, OEM_MANAGED_PRIVATE};
1514 
1515         final List<NetworkStatsExt> ret = new ArrayList<>();
1516 
1517         for (Pair<Integer, Integer> ruleAndTransport : matchRulesAndTransports) {
1518             final Integer matchRule = ruleAndTransport.first;
1519             for (final int oemManaged : oemManagedTypes) {
1520                 // Subscriber Ids and Wifi Network Keys will not be set since the purpose is to
1521                 // slice statistics of different OEM managed networks among all network types.
1522                 // Thus, specifying networks through their identifiers are not needed.
1523                 final NetworkTemplate template = new NetworkTemplate.Builder(matchRule)
1524                         .setOemManaged(oemManaged).build();
1525                 final NetworkStats stats = getUidNetworkStatsSnapshotForTemplateLocked(
1526                         template, false);
1527                 final Integer transport = ruleAndTransport.second;
1528                 ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
1529                         new int[]{transport}, /*slicedByFgbg=*/true, /*slicedByTag=*/false,
1530                         /*slicedByMetered=*/false, TelephonyManager.NETWORK_TYPE_UNKNOWN,
1531                         /*subInfo=*/null, oemManaged, /*isTypeProxy=*/false));
1532             }
1533         }
1534 
1535         return ret;
1536     }
1537 
1538     /**
1539      * Create a snapshot of NetworkStats for a given transport.
1540      */
1541     @GuardedBy("mDataBytesTransferLock")
1542     @NonNull
getUidNetworkStatsSnapshotForTransportLocked(int transport)1543     private NetworkStats getUidNetworkStatsSnapshotForTransportLocked(int transport) {
1544         NetworkTemplate template = null;
1545         switch (transport) {
1546             case TRANSPORT_CELLULAR:
1547                 template = new NetworkTemplate.Builder(MATCH_MOBILE)
1548                         .setMeteredness(METERED_YES).build();
1549                 break;
1550             case TRANSPORT_WIFI:
1551                 template = new NetworkTemplate.Builder(MATCH_WIFI).build();
1552                 break;
1553             default:
1554                 Log.wtf(TAG, "Unexpected transport.");
1555         }
1556         return getUidNetworkStatsSnapshotForTemplateLocked(template, /*includeTags=*/false);
1557     }
1558 
1559     /**
1560      * Check if it is possible to query NetworkStats for TYPE_PROXY. This should only be possible
1561      * if the build includes r.android.com/2828315
1562      * @return true if querying for TYPE_PROXY is allowed
1563      */
canQueryNetworkStatsForTypeProxy()1564     private static boolean canQueryNetworkStatsForTypeProxy() {
1565         try {
1566             new NetworkTemplate.Builder(MATCH_PROXY).build();
1567             return true;
1568         } catch (IllegalArgumentException e) {
1569             Slog.w(TAG, "Querying network stats for TYPE_PROXY is not allowed");
1570             return false;
1571         }
1572     }
1573 
1574     /**
1575      * Create a snapshot of NetworkStats since boot for the given template, but add 1 bucket
1576      * duration before boot as a buffer to ensure at least one full bucket will be included.
1577      * Note that this should be only used to calculate diff since the snapshot might contains
1578      * some traffic before boot.
1579      */
1580     @GuardedBy("mDataBytesTransferLock")
1581     @NonNull
getUidNetworkStatsSnapshotForTemplateLocked( @onNull NetworkTemplate template, boolean includeTags)1582     private NetworkStats getUidNetworkStatsSnapshotForTemplateLocked(
1583             @NonNull NetworkTemplate template, boolean includeTags) {
1584         final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime();
1585         final long currentTimeMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
1586         final long bootTimeMillis = currentTimeMillis - elapsedMillisSinceBoot;
1587         final long bucketDurationMillis = Settings.Global.getLong(mContext.getContentResolver(),
1588                 NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS);
1589 
1590         if (accumulateNetworkStatsSinceBoot()) {
1591             NetworkStatsAccumulator accumulator = CollectionUtils.find(
1592                     mNetworkStatsAccumulators, it -> it.hasEqualParameters(template, includeTags));
1593             if (accumulator == null) {
1594                 accumulator = new NetworkStatsAccumulator(
1595                         template,
1596                         includeTags,
1597                         bucketDurationMillis,
1598                         bootTimeMillis - bucketDurationMillis);
1599                 mNetworkStatsAccumulators.add(accumulator);
1600             }
1601 
1602             return accumulator.queryStats(currentTimeMillis,
1603                     (aTemplate, aIncludeTags, aStartTime, aEndTime) -> {
1604                         synchronized (mDataBytesTransferLock) {
1605                             return getUidNetworkStatsSnapshotForTemplateLocked(aTemplate,
1606                                     aIncludeTags, aStartTime, aEndTime);
1607                         }
1608                     });
1609 
1610         } else {
1611             // Set end time in the future to include all stats in the active bucket.
1612             return getUidNetworkStatsSnapshotForTemplateLocked(
1613                     template, includeTags,
1614                     bootTimeMillis - bucketDurationMillis,
1615                     currentTimeMillis + bucketDurationMillis);
1616         }
1617     }
1618 
1619     @GuardedBy("mDataBytesTransferLock")
1620     @NonNull
1621     private NetworkStats getUidNetworkStatsSnapshotForTemplateLocked(
1622             @NonNull NetworkTemplate template, boolean includeTags, long startTime, long endTime) {
1623         final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime();
1624         if (applyNetworkStatsPollRateLimit()) {
1625             // The new way: rate-limit force-polling for all NetworkStats queries
1626             if (elapsedMillisSinceBoot - mLastNetworkStatsPollTime >= NETSTATS_POLL_RATE_LIMIT_MS) {
1627                 mLastNetworkStatsPollTime = elapsedMillisSinceBoot;
1628                 getNetworkStatsManager().forceUpdate();
1629             }
1630         } else {
1631             // The old way: force-poll only on WiFi queries. Data for other queries can be stale
1632             // if there was no recent poll beforehand (e.g. for WiFi or scheduled poll)
1633             if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) {
1634                 getNetworkStatsManager().forceUpdate();
1635             }
1636         }
1637 
1638         final android.app.usage.NetworkStats queryNonTaggedStats =
1639                 getNetworkStatsManager().querySummary(template, startTime, endTime);
1640 
1641         final NetworkStats nonTaggedStats =
1642                 fromPublicNetworkStats(queryNonTaggedStats);
1643         queryNonTaggedStats.close();
1644         if (!includeTags) return nonTaggedStats;
1645 
1646         final android.app.usage.NetworkStats queryTaggedStats =
1647                 getNetworkStatsManager().queryTaggedSummary(template, startTime, endTime);
1648         final NetworkStats taggedStats =
1649                 fromPublicNetworkStats(queryTaggedStats);
1650         queryTaggedStats.close();
1651         return nonTaggedStats.add(taggedStats);
1652     }
1653 
1654     @GuardedBy("mDataBytesTransferLock")
1655     @NonNull
1656     private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSubLocked(
1657             @NonNull SubInfo subInfo) {
1658         final List<NetworkStatsExt> ret = new ArrayList<>();
1659         for (final int ratType : getAllCollapsedRatTypes()) {
1660             final NetworkTemplate template =
1661                     new NetworkTemplate.Builder(MATCH_MOBILE)
1662                             .setSubscriberIds(Set.of(subInfo.subscriberId))
1663                             .setRatType(ratType)
1664                             .setMeteredness(METERED_YES).build();
1665             final NetworkStats stats =
1666                     getUidNetworkStatsSnapshotForTemplateLocked(template, /*includeTags=*/false);
1667             ret.add(new NetworkStatsExt(sliceNetworkStatsByFgbg(stats),
1668                     new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true,
1669                     /*slicedByTag=*/false, /*slicedByMetered=*/false, ratType, subInfo,
1670                     OEM_MANAGED_ALL, /*isTypeProxy=*/false));
1671         }
1672         return ret;
1673     }
1674 
1675     /**
1676      * Return all supported collapsed RAT types that could be returned by
1677      * {@link android.app.usage.NetworkStatsManager#getCollapsedRatType(int)}.
1678      */
1679     @NonNull
1680     private static int[] getAllCollapsedRatTypes() {
1681         final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
1682         final HashSet<Integer> collapsedRatTypes = new HashSet<>();
1683         for (final int ratType : ratTypes) {
1684             collapsedRatTypes.add(NetworkStatsManager.getCollapsedRatType(ratType));
1685         }
1686         // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
1687         // it is not in TelephonyManager#NETWORK_TYPE_* constants.
1688         // See {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
1689         collapsedRatTypes.add(
1690                 NetworkStatsManager.getCollapsedRatType(NetworkStatsManager.NETWORK_TYPE_5G_NSA));
1691         // Ensure that unknown type is returned.
1692         collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
1693         return com.android.net.module.util.CollectionUtils.toIntArray(collapsedRatTypes);
1694     }
1695 
1696     @NonNull
1697     private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) {
1698         return sliceNetworkStats(stats,
1699                 (entry) -> {
1700                     return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
1701                             NetworkStats.SET_ALL, NetworkStats.TAG_NONE,
1702                             NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
1703                             NetworkStats.DEFAULT_NETWORK_ALL,
1704                             entry.getRxBytes(), entry.getRxPackets(),
1705                             entry.getTxBytes(), entry.getTxPackets(), 0);
1706                 });
1707     }
1708 
1709     @NonNull
1710     private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) {
1711         return sliceNetworkStats(stats,
1712                 (entry) -> {
1713                     return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL,
1714                             entry.getSet(), NetworkStats.TAG_NONE,
1715                             NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
1716                             NetworkStats.DEFAULT_NETWORK_ALL,
1717                             entry.getRxBytes(), entry.getRxPackets(),
1718                             entry.getTxBytes(), entry.getTxPackets(), 0);
1719                 });
1720     }
1721 
1722     @NonNull
1723     private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
1724         return sliceNetworkStats(stats,
1725                 (entry) -> {
1726                     return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
1727                             entry.getSet(), NetworkStats.TAG_NONE,
1728                             NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
1729                             NetworkStats.DEFAULT_NETWORK_ALL,
1730                             entry.getRxBytes(), entry.getRxPackets(),
1731                             entry.getTxBytes(), entry.getTxPackets(), 0);
1732                 });
1733     }
1734 
1735     @NonNull
1736     private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) {
1737         return sliceNetworkStats(stats,
1738                 (entry) -> {
1739                     return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
1740                             NetworkStats.SET_ALL, entry.getTag(),
1741                             entry.getMetered(), NetworkStats.ROAMING_ALL,
1742                             NetworkStats.DEFAULT_NETWORK_ALL,
1743                             entry.getRxBytes(), entry.getRxPackets(),
1744                             entry.getTxBytes(), entry.getTxPackets(), 0);
1745                 });
1746     }
1747 
1748     /**
1749      * Slices NetworkStats along the dimensions specified in the slicer lambda and aggregates over
1750      * non-sliced dimensions.
1751      *
1752      * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the
1753      * default state (with the presumption that we don't want to slice on anything), and then
1754      * applies the slicer lambda to allow users to control which dimensions to slice on.
1755      *
1756      * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to
1757      *               get the state from entry to replace the default value.
1758      *               This is useful for slicing by particular dimensions. For example, if we wished
1759      *               to slice by uid and tag, we could write the following lambda:
1760      *               (entry) -> {
1761      *               return new NetworkStats.Entry(null, entry.getUid(),
1762      *               NetworkStats.SET_ALL, entry.getTag(),
1763      *               NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
1764      *               NetworkStats.DEFAULT_NETWORK_ALL,
1765      *               entry.getRxBytes(), entry.getRxPackets(),
1766      *               entry.getTxBytes(), entry.getTxPackets(), 0);
1767      *               }
1768      * @return new NeworkStats object appropriately sliced
1769      */
1770     @NonNull
1771     private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats,
1772             @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) {
1773         final ArrayList<NetworkStats.Entry> entries = new ArrayList();
1774         for (NetworkStats.Entry e : stats) {
1775             entries.add(slicer.apply(e));
1776         }
1777         if (isAddEntriesSupported()) {
1778             return new NetworkStats(0, entries.size()).addEntries(entries);
1779         } else {
1780             NetworkStats outputStats = new NetworkStats(0L, 1);
1781             for (NetworkStats.Entry e : entries) {
1782                 outputStats = outputStats.addEntry(e);
1783             }
1784             return outputStats;
1785         }
1786     }
1787 
1788     private void registerWifiBytesTransferBackground() {
1789         int tagId = FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG;
1790         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1791                 .setAdditiveFields(new int[]{3, 4, 5, 6})
1792                 .build();
1793         mStatsManager.setPullAtomCallback(
1794                 tagId,
1795                 metadata,
1796                 DIRECT_EXECUTOR,
1797                 mStatsCallbackImpl
1798         );
1799     }
1800 
1801     private void registerMobileBytesTransfer() {
1802         int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER;
1803         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1804                 .setAdditiveFields(new int[]{2, 3, 4, 5})
1805                 .build();
1806         mStatsManager.setPullAtomCallback(
1807                 tagId,
1808                 metadata,
1809                 DIRECT_EXECUTOR,
1810                 mStatsCallbackImpl
1811         );
1812     }
1813 
1814     private void registerMobileBytesTransferBackground() {
1815         int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG;
1816         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1817                 .setAdditiveFields(new int[]{3, 4, 5, 6})
1818                 .build();
1819         mStatsManager.setPullAtomCallback(
1820                 tagId,
1821                 metadata,
1822                 DIRECT_EXECUTOR,
1823                 mStatsCallbackImpl
1824         );
1825     }
1826 
1827     private void registerProxyBytesTransferBackground() {
1828         int tagId = FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG;
1829         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1830                 .setAdditiveFields(new int[]{3, 4, 5, 6})
1831                 .build();
1832         mStatsManager.setPullAtomCallback(
1833                 tagId,
1834                 metadata,
1835                 DIRECT_EXECUTOR,
1836                 mStatsCallbackImpl
1837         );
1838     }
1839 
1840     private void registerBytesTransferByTagAndMetered() {
1841         int tagId = FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED;
1842         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1843                 .setAdditiveFields(new int[]{4, 5, 6, 7})
1844                 .build();
1845         mStatsManager.setPullAtomCallback(
1846                 tagId,
1847                 metadata,
1848                 DIRECT_EXECUTOR,
1849                 mStatsCallbackImpl
1850         );
1851     }
1852 
1853     private void registerDataUsageBytesTransfer() {
1854         int tagId = FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER;
1855         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1856                 .setAdditiveFields(new int[]{2, 3, 4, 5})
1857                 .build();
1858         mStatsManager.setPullAtomCallback(
1859                 tagId,
1860                 metadata,
1861                 DIRECT_EXECUTOR,
1862                 mStatsCallbackImpl
1863         );
1864     }
1865 
1866     private void registerOemManagedBytesTransfer() {
1867         int tagId = FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER;
1868         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1869                 .setAdditiveFields(new int[]{5, 6, 7, 8})
1870                 .build();
1871         mStatsManager.setPullAtomCallback(
1872                 tagId,
1873                 metadata,
1874                 DIRECT_EXECUTOR,
1875                 mStatsCallbackImpl
1876         );
1877     }
1878 
1879     private void registerBluetoothBytesTransfer() {
1880         int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER;
1881         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1882                 .setAdditiveFields(new int[]{2, 3})
1883                 .build();
1884         mStatsManager.setPullAtomCallback(
1885                 tagId,
1886                 metadata,
1887                 DIRECT_EXECUTOR,
1888                 mStatsCallbackImpl
1889         );
1890     }
1891 
1892     /**
1893      * Helper method to extract the Parcelable controller info from a
1894      * SynchronousResultReceiver.
1895      */
1896     private static <T extends Parcelable> T awaitControllerInfo(
1897             @Nullable SynchronousResultReceiver receiver) {
1898         if (receiver == null) {
1899             return null;
1900         }
1901 
1902         try {
1903             final SynchronousResultReceiver.Result result =
1904                     receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
1905             if (result.bundle != null) {
1906                 // This is the final destination for the Bundle.
1907                 result.bundle.setDefusable(true);
1908 
1909                 final T data = result.bundle.getParcelable(RESULT_RECEIVER_CONTROLLER_KEY);
1910                 if (data != null) {
1911                     return data;
1912                 }
1913             }
1914         } catch (TimeoutException e) {
1915             Slog.w(TAG, "timeout reading " + receiver.getName() + " stats");
1916         }
1917         return null;
1918     }
1919 
1920     private BluetoothActivityEnergyInfo fetchBluetoothData() {
1921         final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
1922         if (adapter != null) {
1923             SynchronousResultReceiver bluetoothReceiver =
1924                     new SynchronousResultReceiver("bluetooth");
1925             adapter.requestControllerActivityEnergyInfo(
1926                     Runnable::run,
1927                     new BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback() {
1928                         @Override
1929                         public void onBluetoothActivityEnergyInfoAvailable(
1930                                 BluetoothActivityEnergyInfo info) {
1931                             Bundle bundle = new Bundle();
1932                             bundle.putParcelable(
1933                                     BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, info);
1934                             bluetoothReceiver.send(0, bundle);
1935                         }
1936 
1937                         @Override
1938                         public void onBluetoothActivityEnergyInfoError(int errorCode) {
1939                             Slog.w(TAG, "error reading Bluetooth stats: " + errorCode);
1940                             Bundle bundle = new Bundle();
1941                             bundle.putParcelable(
1942                                     BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, null);
1943                             bluetoothReceiver.send(0, bundle);
1944                         }
1945                     }
1946             );
1947             return awaitControllerInfo(bluetoothReceiver);
1948         } else {
1949             Slog.e(TAG, "Failed to get bluetooth adapter!");
1950             return null;
1951         }
1952     }
1953 
1954     int pullBluetoothBytesTransferLocked(int atomTag, List<StatsEvent> pulledData) {
1955         BluetoothActivityEnergyInfo info = fetchBluetoothData();
1956         if (info == null) {
1957             return StatsManager.PULL_SKIP;
1958         }
1959         for (UidTraffic traffic : info.getUidTraffic()) {
1960             pulledData.add(FrameworkStatsLog.buildStatsEvent(
1961                     atomTag, traffic.getUid(), traffic.getRxBytes(), traffic.getTxBytes()));
1962         }
1963         return StatsManager.PULL_SUCCESS;
1964     }
1965 
1966     private void registerKernelWakelock() {
1967         int tagId = FrameworkStatsLog.KERNEL_WAKELOCK;
1968         mStatsManager.setPullAtomCallback(
1969                 tagId,
1970                 /* PullAtomMetadata */ null,
1971                 DIRECT_EXECUTOR,
1972                 mStatsCallbackImpl
1973         );
1974     }
1975 
1976     int pullKernelWakelockLocked(int atomTag, List<StatsEvent> pulledData) {
1977         final KernelWakelockStats wakelockStats =
1978                 mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
1979         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
1980             String name = ent.getKey();
1981             KernelWakelockStats.Entry kws = ent.getValue();
1982             pulledData.add(FrameworkStatsLog.buildStatsEvent(
1983                     atomTag, name, kws.count, kws.version, kws.totalTimeUs));
1984         }
1985         return StatsManager.PULL_SUCCESS;
1986     }
1987 
1988     private void registerCpuTimePerClusterFreq() {
1989         if (KernelCpuBpfTracking.isSupported()) {
1990             int tagId = FrameworkStatsLog.CPU_TIME_PER_CLUSTER_FREQ;
1991             PullAtomMetadata metadata = new PullAtomMetadata.Builder()
1992                     .setAdditiveFields(new int[]{3})
1993                     .build();
1994             mStatsManager.setPullAtomCallback(
1995                     tagId,
1996                     metadata,
1997                     DIRECT_EXECUTOR,
1998                     mStatsCallbackImpl
1999             );
2000         }
2001     }
2002 
2003     int pullCpuTimePerClusterFreqLocked(int atomTag, List<StatsEvent> pulledData) {
2004         int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
2005         long[] freqs = KernelCpuBpfTracking.getFreqs();
2006         long[] timesMs = KernelCpuTotalBpfMapReader.read();
2007         if (timesMs == null) {
2008             return StatsManager.PULL_SKIP;
2009         }
2010         for (int freqIndex = 0; freqIndex < timesMs.length; ++freqIndex) {
2011             int cluster = freqsClusters[freqIndex];
2012             int freq = (int) freqs[freqIndex];
2013             long timeMs = timesMs[freqIndex];
2014             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
2015         }
2016         return StatsManager.PULL_SUCCESS;
2017     }
2018 
2019     private void registerCpuTimePerUid() {
2020         int tagId = FrameworkStatsLog.CPU_TIME_PER_UID;
2021         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2022                 .setAdditiveFields(new int[]{2, 3})
2023                 .build();
2024         mStatsManager.setPullAtomCallback(
2025                 tagId,
2026                 metadata,
2027                 DIRECT_EXECUTOR,
2028                 mStatsCallbackImpl
2029         );
2030     }
2031 
2032     int pullCpuTimePerUidLocked(int atomTag, List<StatsEvent> pulledData) {
2033         mCpuUidUserSysTimeReader.readAbsolute((uid, timesUs) -> {
2034             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
2035             pulledData.add(
2036                     FrameworkStatsLog.buildStatsEvent(atomTag, uid, userTimeUs, systemTimeUs));
2037         });
2038         return StatsManager.PULL_SUCCESS;
2039     }
2040 
2041     private void registerCpuCyclesPerUidCluster() {
2042         // If eBPF tracking is not support, the procfs fallback is used if the kernel knows about
2043         // CPU frequencies.
2044         if (KernelCpuBpfTracking.isSupported() || KernelCpuBpfTracking.getClusters() > 0) {
2045             int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
2046             PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2047                     .setAdditiveFields(new int[]{3, 4, 5})
2048                     .build();
2049             mStatsManager.setPullAtomCallback(
2050                     tagId,
2051                     metadata,
2052                     DIRECT_EXECUTOR,
2053                     mStatsCallbackImpl
2054             );
2055         }
2056     }
2057 
2058     int pullCpuCyclesPerUidClusterLocked(int atomTag, List<StatsEvent> pulledData) {
2059         PowerProfile powerProfile = new PowerProfile(mContext);
2060         int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
2061         int clusters = KernelCpuBpfTracking.getClusters();
2062         long[] freqs = KernelCpuBpfTracking.getFreqs();
2063         double[] freqsPowers = new double[freqs.length];
2064         // Initialize frequency power mapping.
2065         {
2066             int freqClusterIndex = 0;
2067             int lastCluster = -1;
2068             for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex, ++freqClusterIndex) {
2069                 int cluster = freqsClusters[freqIndex];
2070                 if (cluster != lastCluster) {
2071                     freqClusterIndex = 0;
2072                 }
2073                 lastCluster = cluster;
2074 
2075                 freqsPowers[freqIndex] =
2076                         powerProfile.getAveragePowerForCpuCore(cluster, freqClusterIndex);
2077             }
2078         }
2079 
2080         // Aggregate 0: mcycles, 1: runtime ms, 2: power profile estimate for the same uids for
2081         // each cluster.
2082         SparseArray<double[]> aggregated = new SparseArray<>();
2083         mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
2084             if (UserHandle.isIsolated(uid)) {
2085                 // Skip individual isolated uids because they are recycled and quickly removed from
2086                 // the underlying data source.
2087                 return;
2088             } else if (UserHandle.isSharedAppGid(uid)) {
2089                 // All shared app gids are accounted together.
2090                 uid = LAST_SHARED_APPLICATION_GID;
2091             } else {
2092                 // Everything else is accounted under their base uid.
2093                 uid = UserHandle.getAppId(uid);
2094             }
2095 
2096             double[] values = aggregated.get(uid);
2097             if (values == null) {
2098                 values = new double[clusters * CPU_CYCLES_PER_UID_CLUSTER_VALUES];
2099                 aggregated.put(uid, values);
2100             }
2101 
2102             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
2103                 int cluster = freqsClusters[freqIndex];
2104                 long timeMs = cpuFreqTimeMs[freqIndex];
2105                 values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES] += freqs[freqIndex] * timeMs;
2106                 values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 1] += timeMs;
2107                 values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 2] +=
2108                         freqsPowers[freqIndex] * timeMs;
2109             }
2110         });
2111 
2112         int size = aggregated.size();
2113         for (int i = 0; i < size; ++i) {
2114             int uid = aggregated.keyAt(i);
2115             double[] values = aggregated.valueAt(i);
2116             for (int cluster = 0; cluster < clusters; ++cluster) {
2117                 pulledData.add(FrameworkStatsLog.buildStatsEvent(
2118                         atomTag, uid, cluster,
2119                         (long) (values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES] / 1e6),
2120                         (long) values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 1],
2121                         (long) (values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 2] / 1e3)));
2122             }
2123         }
2124         return StatsManager.PULL_SUCCESS;
2125     }
2126 
2127     private void registerCpuTimePerUidFreq() {
2128         // the throttling is 3sec, handled in
2129         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
2130         int tagId = FrameworkStatsLog.CPU_TIME_PER_UID_FREQ;
2131         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2132                 .setAdditiveFields(new int[]{3})
2133                 .build();
2134         mStatsManager.setPullAtomCallback(
2135                 tagId,
2136                 metadata,
2137                 DIRECT_EXECUTOR,
2138                 mStatsCallbackImpl
2139         );
2140     }
2141 
2142     int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
2143         // Aggregate times for the same uids.
2144         SparseArray<long[]> aggregated = new SparseArray<>();
2145         mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
2146             if (UserHandle.isIsolated(uid)) {
2147                 // Skip individual isolated uids because they are recycled and quickly removed from
2148                 // the underlying data source.
2149                 return;
2150             } else if (UserHandle.isSharedAppGid(uid)) {
2151                 // All shared app gids are accounted together.
2152                 uid = LAST_SHARED_APPLICATION_GID;
2153             } else {
2154                 // Everything else is accounted under their base uid.
2155                 uid = UserHandle.getAppId(uid);
2156             }
2157 
2158             long[] aggCpuFreqTimeMs = aggregated.get(uid);
2159             if (aggCpuFreqTimeMs == null) {
2160                 aggCpuFreqTimeMs = new long[cpuFreqTimeMs.length];
2161                 aggregated.put(uid, aggCpuFreqTimeMs);
2162             }
2163             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
2164                 aggCpuFreqTimeMs[freqIndex] += cpuFreqTimeMs[freqIndex];
2165             }
2166         });
2167 
2168         int size = aggregated.size();
2169         for (int i = 0; i < size; ++i) {
2170             int uid = aggregated.keyAt(i);
2171             long[] aggCpuFreqTimeMs = aggregated.valueAt(i);
2172             for (int freqIndex = 0; freqIndex < aggCpuFreqTimeMs.length; ++freqIndex) {
2173                 if (aggCpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
2174                     pulledData.add(FrameworkStatsLog.buildStatsEvent(
2175                             atomTag, uid, freqIndex, aggCpuFreqTimeMs[freqIndex]));
2176                 }
2177             }
2178         }
2179         return StatsManager.PULL_SUCCESS;
2180     }
2181 
2182     private void registerCpuCyclesPerThreadGroupCluster() {
2183         if (KernelCpuBpfTracking.isSupported()
2184                 && !com.android.server.power.optimization.Flags.disableSystemServicePowerAttr()) {
2185             int tagId = FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER;
2186             PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2187                     .setAdditiveFields(new int[]{3, 4})
2188                     .build();
2189             mStatsManager.setPullAtomCallback(
2190                     tagId,
2191                     metadata,
2192                     DIRECT_EXECUTOR,
2193                     mStatsCallbackImpl
2194             );
2195         }
2196     }
2197 
2198     int pullCpuCyclesPerThreadGroupCluster(int atomTag, List<StatsEvent> pulledData) {
2199         if (com.android.server.power.optimization.Flags.disableSystemServicePowerAttr()) {
2200             return StatsManager.PULL_SKIP;
2201         }
2202 
2203         SystemServiceCpuThreadTimes times = LocalServices.getService(BatteryStatsInternal.class)
2204                 .getSystemServiceCpuThreadTimes();
2205         if (times == null) {
2206             return StatsManager.PULL_SKIP;
2207         }
2208 
2209         addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
2210                 FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER,
2211                 times.threadCpuTimesUs);
2212         addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
2213                 FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER_BINDER,
2214                 times.binderThreadCpuTimesUs);
2215 
2216         ProcessCpuUsage surfaceFlingerTimes = mSurfaceFlingerProcessCpuThreadReader.readAbsolute();
2217         if (surfaceFlingerTimes != null && surfaceFlingerTimes.threadCpuTimesMillis != null) {
2218             long[] surfaceFlingerTimesUs =
2219                     new long[surfaceFlingerTimes.threadCpuTimesMillis.length];
2220             for (int i = 0; i < surfaceFlingerTimesUs.length; ++i) {
2221                 surfaceFlingerTimesUs[i] = surfaceFlingerTimes.threadCpuTimesMillis[i] * 1_000;
2222             }
2223             addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
2224                     FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SURFACE_FLINGER,
2225                     surfaceFlingerTimesUs);
2226         }
2227 
2228         return StatsManager.PULL_SUCCESS;
2229     }
2230 
2231     private static void addCpuCyclesPerThreadGroupClusterAtoms(
2232             int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs) {
2233         int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
2234         int clusters = KernelCpuBpfTracking.getClusters();
2235         long[] freqs = KernelCpuBpfTracking.getFreqs();
2236         long[] aggregatedCycles = new long[clusters];
2237         long[] aggregatedTimesUs = new long[clusters];
2238         for (int i = 0; i < cpuTimesUs.length; ++i) {
2239             aggregatedCycles[freqsClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
2240             aggregatedTimesUs[freqsClusters[i]] += cpuTimesUs[i];
2241         }
2242         for (int cluster = 0; cluster < clusters; ++cluster) {
2243             pulledData.add(FrameworkStatsLog.buildStatsEvent(
2244                     atomTag, threadGroup, cluster, aggregatedCycles[cluster] / 1_000_000L,
2245                     aggregatedTimesUs[cluster] / 1_000));
2246         }
2247     }
2248 
2249     private void registerCpuActiveTime() {
2250         // the throttling is 3sec, handled in
2251         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
2252         int tagId = FrameworkStatsLog.CPU_ACTIVE_TIME;
2253         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2254                 .setAdditiveFields(new int[]{2})
2255                 .build();
2256         mStatsManager.setPullAtomCallback(
2257                 tagId,
2258                 metadata,
2259                 DIRECT_EXECUTOR,
2260                 mStatsCallbackImpl
2261         );
2262     }
2263 
2264     int pullCpuActiveTimeLocked(int atomTag, List<StatsEvent> pulledData) {
2265         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
2266             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, uid, cpuActiveTimesMs));
2267         });
2268         return StatsManager.PULL_SUCCESS;
2269     }
2270 
2271     private void registerCpuClusterTime() {
2272         // the throttling is 3sec, handled in
2273         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
2274         int tagId = FrameworkStatsLog.CPU_CLUSTER_TIME;
2275         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2276                 .setAdditiveFields(new int[]{3})
2277                 .build();
2278         mStatsManager.setPullAtomCallback(
2279                 tagId,
2280                 metadata,
2281                 DIRECT_EXECUTOR,
2282                 mStatsCallbackImpl
2283         );
2284     }
2285 
2286     int pullCpuClusterTimeLocked(int atomTag, List<StatsEvent> pulledData) {
2287         mCpuUidClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
2288             for (int i = 0; i < cpuClusterTimesMs.length; i++) {
2289                 pulledData.add(
2290                         FrameworkStatsLog.buildStatsEvent(atomTag, uid, i, cpuClusterTimesMs[i]));
2291             }
2292         });
2293         return StatsManager.PULL_SUCCESS;
2294     }
2295 
2296     private void registerWifiActivityInfo() {
2297         int tagId = FrameworkStatsLog.WIFI_ACTIVITY_INFO;
2298         mStatsManager.setPullAtomCallback(
2299                 tagId,
2300                 null, // use default PullAtomMetadata values
2301                 DIRECT_EXECUTOR,
2302                 mStatsCallbackImpl
2303         );
2304     }
2305 
2306     int pullWifiActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
2307         final long token = Binder.clearCallingIdentity();
2308         try {
2309             SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
2310             mWifiManager.getWifiActivityEnergyInfoAsync(
2311                     new Executor() {
2312                         @Override
2313                         public void execute(Runnable runnable) {
2314                             // run the listener on the binder thread, if it was run on the main
2315                             // thread it would deadlock since we would be waiting on ourselves
2316                             runnable.run();
2317                         }
2318                     },
2319                     info -> {
2320                         Bundle bundle = new Bundle();
2321                         bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, info);
2322                         wifiReceiver.send(0, bundle);
2323                     }
2324             );
2325             final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
2326             if (wifiInfo == null) {
2327                 return StatsManager.PULL_SKIP;
2328             }
2329             pulledData.add(
2330                     FrameworkStatsLog.buildStatsEvent(atomTag, wifiInfo.getTimeSinceBootMillis(),
2331                             wifiInfo.getStackState(), wifiInfo.getControllerTxDurationMillis(),
2332                             wifiInfo.getControllerRxDurationMillis(),
2333                             wifiInfo.getControllerIdleDurationMillis(),
2334                             wifiInfo.getControllerEnergyUsedMicroJoules()));
2335         } catch (RuntimeException e) {
2336             Slog.e(TAG, "failed to getWifiActivityEnergyInfoAsync", e);
2337             return StatsManager.PULL_SKIP;
2338         } finally {
2339             Binder.restoreCallingIdentity(token);
2340         }
2341         return StatsManager.PULL_SUCCESS;
2342     }
2343 
2344     private void registerModemActivityInfo() {
2345         int tagId = FrameworkStatsLog.MODEM_ACTIVITY_INFO;
2346         mStatsManager.setPullAtomCallback(
2347                 tagId,
2348                 null, // use default PullAtomMetadata values
2349                 DIRECT_EXECUTOR,
2350                 mStatsCallbackImpl
2351         );
2352     }
2353 
2354     int pullModemActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
2355         final long token = Binder.clearCallingIdentity();
2356         try {
2357             CompletableFuture<ModemActivityInfo> modemFuture = new CompletableFuture<>();
2358             mTelephony.requestModemActivityInfo(Runnable::run,
2359                     new OutcomeReceiver<ModemActivityInfo,
2360                             TelephonyManager.ModemActivityInfoException>() {
2361                         @Override
2362                         public void onResult(ModemActivityInfo result) {
2363                             modemFuture.complete(result);
2364                         }
2365 
2366                         @Override
2367                         public void onError(TelephonyManager.ModemActivityInfoException e) {
2368                             Slog.w(TAG, "error reading modem stats:" + e);
2369                             modemFuture.complete(null);
2370                         }
2371                     });
2372 
2373             ModemActivityInfo modemInfo;
2374             try {
2375                 modemInfo = modemFuture.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
2376                         TimeUnit.MILLISECONDS);
2377             } catch (TimeoutException | InterruptedException e) {
2378                 Slog.w(TAG, "timeout or interrupt reading modem stats: " + e);
2379                 return StatsManager.PULL_SKIP;
2380             } catch (ExecutionException e) {
2381                 Slog.w(TAG, "exception reading modem stats: " + e.getCause());
2382                 return StatsManager.PULL_SKIP;
2383             }
2384 
2385             if (modemInfo == null) {
2386                 return StatsManager.PULL_SKIP;
2387             }
2388             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
2389                     modemInfo.getTimestampMillis(),
2390                     modemInfo.getSleepTimeMillis(), modemInfo.getIdleTimeMillis(),
2391                     modemInfo.getTransmitDurationMillisAtPowerLevel(0),
2392                     modemInfo.getTransmitDurationMillisAtPowerLevel(1),
2393                     modemInfo.getTransmitDurationMillisAtPowerLevel(2),
2394                     modemInfo.getTransmitDurationMillisAtPowerLevel(3),
2395                     modemInfo.getTransmitDurationMillisAtPowerLevel(4),
2396                     modemInfo.getReceiveTimeMillis(),
2397                     -1 /*`energy_used` field name deprecated, use -1 to indicate as unused.*/));
2398         } finally {
2399             Binder.restoreCallingIdentity(token);
2400         }
2401         return StatsManager.PULL_SUCCESS;
2402     }
2403 
2404     private void registerBluetoothActivityInfo() {
2405         int tagId = FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO;
2406         mStatsManager.setPullAtomCallback(
2407                 tagId,
2408                 /* metadata */ null,
2409                 DIRECT_EXECUTOR,
2410                 mStatsCallbackImpl
2411         );
2412     }
2413 
2414     int pullBluetoothActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
2415         BluetoothActivityEnergyInfo info = fetchBluetoothData();
2416         if (info == null) {
2417             return StatsManager.PULL_SKIP;
2418         }
2419         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, info.getTimestampMillis(),
2420                 info.getBluetoothStackState(), info.getControllerTxTimeMillis(),
2421                 info.getControllerRxTimeMillis(), info.getControllerIdleTimeMillis(),
2422                 info.getControllerEnergyUsed()));
2423         return StatsManager.PULL_SUCCESS;
2424     }
2425 
2426     private void registerUwbActivityInfo() {
2427         if (mUwbManager == null) {
2428             return;
2429         }
2430         int tagId = FrameworkStatsLog.UWB_ACTIVITY_INFO;
2431         mStatsManager.setPullAtomCallback(
2432                 tagId,
2433                 null, // use default PullAtomMetadata values
2434                 DIRECT_EXECUTOR,
2435                 mStatsCallbackImpl
2436         );
2437     }
2438 
2439     int pullUwbActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
2440         final long token = Binder.clearCallingIdentity();
2441         try {
2442             SynchronousResultReceiver uwbReceiver = new SynchronousResultReceiver("uwb");
2443             mUwbManager.getUwbActivityEnergyInfoAsync(Runnable::run,
2444                     info -> {
2445                         Bundle bundle = new Bundle();
2446                         bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, info);
2447                         uwbReceiver.send(0, bundle);
2448                 }
2449             );
2450             final UwbActivityEnergyInfo uwbInfo = awaitControllerInfo(uwbReceiver);
2451             if (uwbInfo == null) {
2452                 return StatsManager.PULL_SKIP;
2453             }
2454             pulledData.add(
2455                     FrameworkStatsLog.buildStatsEvent(atomTag,
2456                             uwbInfo.getControllerTxDurationMillis(),
2457                             uwbInfo.getControllerRxDurationMillis(),
2458                             uwbInfo.getControllerIdleDurationMillis(),
2459                             uwbInfo.getControllerWakeCount()));
2460         } catch (RuntimeException e) {
2461             Slog.e(TAG, "failed to getUwbActivityEnergyInfoAsync", e);
2462             return StatsManager.PULL_SKIP;
2463         } finally {
2464             Binder.restoreCallingIdentity(token);
2465         }
2466         return StatsManager.PULL_SUCCESS;
2467     }
2468 
2469     private void registerSystemElapsedRealtime() {
2470         int tagId = FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME;
2471         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2472                 .setCoolDownMillis(MILLIS_PER_SEC)
2473                 .setTimeoutMillis(MILLIS_PER_SEC / 2)
2474                 .build();
2475         mStatsManager.setPullAtomCallback(
2476                 tagId,
2477                 metadata,
2478                 DIRECT_EXECUTOR,
2479                 mStatsCallbackImpl
2480         );
2481     }
2482 
2483     int pullSystemElapsedRealtimeLocked(int atomTag, List<StatsEvent> pulledData) {
2484         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, SystemClock.elapsedRealtime()));
2485         return StatsManager.PULL_SUCCESS;
2486     }
2487 
2488     private void registerSystemUptime() {
2489         int tagId = FrameworkStatsLog.SYSTEM_UPTIME;
2490         mStatsManager.setPullAtomCallback(
2491                 tagId,
2492                 null, // use default PullAtomMetadata values
2493                 DIRECT_EXECUTOR,
2494                 mStatsCallbackImpl
2495         );
2496     }
2497 
2498     int pullSystemUptimeLocked(int atomTag, List<StatsEvent> pulledData) {
2499         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, SystemClock.uptimeMillis()));
2500         return StatsManager.PULL_SUCCESS;
2501     }
2502 
2503     private void registerProcessMemoryState() {
2504         int tagId = FrameworkStatsLog.PROCESS_MEMORY_STATE;
2505         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2506                 .setAdditiveFields(new int[]{4, 5, 6, 7, 8})
2507                 .build();
2508         mStatsManager.setPullAtomCallback(
2509                 tagId,
2510                 metadata,
2511                 DIRECT_EXECUTOR,
2512                 mStatsCallbackImpl
2513         );
2514     }
2515 
2516     int pullProcessMemoryStateLocked(int atomTag, List<StatsEvent> pulledData) {
2517         List<ProcessMemoryState> processMemoryStates =
2518                 LocalServices.getService(ActivityManagerInternal.class)
2519                         .getMemoryStateForProcesses();
2520         for (ProcessMemoryState processMemoryState : processMemoryStates) {
2521             final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid,
2522                     processMemoryState.pid);
2523             if (memoryStat == null) {
2524                 continue;
2525             }
2526             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, processMemoryState.uid,
2527                     processMemoryState.processName, processMemoryState.oomScore, memoryStat.pgfault,
2528                     memoryStat.pgmajfault, memoryStat.rssInBytes, memoryStat.cacheInBytes,
2529                     memoryStat.swapInBytes, -1 /*unused*/, -1 /*unused*/, -1 /*unused*/));
2530         }
2531         return StatsManager.PULL_SUCCESS;
2532     }
2533 
2534     private void registerProcessMemoryHighWaterMark() {
2535         int tagId = FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK;
2536         mStatsManager.setPullAtomCallback(
2537                 tagId,
2538                 null, // use default PullAtomMetadata values
2539                 DIRECT_EXECUTOR,
2540                 mStatsCallbackImpl
2541         );
2542     }
2543 
2544     int pullProcessMemoryHighWaterMarkLocked(int atomTag, List<StatsEvent> pulledData) {
2545         List<ProcessMemoryState> managedProcessList =
2546                 LocalServices.getService(ActivityManagerInternal.class)
2547                         .getMemoryStateForProcesses();
2548         for (ProcessMemoryState managedProcess : managedProcessList) {
2549             final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
2550             if (snapshot == null) {
2551                 continue;
2552             }
2553             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, managedProcess.uid,
2554                     managedProcess.processName,
2555                     // RSS high-water mark in bytes.
2556                     snapshot.rssHighWaterMarkInKilobytes * 1024L,
2557                     snapshot.rssHighWaterMarkInKilobytes));
2558         }
2559         // Complement the data with native system processes
2560         SparseArray<String> processCmdlines = getProcessCmdlines();
2561         managedProcessList.forEach(managedProcess -> processCmdlines.delete(managedProcess.pid));
2562         int size = processCmdlines.size();
2563         for (int i = 0; i < size; ++i) {
2564             final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(processCmdlines.keyAt(i));
2565             if (snapshot == null) {
2566                 continue;
2567             }
2568             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, snapshot.uid,
2569                     processCmdlines.valueAt(i),
2570                     // RSS high-water mark in bytes.
2571                     snapshot.rssHighWaterMarkInKilobytes * 1024L,
2572                     snapshot.rssHighWaterMarkInKilobytes));
2573         }
2574         // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
2575         SystemProperties.set("sys.rss_hwm_reset.on", "1");
2576         return StatsManager.PULL_SUCCESS;
2577     }
2578 
2579     private void registerProcessMemorySnapshot() {
2580         int tagId = FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT;
2581         mStatsManager.setPullAtomCallback(
2582                 tagId,
2583                 null, // use default PullAtomMetadata values
2584                 DIRECT_EXECUTOR,
2585                 mStatsCallbackImpl
2586         );
2587     }
2588 
2589     int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
2590         List<ProcessMemoryState> managedProcessList =
2591                 LocalServices.getService(ActivityManagerInternal.class)
2592                         .getMemoryStateForProcesses();
2593         KernelAllocationStats.ProcessGpuMem[] gpuAllocations =
2594                 KernelAllocationStats.getGpuAllocations();
2595         SparseIntArray gpuMemPerPid = new SparseIntArray(gpuAllocations.length);
2596         for (KernelAllocationStats.ProcessGpuMem processGpuMem : gpuAllocations) {
2597             gpuMemPerPid.put(processGpuMem.pid, processGpuMem.gpuMemoryKb);
2598         }
2599         for (ProcessMemoryState managedProcess : managedProcessList) {
2600             final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
2601             if (snapshot == null) {
2602                 continue;
2603             }
2604             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, managedProcess.uid,
2605                     managedProcess.processName, managedProcess.pid, managedProcess.oomScore,
2606                     snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
2607                     snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
2608                     gpuMemPerPid.get(managedProcess.pid), managedProcess.hasForegroundServices,
2609                     snapshot.rssShmemKilobytes, managedProcess.mHostingComponentTypes,
2610                     managedProcess.mHistoricalHostingComponentTypes));
2611         }
2612         // Complement the data with native system processes. Given these measurements can be taken
2613         // in response to LMKs happening, we want to first collect the managed app stats (to
2614         // maximize the probability that a heavyweight process will be sampled before it dies).
2615         SparseArray<String> processCmdlines = getProcessCmdlines();
2616         managedProcessList.forEach(managedProcess -> processCmdlines.delete(managedProcess.pid));
2617         int size = processCmdlines.size();
2618         for (int i = 0; i < size; ++i) {
2619             int pid = processCmdlines.keyAt(i);
2620             final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
2621             if (snapshot == null) {
2622                 continue;
2623             }
2624             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, snapshot.uid,
2625                     processCmdlines.valueAt(i), pid,
2626                     -1001 /*Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.*/,
2627                     snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
2628                     snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
2629                     gpuMemPerPid.get(pid), false /* has_foreground_services */,
2630                     snapshot.rssShmemKilobytes,
2631                     // Native processes don't really have a hosting component type.
2632                     HOSTING_COMPONENT_TYPE_EMPTY,
2633                     HOSTING_COMPONENT_TYPE_EMPTY));
2634         }
2635         return StatsManager.PULL_SUCCESS;
2636     }
2637 
2638     private void registerSystemIonHeapSize() {
2639         int tagId = FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE;
2640         mStatsManager.setPullAtomCallback(
2641                 tagId,
2642                 null, // use default PullAtomMetadata values
2643                 DIRECT_EXECUTOR,
2644                 mStatsCallbackImpl
2645         );
2646     }
2647 
2648     int pullSystemIonHeapSizeLocked(int atomTag, List<StatsEvent> pulledData) {
2649         final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
2650         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, systemIonHeapSizeInBytes));
2651         return StatsManager.PULL_SUCCESS;
2652     }
2653 
2654     private void registerIonHeapSize() {
2655         if (!new File("/sys/kernel/ion/total_heaps_kb").exists()) {
2656             return;
2657         }
2658         int tagId = FrameworkStatsLog.ION_HEAP_SIZE;
2659         mStatsManager.setPullAtomCallback(
2660                 tagId,
2661                 /* PullAtomMetadata */ null,
2662                 DIRECT_EXECUTOR,
2663                 mStatsCallbackImpl
2664         );
2665     }
2666 
2667     int pullIonHeapSizeLocked(int atomTag, List<StatsEvent> pulledData) {
2668         int ionHeapSizeInKilobytes = (int) getIonHeapsSizeKb();
2669         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, ionHeapSizeInKilobytes));
2670         return StatsManager.PULL_SUCCESS;
2671     }
2672 
2673     private void registerProcessSystemIonHeapSize() {
2674         int tagId = FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE;
2675         mStatsManager.setPullAtomCallback(
2676                 tagId,
2677                 null, // use default PullAtomMetadata values
2678                 DIRECT_EXECUTOR,
2679                 mStatsCallbackImpl
2680         );
2681     }
2682 
2683     int pullProcessSystemIonHeapSizeLocked(int atomTag, List<StatsEvent> pulledData) {
2684         List<IonAllocations> result = readProcessSystemIonHeapSizesFromDebugfs();
2685         for (IonAllocations allocations : result) {
2686             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, getUidForPid(allocations.pid),
2687                     readCmdlineFromProcfs(allocations.pid),
2688                     (int) (allocations.totalSizeInBytes / 1024), allocations.count,
2689                     (int) (allocations.maxSizeInBytes / 1024)));
2690         }
2691         return StatsManager.PULL_SUCCESS;
2692     }
2693 
2694     private void registerProcessDmabufMemory() {
2695         int tagId = FrameworkStatsLog.PROCESS_DMABUF_MEMORY;
2696         mStatsManager.setPullAtomCallback(
2697                 tagId,
2698                 null, // use default PullAtomMetadata values
2699                 DIRECT_EXECUTOR,
2700                 mStatsCallbackImpl
2701         );
2702     }
2703 
2704     int pullProcessDmabufMemory(int atomTag, List<StatsEvent> pulledData) {
2705         KernelAllocationStats.ProcessDmabuf[] procBufs =
2706                 KernelAllocationStats.getDmabufAllocations();
2707 
2708         if (procBufs == null) {
2709             return StatsManager.PULL_SKIP;
2710         }
2711         for (KernelAllocationStats.ProcessDmabuf procBuf : procBufs) {
2712             pulledData.add(FrameworkStatsLog.buildStatsEvent(
2713                     atomTag,
2714                     procBuf.uid,
2715                     procBuf.processName,
2716                     procBuf.oomScore,
2717                     procBuf.retainedSizeKb,
2718                     procBuf.retainedBuffersCount,
2719                     0, /* mapped_dmabuf_kb - deprecated */
2720                     0, /* mapped_dmabuf_count - deprecated */
2721                     procBuf.surfaceFlingerSizeKb,
2722                     procBuf.surfaceFlingerCount
2723             ));
2724         }
2725         return StatsManager.PULL_SUCCESS;
2726     }
2727 
2728     private void registerSystemMemory() {
2729         int tagId = FrameworkStatsLog.SYSTEM_MEMORY;
2730         mStatsManager.setPullAtomCallback(
2731                 tagId,
2732                 null, // use default PullAtomMetadata values
2733                 DIRECT_EXECUTOR,
2734                 mStatsCallbackImpl
2735         );
2736     }
2737 
2738     int pullSystemMemory(int atomTag, List<StatsEvent> pulledData) {
2739         SystemMemoryUtil.Metrics metrics = SystemMemoryUtil.getMetrics();
2740         pulledData.add(
2741                 FrameworkStatsLog.buildStatsEvent(
2742                         atomTag,
2743                         metrics.unreclaimableSlabKb,
2744                         metrics.vmallocUsedKb,
2745                         metrics.pageTablesKb,
2746                         metrics.kernelStackKb,
2747                         metrics.totalIonKb,
2748                         metrics.unaccountedKb,
2749                         metrics.gpuTotalUsageKb,
2750                         metrics.gpuPrivateAllocationsKb,
2751                         metrics.dmaBufTotalExportedKb,
2752                         metrics.shmemKb,
2753                         metrics.totalKb,
2754                         metrics.freeKb,
2755                         metrics.availableKb,
2756                         metrics.activeKb,
2757                         metrics.inactiveKb,
2758                         metrics.activeAnonKb,
2759                         metrics.inactiveAnonKb,
2760                         metrics.activeFileKb,
2761                         metrics.inactiveFileKb,
2762                         metrics.swapTotalKb,
2763                         metrics.swapFreeKb,
2764                         metrics.cmaTotalKb,
2765                         metrics.cmaFreeKb));
2766         return StatsManager.PULL_SUCCESS;
2767     }
2768 
2769     private void registerVmStat() {
2770         int tagId = FrameworkStatsLog.VMSTAT;
2771         mStatsManager.setPullAtomCallback(
2772                 tagId,
2773                 null, // use default PullAtomMetadata values
2774                 DIRECT_EXECUTOR,
2775                 mStatsCallbackImpl
2776         );
2777     }
2778 
2779     int pullVmStat(int atomTag, List<StatsEvent> pulledData) {
2780         ProcfsMemoryUtil.VmStat vmStat = ProcfsMemoryUtil.readVmStat();
2781         if (vmStat != null) {
2782             pulledData.add(
2783                     FrameworkStatsLog.buildStatsEvent(
2784                             atomTag,
2785                             vmStat.oomKillCount));
2786         }
2787         return StatsManager.PULL_SUCCESS;
2788     }
2789 
2790     private void registerTemperature() {
2791         int tagId = FrameworkStatsLog.TEMPERATURE;
2792         mStatsManager.setPullAtomCallback(
2793                 tagId,
2794                 null, // use default PullAtomMetadata values
2795                 DIRECT_EXECUTOR,
2796                 mStatsCallbackImpl
2797         );
2798     }
2799 
2800     int pullTemperatureLocked(int atomTag, List<StatsEvent> pulledData) {
2801         IThermalService thermalService = getIThermalService();
2802         if (thermalService == null) {
2803             return StatsManager.PULL_SKIP;
2804         }
2805         final long callingToken = Binder.clearCallingIdentity();
2806         try {
2807             Temperature temperatures[] = thermalService.getCurrentTemperatures();
2808             for (Temperature temp : temperatures) {
2809                 pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, temp.getType(),
2810                         temp.getName(), (int) (temp.getValue() * 10), temp.getStatus()));
2811             }
2812         } catch (RemoteException e) {
2813             // Should not happen.
2814             Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
2815             return StatsManager.PULL_SKIP;
2816         } finally {
2817             Binder.restoreCallingIdentity(callingToken);
2818         }
2819         return StatsManager.PULL_SUCCESS;
2820     }
2821 
2822     private void registerCoolingDevice() {
2823         int tagId = FrameworkStatsLog.COOLING_DEVICE;
2824         mStatsManager.setPullAtomCallback(
2825                 tagId,
2826                 null, // use default PullAtomMetadata values
2827                 DIRECT_EXECUTOR,
2828                 mStatsCallbackImpl
2829         );
2830     }
2831 
2832     int pullCooldownDeviceLocked(int atomTag, List<StatsEvent> pulledData) {
2833         IThermalService thermalService = getIThermalService();
2834         if (thermalService == null) {
2835             return StatsManager.PULL_SKIP;
2836         }
2837         final long callingToken = Binder.clearCallingIdentity();
2838         try {
2839             CoolingDevice devices[] = thermalService.getCurrentCoolingDevices();
2840             for (CoolingDevice device : devices) {
2841                 pulledData.add(FrameworkStatsLog.buildStatsEvent(
2842                         atomTag, device.getType(), device.getName(), (int) (device.getValue())));
2843             }
2844         } catch (RemoteException e) {
2845             // Should not happen.
2846             Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
2847             return StatsManager.PULL_SKIP;
2848         } finally {
2849             Binder.restoreCallingIdentity(callingToken);
2850         }
2851         return StatsManager.PULL_SUCCESS;
2852     }
2853 
2854     private void registerBinderCallsStats() {
2855         int tagId = FrameworkStatsLog.BINDER_CALLS;
2856         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2857                 .setAdditiveFields(new int[]{4, 5, 6, 8, 12})
2858                 .build();
2859         mStatsManager.setPullAtomCallback(
2860                 tagId,
2861                 metadata,
2862                 DIRECT_EXECUTOR,
2863                 mStatsCallbackImpl
2864         );
2865     }
2866 
2867     int pullBinderCallsStatsLocked(int atomTag, List<StatsEvent> pulledData) {
2868         BinderCallsStatsService.Internal binderStats =
2869                 LocalServices.getService(BinderCallsStatsService.Internal.class);
2870         if (binderStats == null) {
2871             Slog.e(TAG, "failed to get binderStats");
2872             return StatsManager.PULL_SKIP;
2873         }
2874 
2875         List<ExportedCallStat> callStats = binderStats.getExportedCallStats();
2876         binderStats.reset();
2877         for (ExportedCallStat callStat : callStats) {
2878             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, callStat.workSourceUid,
2879                     callStat.className, callStat.methodName, callStat.callCount,
2880                     callStat.exceptionCount, callStat.latencyMicros, callStat.maxLatencyMicros,
2881                     callStat.cpuTimeMicros, callStat.maxCpuTimeMicros, callStat.maxReplySizeBytes,
2882                     callStat.maxRequestSizeBytes, callStat.recordedCallCount,
2883                     callStat.screenInteractive, callStat.callingUid));
2884         }
2885         return StatsManager.PULL_SUCCESS;
2886     }
2887 
2888     private void registerBinderCallsStatsExceptions() {
2889         int tagId = FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS;
2890         mStatsManager.setPullAtomCallback(
2891                 tagId,
2892                 null, // use default PullAtomMetadata values
2893                 DIRECT_EXECUTOR,
2894                 mStatsCallbackImpl
2895         );
2896     }
2897 
2898     int pullBinderCallsStatsExceptionsLocked(int atomTag, List<StatsEvent> pulledData) {
2899         BinderCallsStatsService.Internal binderStats =
2900                 LocalServices.getService(BinderCallsStatsService.Internal.class);
2901         if (binderStats == null) {
2902             Slog.e(TAG, "failed to get binderStats");
2903             return StatsManager.PULL_SKIP;
2904         }
2905 
2906         ArrayMap<String, Integer> exceptionStats = binderStats.getExportedExceptionStats();
2907         // TODO: decouple binder calls exceptions with the rest of the binder calls data so that we
2908         // can reset the exception stats.
2909         for (Map.Entry<String, Integer> entry : exceptionStats.entrySet()) {
2910             pulledData.add(
2911                     FrameworkStatsLog.buildStatsEvent(atomTag, entry.getKey(), entry.getValue()));
2912         }
2913         return StatsManager.PULL_SUCCESS;
2914     }
2915 
2916     private void registerLooperStats() {
2917         int tagId = FrameworkStatsLog.LOOPER_STATS;
2918         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
2919                 .setAdditiveFields(new int[]{5, 6, 7, 8, 9})
2920                 .build();
2921         mStatsManager.setPullAtomCallback(
2922                 tagId,
2923                 metadata,
2924                 DIRECT_EXECUTOR,
2925                 mStatsCallbackImpl
2926         );
2927     }
2928 
2929     int pullLooperStatsLocked(int atomTag, List<StatsEvent> pulledData) {
2930         LooperStats looperStats = LocalServices.getService(LooperStats.class);
2931         if (looperStats == null) {
2932             return StatsManager.PULL_SKIP;
2933         }
2934 
2935         List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
2936         looperStats.reset();
2937         for (LooperStats.ExportedEntry entry : entries) {
2938             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, entry.workSourceUid,
2939                     entry.handlerClassName, entry.threadName, entry.messageName, entry.messageCount,
2940                     entry.exceptionCount, entry.recordedMessageCount, entry.totalLatencyMicros,
2941                     entry.cpuUsageMicros, entry.isInteractive, entry.maxCpuUsageMicros,
2942                     entry.maxLatencyMicros, entry.recordedDelayMessageCount, entry.delayMillis,
2943                     entry.maxDelayMillis));
2944         }
2945         return StatsManager.PULL_SUCCESS;
2946     }
2947 
2948     private void registerDiskStats() {
2949         int tagId = FrameworkStatsLog.DISK_STATS;
2950         mStatsManager.setPullAtomCallback(
2951                 tagId,
2952                 null, // use default PullAtomMetadata values
2953                 DIRECT_EXECUTOR,
2954                 mStatsCallbackImpl
2955         );
2956     }
2957 
2958     int pullDiskStatsLocked(int atomTag, List<StatsEvent> pulledData) {
2959         // Run a quick-and-dirty performance test: write 512 bytes
2960         byte[] junk = new byte[512];
2961         for (int i = 0; i < junk.length; i++) junk[i] = (byte) i;  // Write nonzero bytes
2962 
2963         File tmp = new File(Environment.getDataDirectory(), "system/statsdperftest.tmp");
2964         FileOutputStream fos = null;
2965         IOException error = null;
2966 
2967         long before = SystemClock.elapsedRealtime();
2968         try {
2969             fos = new FileOutputStream(tmp);
2970             fos.write(junk);
2971         } catch (IOException e) {
2972             error = e;
2973         } finally {
2974             try {
2975                 if (fos != null) fos.close();
2976             } catch (IOException e) {
2977                 // Do nothing.
2978             }
2979         }
2980 
2981         long latency = SystemClock.elapsedRealtime() - before;
2982         if (tmp.exists()) tmp.delete();
2983 
2984         if (error != null) {
2985             Slog.e(TAG, "Error performing diskstats latency test");
2986             latency = -1;
2987         }
2988         // File based encryption.
2989         boolean fileBased = StorageManager.isFileEncrypted();
2990 
2991         //Recent disk write speed. Binder call to storaged.
2992         int writeSpeed = -1;
2993         IStoraged storaged = getIStoragedService();
2994         if (storaged == null) {
2995             return StatsManager.PULL_SKIP;
2996         }
2997         try {
2998             writeSpeed = storaged.getRecentPerf();
2999         } catch (RemoteException e) {
3000             Slog.e(TAG, "storaged not found");
3001         }
3002 
3003         // Add info pulledData.
3004         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, latency, fileBased, writeSpeed));
3005         return StatsManager.PULL_SUCCESS;
3006     }
3007 
3008     private void registerDirectoryUsage() {
3009         int tagId = FrameworkStatsLog.DIRECTORY_USAGE;
3010         mStatsManager.setPullAtomCallback(
3011                 tagId,
3012                 null, // use default PullAtomMetadata values
3013                 DIRECT_EXECUTOR,
3014                 mStatsCallbackImpl
3015         );
3016     }
3017 
3018     int pullDirectoryUsageLocked(int atomTag, List<StatsEvent> pulledData) {
3019         StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
3020         StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
3021         StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
3022         StatFs metadataFsSystem = new StatFs(Environment.getMetadataDirectory().getAbsolutePath());
3023 
3024         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3025                 FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__DATA, statFsData.getAvailableBytes(),
3026                 statFsData.getTotalBytes()));
3027 
3028         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3029                 FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE,
3030                 statFsCache.getAvailableBytes(), statFsCache.getTotalBytes()));
3031 
3032         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3033                 FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM,
3034                 statFsSystem.getAvailableBytes(), statFsSystem.getTotalBytes()));
3035 
3036         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3037                 FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__METADATA,
3038                 metadataFsSystem.getAvailableBytes(), metadataFsSystem.getTotalBytes()));
3039         return StatsManager.PULL_SUCCESS;
3040     }
3041 
3042     private void registerAppSize() {
3043         int tagId = FrameworkStatsLog.APP_SIZE;
3044         mStatsManager.setPullAtomCallback(
3045                 tagId,
3046                 null, // use default PullAtomMetadata values
3047                 DIRECT_EXECUTOR,
3048                 mStatsCallbackImpl
3049         );
3050     }
3051 
3052     int pullAppSizeLocked(int atomTag, List<StatsEvent> pulledData) {
3053         try {
3054             String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
3055             JSONObject json = new JSONObject(jsonStr);
3056             long cache_time = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
3057             JSONArray pkg_names = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
3058             JSONArray app_sizes = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY);
3059             JSONArray app_data_sizes = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY);
3060             JSONArray app_cache_sizes = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY);
3061             // Validity check: Ensure all 4 lists have the same length.
3062             int length = pkg_names.length();
3063             if (app_sizes.length() != length || app_data_sizes.length() != length
3064                     || app_cache_sizes.length() != length) {
3065                 Slog.e(TAG, "formatting error in diskstats cache file!");
3066                 return StatsManager.PULL_SKIP;
3067             }
3068             for (int i = 0; i < length; i++) {
3069                 pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, pkg_names.getString(i),
3070                         app_sizes.optLong(i, /* fallback */ -1L),
3071                         app_data_sizes.optLong(i, /* fallback */ -1L),
3072                         app_cache_sizes.optLong(i, /* fallback */ -1L), cache_time));
3073             }
3074         } catch (IOException | JSONException e) {
3075             Slog.w(TAG, "Unable to read diskstats cache file within pullAppSize");
3076             return StatsManager.PULL_SKIP;
3077         }
3078         return StatsManager.PULL_SUCCESS;
3079     }
3080 
3081     private void registerCategorySize() {
3082         int tagId = FrameworkStatsLog.CATEGORY_SIZE;
3083         mStatsManager.setPullAtomCallback(
3084                 tagId,
3085                 null, // use default PullAtomMetadata values
3086                 DIRECT_EXECUTOR,
3087                 mStatsCallbackImpl
3088         );
3089     }
3090 
3091     int pullCategorySizeLocked(int atomTag, List<StatsEvent> pulledData) {
3092         try {
3093             String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
3094             JSONObject json = new JSONObject(jsonStr);
3095             long cacheTime = json.optLong(
3096                     DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, /* fallback */ -1L);
3097 
3098             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3099                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE,
3100                     json.optLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY, /* fallback */ -1L),
3101                     cacheTime));
3102 
3103             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3104                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE,
3105                     json.optLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, /* fallback */ -1L),
3106                     cacheTime));
3107 
3108             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3109                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE,
3110                     json.optLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY, /* fallback */ -1L),
3111                     cacheTime));
3112 
3113             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3114                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS,
3115                     json.optLong(DiskStatsFileLogger.PHOTOS_KEY, /* fallback */ -1L), cacheTime));
3116 
3117             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3118                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS,
3119                     json.optLong(DiskStatsFileLogger.VIDEOS_KEY, /* fallback */ -1L), cacheTime));
3120 
3121             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3122                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__AUDIO,
3123                     json.optLong(DiskStatsFileLogger.AUDIO_KEY, /* fallback */ -1L), cacheTime));
3124 
3125             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3126                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS,
3127                     json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, /* fallback */ -1L),
3128                     cacheTime));
3129 
3130             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3131                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM,
3132                     json.optLong(DiskStatsFileLogger.SYSTEM_KEY, /* fallback */ -1L), cacheTime));
3133 
3134             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3135                     FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__OTHER,
3136                     json.optLong(DiskStatsFileLogger.MISC_KEY, /* fallback */ -1L), cacheTime));
3137         } catch (IOException | JSONException e) {
3138             Slog.w(TAG, "Unable to read diskstats cache file within pullCategorySize");
3139             return StatsManager.PULL_SKIP;
3140         }
3141         return StatsManager.PULL_SUCCESS;
3142     }
3143 
3144     private void registerNumFingerprintsEnrolled() {
3145         int tagId = FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED;
3146         mStatsManager.setPullAtomCallback(
3147                 tagId,
3148                 null, // use default PullAtomMetadata values
3149                 DIRECT_EXECUTOR,
3150                 mStatsCallbackImpl
3151         );
3152     }
3153 
3154     private void registerNumFacesEnrolled() {
3155         int tagId = FrameworkStatsLog.NUM_FACES_ENROLLED;
3156         mStatsManager.setPullAtomCallback(
3157                 tagId,
3158                 null, // use default PullAtomMetadata values
3159                 DIRECT_EXECUTOR,
3160                 mStatsCallbackImpl
3161         );
3162     }
3163 
3164     private int pullNumBiometricsEnrolledLocked(int modality, int atomTag,
3165             List<StatsEvent> pulledData) {
3166         final PackageManager pm = mContext.getPackageManager();
3167         FingerprintManager fingerprintManager = null;
3168         FaceManager faceManager = null;
3169 
3170         if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
3171             fingerprintManager = mContext.getSystemService(FingerprintManager.class);
3172         }
3173         if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
3174             faceManager = mContext.getSystemService(FaceManager.class);
3175         }
3176 
3177         if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT && fingerprintManager == null) {
3178             return StatsManager.PULL_SKIP;
3179         }
3180         if (modality == BiometricsProtoEnums.MODALITY_FACE && faceManager == null) {
3181             return StatsManager.PULL_SKIP;
3182         }
3183         UserManager userManager = mContext.getSystemService(UserManager.class);
3184         if (userManager == null) {
3185             return StatsManager.PULL_SKIP;
3186         }
3187 
3188         final long token = Binder.clearCallingIdentity();
3189         try {
3190             for (UserInfo user : userManager.getUsers()) {
3191                 final int userId = user.getUserHandle().getIdentifier();
3192                 int numEnrolled = 0;
3193                 if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT) {
3194                     numEnrolled = fingerprintManager.getEnrolledFingerprints(userId).size();
3195                 } else if (modality == BiometricsProtoEnums.MODALITY_FACE) {
3196                     numEnrolled = faceManager.getEnrolledFaces(userId).size();
3197                 } else {
3198                     return StatsManager.PULL_SKIP;
3199                 }
3200                 pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, userId, numEnrolled));
3201             }
3202         } finally {
3203             Binder.restoreCallingIdentity(token);
3204         }
3205         return StatsManager.PULL_SUCCESS;
3206     }
3207 
3208     private void registerProcStats() {
3209         int tagId = FrameworkStatsLog.PROC_STATS;
3210         mStatsManager.setPullAtomCallback(
3211                 tagId,
3212                 null, // use default PullAtomMetadata values
3213                 DIRECT_EXECUTOR,
3214                 mStatsCallbackImpl
3215         );
3216     }
3217 
3218     private void registerProcStatsPkgProc() {
3219         int tagId = FrameworkStatsLog.PROC_STATS_PKG_PROC;
3220         mStatsManager.setPullAtomCallback(
3221                 tagId,
3222                 null, // use default PullAtomMetadata values
3223                 DIRECT_EXECUTOR,
3224                 mStatsCallbackImpl
3225         );
3226     }
3227 
3228     private void registerProcessState() {
3229         int tagId = FrameworkStatsLog.PROCESS_STATE;
3230         mStatsManager.setPullAtomCallback(
3231                 tagId,
3232                 null, // use default PullAtomMetadata values
3233                 DIRECT_EXECUTOR,
3234                 mStatsCallbackImpl);
3235     }
3236 
3237     private void registerProcessAssociation() {
3238         int tagId = FrameworkStatsLog.PROCESS_ASSOCIATION;
3239         mStatsManager.setPullAtomCallback(
3240                 tagId,
3241                 null, // use default PullAtomMetadata values
3242                 DIRECT_EXECUTOR,
3243                 mStatsCallbackImpl);
3244     }
3245 
3246     @GuardedBy("mProcStatsLock")
3247     private ProcessStats getStatsFromProcessStatsService(int atomTag) {
3248         IProcessStats processStatsService = getIProcessStatsService();
3249         if (processStatsService == null) {
3250             return null;
3251         }
3252         final long token = Binder.clearCallingIdentity();
3253         try {
3254             // force procstats to flush & combine old files into one store
3255             long lastHighWaterMark = readProcStatsHighWaterMark(atomTag);
3256             ProcessStats procStats = new ProcessStats(false);
3257             // Force processStatsService to aggregate all in-storage and in-memory data.
3258             long highWaterMark =
3259                     processStatsService.getCommittedStatsMerged(
3260                             lastHighWaterMark,
3261                             ProcessStats.REPORT_ALL, // ignored since committedStats below is null.
3262                             true,
3263                             null, // committedStats
3264                             procStats);
3265             new File(
3266                             mBaseDir.getAbsolutePath()
3267                                     + "/"
3268                                     + highWaterMarkFilePrefix(atomTag)
3269                                     + "_"
3270                                     + lastHighWaterMark)
3271                     .delete();
3272             new File(
3273                             mBaseDir.getAbsolutePath()
3274                                     + "/"
3275                                     + highWaterMarkFilePrefix(atomTag)
3276                                     + "_"
3277                                     + highWaterMark)
3278                     .createNewFile();
3279             return procStats;
3280         } catch (RemoteException | IOException e) {
3281             Slog.e(TAG, "Getting procstats failed: ", e);
3282             return null;
3283         } finally {
3284             Binder.restoreCallingIdentity(token);
3285         }
3286     }
3287 
3288     @GuardedBy("mProcStatsLock")
3289     private int pullProcStatsLocked(int atomTag, List<StatsEvent> pulledData) {
3290         ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
3291         if (procStats == null) {
3292             return StatsManager.PULL_SKIP;
3293         }
3294         ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
3295         for (int i = 0; i < protoStreams.length; i++) {
3296             protoStreams[i] = new ProtoOutputStream();
3297         }
3298         procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
3299         for (int i = 0; i < protoStreams.length; i++) {
3300             byte[] bytes = protoStreams[i].getBytes(); // cache the value
3301             if (bytes.length > 0) {
3302                 pulledData.add(
3303                         FrameworkStatsLog.buildStatsEvent(
3304                                 atomTag,
3305                                 bytes,
3306                                 // This is a shard ID, and is specified in the metric definition to
3307                                 // be
3308                                 // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE
3309                                 // to
3310                                 // keep all the shards, as it thinks each shard is a different
3311                                 // dimension
3312                                 // of data.
3313                                 i));
3314             }
3315         }
3316         return StatsManager.PULL_SUCCESS;
3317     }
3318 
3319     @GuardedBy("mProcStatsLock")
3320     private int pullProcessStateLocked(int atomTag, List<StatsEvent> pulledData) {
3321         ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
3322         if (procStats == null) {
3323             return StatsManager.PULL_SKIP;
3324         }
3325         procStats.dumpProcessState(atomTag, new StatsEventOutput(pulledData));
3326         return StatsManager.PULL_SUCCESS;
3327     }
3328 
3329     @GuardedBy("mProcStatsLock")
3330     private int pullProcessAssociationLocked(int atomTag, List<StatsEvent> pulledData) {
3331         ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
3332         if (procStats == null) {
3333             return StatsManager.PULL_SKIP;
3334         }
3335         procStats.dumpProcessAssociation(atomTag, new StatsEventOutput(pulledData));
3336         return StatsManager.PULL_SUCCESS;
3337     }
3338 
3339     private String highWaterMarkFilePrefix(int atomTag) {
3340         // For backward compatibility, use the legacy ProcessStats enum value as the prefix for
3341         // PROC_STATS and PROC_STATS_PKG_PROC.
3342         if (atomTag == FrameworkStatsLog.PROC_STATS) {
3343             return String.valueOf(ProcessStats.REPORT_ALL);
3344         }
3345         if (atomTag == FrameworkStatsLog.PROC_STATS_PKG_PROC) {
3346             return String.valueOf(ProcessStats.REPORT_PKG_PROC_STATS);
3347         }
3348         return "atom-" + atomTag;
3349     }
3350 
3351     // read high watermark for section
3352     @GuardedBy("mProcStatsLock")
3353     private long readProcStatsHighWaterMark(int atomTag) {
3354         try {
3355             File[] files =
3356                     mBaseDir.listFiles(
3357                             (d, name) -> {
3358                                 return name.toLowerCase()
3359                                         .startsWith(highWaterMarkFilePrefix(atomTag) + '_');
3360                             });
3361             if (files == null || files.length == 0) {
3362                 return 0;
3363             }
3364             if (files.length > 1) {
3365                 Slog.e(TAG, "Only 1 file expected for high water mark. Found " + files.length);
3366             }
3367             return Long.valueOf(files[0].getName().split("_")[1]);
3368         } catch (SecurityException e) {
3369             Slog.e(TAG, "Failed to get procstats high watermark file.", e);
3370         } catch (NumberFormatException e) {
3371             Slog.e(TAG, "Failed to parse file name.", e);
3372         }
3373         return 0;
3374     }
3375 
3376     private void registerDiskIO() {
3377         int tagId = FrameworkStatsLog.DISK_IO;
3378         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
3379                 .setAdditiveFields(new int[]{2, 3, 4, 5, 6, 7, 8, 9, 10, 11})
3380                 .setCoolDownMillis(3 * MILLIS_PER_SEC)
3381                 .build();
3382         mStatsManager.setPullAtomCallback(
3383                 tagId,
3384                 metadata,
3385                 DIRECT_EXECUTOR,
3386                 mStatsCallbackImpl
3387         );
3388     }
3389 
3390     int pullDiskIOLocked(int atomTag, List<StatsEvent> pulledData) {
3391         mStoragedUidIoStatsReader.readAbsolute(
3392                 (uid, fgCharsRead, fgCharsWrite, fgBytesRead, fgBytesWrite, bgCharsRead,
3393                         bgCharsWrite, bgBytesRead, bgBytesWrite, fgFsync, bgFsync) -> {
3394                     pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, uid, fgCharsRead,
3395                             fgCharsWrite, fgBytesRead, fgBytesWrite, bgCharsRead, bgCharsWrite,
3396                             bgBytesRead, bgBytesWrite, fgFsync, bgFsync));
3397                 });
3398         return StatsManager.PULL_SUCCESS;
3399     }
3400 
3401     private void registerPowerProfile() {
3402         int tagId = FrameworkStatsLog.POWER_PROFILE;
3403         mStatsManager.setPullAtomCallback(
3404                 tagId,
3405                 /* PullAtomMetadata */ null,
3406                 DIRECT_EXECUTOR,
3407                 mStatsCallbackImpl
3408         );
3409     }
3410 
3411     int pullPowerProfileLocked(int atomTag, List<StatsEvent> pulledData) {
3412         PowerProfile powerProfile = new PowerProfile(mContext);
3413         ProtoOutputStream proto = new ProtoOutputStream();
3414         powerProfile.dumpDebug(proto);
3415         proto.flush();
3416         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, proto.getBytes()));
3417         return StatsManager.PULL_SUCCESS;
3418     }
3419 
3420     private void registerProcessCpuTime() {
3421         int tagId = FrameworkStatsLog.PROCESS_CPU_TIME;
3422         // Min cool-down is 5 sec, in line with what ActivityManagerService uses.
3423         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
3424                 .setCoolDownMillis(5 * MILLIS_PER_SEC)
3425                 .build();
3426         mStatsManager.setPullAtomCallback(
3427                 tagId,
3428                 metadata,
3429                 DIRECT_EXECUTOR,
3430                 mStatsCallbackImpl
3431         );
3432     }
3433 
3434     int pullProcessCpuTimeLocked(int atomTag, List<StatsEvent> pulledData) {
3435         if (mProcessCpuTracker == null) {
3436             mProcessCpuTracker = new ProcessCpuTracker(false);
3437             mProcessCpuTracker.init();
3438         }
3439         mProcessCpuTracker.update();
3440         for (int i = 0; i < mProcessCpuTracker.countStats(); i++) {
3441             ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
3442             pulledData.add(FrameworkStatsLog.buildStatsEvent(
3443                     atomTag, st.uid, st.name, st.base_utime, st.base_stime));
3444         }
3445         return StatsManager.PULL_SUCCESS;
3446     }
3447 
3448     private void registerCpuTimePerThreadFreq() {
3449         int tagId = FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ;
3450         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
3451                 .setAdditiveFields(new int[]{7, 9, 11, 13, 15, 17, 19, 21})
3452                 .build();
3453         mStatsManager.setPullAtomCallback(
3454                 tagId,
3455                 metadata,
3456                 DIRECT_EXECUTOR,
3457                 mStatsCallbackImpl
3458         );
3459     }
3460 
3461     int pullCpuTimePerThreadFreqLocked(int atomTag, List<StatsEvent> pulledData) {
3462         if (this.mKernelCpuThreadReader == null) {
3463             Slog.e(TAG, "mKernelCpuThreadReader is null");
3464             return StatsManager.PULL_SKIP;
3465         }
3466         ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages =
3467                 this.mKernelCpuThreadReader.getProcessCpuUsageDiffed();
3468         if (processCpuUsages == null) {
3469             Slog.e(TAG, "processCpuUsages is null");
3470             return StatsManager.PULL_SKIP;
3471         }
3472         int[] cpuFrequencies = mKernelCpuThreadReader.getCpuFrequenciesKhz();
3473         if (cpuFrequencies.length > CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES) {
3474             String message = "Expected maximum " + CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES
3475                     + " frequencies, but got " + cpuFrequencies.length;
3476             Slog.w(TAG, message);
3477             return StatsManager.PULL_SKIP;
3478         }
3479         for (int i = 0; i < processCpuUsages.size(); i++) {
3480             KernelCpuThreadReader.ProcessCpuUsage processCpuUsage = processCpuUsages.get(i);
3481             ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages =
3482                     processCpuUsage.threadCpuUsages;
3483             for (int j = 0; j < threadCpuUsages.size(); j++) {
3484                 KernelCpuThreadReader.ThreadCpuUsage threadCpuUsage = threadCpuUsages.get(j);
3485                 if (threadCpuUsage.usageTimesMillis.length != cpuFrequencies.length) {
3486                     String message = "Unexpected number of usage times,"
3487                             + " expected " + cpuFrequencies.length
3488                             + " but got " + threadCpuUsage.usageTimesMillis.length;
3489                     Slog.w(TAG, message);
3490                     return StatsManager.PULL_SKIP;
3491                 }
3492 
3493                 int[] frequencies = new int[CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES];
3494                 int[] usageTimesMillis = new int[CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES];
3495                 for (int k = 0; k < CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES; k++) {
3496                     if (k < cpuFrequencies.length) {
3497                         frequencies[k] = cpuFrequencies[k];
3498                         usageTimesMillis[k] = threadCpuUsage.usageTimesMillis[k];
3499                     } else {
3500                         // If we have no more frequencies to write, we still must write empty data.
3501                         // We know that this data is empty (and not just zero) because all
3502                         // frequencies are expected to be greater than zero
3503                         frequencies[k] = 0;
3504                         usageTimesMillis[k] = 0;
3505                     }
3506                 }
3507                 pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, processCpuUsage.uid,
3508                         processCpuUsage.processId, threadCpuUsage.threadId,
3509                         processCpuUsage.processName, threadCpuUsage.threadName, frequencies[0],
3510                         usageTimesMillis[0], frequencies[1], usageTimesMillis[1], frequencies[2],
3511                         usageTimesMillis[2], frequencies[3], usageTimesMillis[3], frequencies[4],
3512                         usageTimesMillis[4], frequencies[5], usageTimesMillis[5], frequencies[6],
3513                         usageTimesMillis[6], frequencies[7], usageTimesMillis[7]));
3514             }
3515         }
3516         return StatsManager.PULL_SUCCESS;
3517     }
3518 
3519     private long milliAmpHrsToNanoAmpSecs(double mAh) {
3520         return (long) (mAh * MILLI_AMP_HR_TO_NANO_AMP_SECS + 0.5);
3521     }
3522 
3523     private void registerDeviceCalculatedPowerUse() {
3524         int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE;
3525         mStatsManager.setPullAtomCallback(
3526                 tagId,
3527                 null, // use default PullAtomMetadata values
3528                 DIRECT_EXECUTOR,
3529                 mStatsCallbackImpl
3530         );
3531     }
3532 
3533     int pullDeviceCalculatedPowerUseLocked(int atomTag, List<StatsEvent> pulledData) {
3534         final BatteryStatsManager bsm = mContext.getSystemService(BatteryStatsManager.class);
3535         try {
3536             final BatteryUsageStats stats = bsm.getBatteryUsageStats();
3537             pulledData.add(FrameworkStatsLog.buildStatsEvent(
3538                     atomTag, milliAmpHrsToNanoAmpSecs(stats.getConsumedPower())));
3539             return StatsManager.PULL_SUCCESS;
3540         } catch (Exception e) {
3541             Log.e(TAG, "Could not obtain battery usage stats", e);
3542             return StatsManager.PULL_SKIP;
3543         }
3544     }
3545 
3546     private void registerDebugElapsedClock() {
3547         int tagId = FrameworkStatsLog.DEBUG_ELAPSED_CLOCK;
3548         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
3549                 .setAdditiveFields(new int[]{1, 2, 3, 4})
3550                 .build();
3551         mStatsManager.setPullAtomCallback(
3552                 tagId,
3553                 metadata,
3554                 DIRECT_EXECUTOR,
3555                 mStatsCallbackImpl
3556         );
3557     }
3558 
3559     int pullDebugElapsedClockLocked(int atomTag, List<StatsEvent> pulledData) {
3560         final long elapsedMillis = SystemClock.elapsedRealtime();
3561         final long clockDiffMillis = mDebugElapsedClockPreviousValue == 0
3562                 ? 0 : elapsedMillis - mDebugElapsedClockPreviousValue;
3563 
3564         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, mDebugElapsedClockPullCount,
3565                 elapsedMillis,
3566                 // Log it twice to be able to test multi-value aggregation from ValueMetric.
3567                 elapsedMillis, clockDiffMillis, 1 /* always set */));
3568 
3569         if (mDebugElapsedClockPullCount % 2 == 1) {
3570             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, mDebugElapsedClockPullCount,
3571                     elapsedMillis,
3572                     // Log it twice to be able to test multi-value aggregation from ValueMetric.
3573                     elapsedMillis, clockDiffMillis, 2 /* set on odd pulls */));
3574         }
3575 
3576         mDebugElapsedClockPullCount++;
3577         mDebugElapsedClockPreviousValue = elapsedMillis;
3578         return StatsManager.PULL_SUCCESS;
3579     }
3580 
3581     private void registerDebugFailingElapsedClock() {
3582         int tagId = FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK;
3583         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
3584                 .setAdditiveFields(new int[]{1, 2, 3, 4})
3585                 .build();
3586         mStatsManager.setPullAtomCallback(
3587                 tagId,
3588                 metadata,
3589                 DIRECT_EXECUTOR,
3590                 mStatsCallbackImpl
3591         );
3592     }
3593 
3594     int pullDebugFailingElapsedClockLocked(int atomTag, List<StatsEvent> pulledData) {
3595         final long elapsedMillis = SystemClock.elapsedRealtime();
3596         // Fails every 5 buckets.
3597         if (mDebugFailingElapsedClockPullCount++ % 5 == 0) {
3598             mDebugFailingElapsedClockPreviousValue = elapsedMillis;
3599             Slog.e(TAG, "Failing debug elapsed clock");
3600             return StatsManager.PULL_SKIP;
3601         }
3602 
3603         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3604                 mDebugFailingElapsedClockPullCount, elapsedMillis,
3605                 // Log it twice to be able to test multi-value aggregation from ValueMetric.
3606                 elapsedMillis,
3607                 mDebugFailingElapsedClockPreviousValue == 0
3608                         ? 0
3609                         : elapsedMillis - mDebugFailingElapsedClockPreviousValue));
3610 
3611         mDebugFailingElapsedClockPreviousValue = elapsedMillis;
3612         return StatsManager.PULL_SUCCESS;
3613     }
3614 
3615     private void registerBuildInformation() {
3616         int tagId = FrameworkStatsLog.BUILD_INFORMATION;
3617         mStatsManager.setPullAtomCallback(
3618                 tagId,
3619                 null, // use default PullAtomMetadata values
3620                 DIRECT_EXECUTOR,
3621                 mStatsCallbackImpl
3622         );
3623     }
3624 
3625     int pullBuildInformationLocked(int atomTag, List<StatsEvent> pulledData) {
3626         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, Build.FINGERPRINT, Build.BRAND,
3627                 Build.PRODUCT, Build.DEVICE, Build.VERSION.RELEASE_OR_CODENAME, Build.ID,
3628                 Build.VERSION.INCREMENTAL, Build.TYPE, Build.TAGS));
3629         return StatsManager.PULL_SUCCESS;
3630     }
3631 
3632     private void registerRoleHolder() {
3633         int tagId = FrameworkStatsLog.ROLE_HOLDER;
3634         mStatsManager.setPullAtomCallback(
3635                 tagId,
3636                 null, // use default PullAtomMetadata values
3637                 DIRECT_EXECUTOR,
3638                 mStatsCallbackImpl
3639         );
3640     }
3641 
3642     // Add a RoleHolder atom for each package that holds a role.
3643     int pullRoleHolderLocked(int atomTag, List<StatsEvent> pulledData) {
3644         final long callingToken = Binder.clearCallingIdentity();
3645         try {
3646             PackageManager pm = mContext.getPackageManager();
3647             RoleManagerLocal roleManagerLocal = LocalManagerRegistry.getManager(
3648                     RoleManagerLocal.class);
3649 
3650             List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
3651 
3652             int numUsers = users.size();
3653             for (int userNum = 0; userNum < numUsers; userNum++) {
3654                 int userId = users.get(userNum).getUserHandle().getIdentifier();
3655 
3656                 Map<String, Set<String>> roles = roleManagerLocal.getRolesAndHolders(userId);
3657 
3658                 for (Map.Entry<String, Set<String>> roleEntry : roles.entrySet()) {
3659                     String roleName = roleEntry.getKey();
3660                     Set<String> packageNames = roleEntry.getValue();
3661 
3662                     if (!packageNames.isEmpty()) {
3663                         for (String packageName : packageNames) {
3664                             int uid = INVALID_UID;
3665                             try {
3666                                 PackageInfo pkg = pm.getPackageInfoAsUser(packageName, 0, userId);
3667                                 uid = pkg.applicationInfo.uid;
3668                             } catch (PackageManager.NameNotFoundException e) {
3669                                 Slog.w(TAG, "Role holder " + packageName + " not found for user "
3670                                         + userId);
3671                             }
3672 
3673                             pulledData.add(FrameworkStatsLog.buildStatsEvent(
3674                                     atomTag, uid, packageName, roleName));
3675                         }
3676                     } else {
3677                         // Ensure that roles set to None are logged with an empty state.
3678                         pulledData.add(FrameworkStatsLog.buildStatsEvent(
3679                                 atomTag, INVALID_UID, "", roleName));
3680                     }
3681                 }
3682             }
3683         } catch (Throwable t) {
3684             Log.e(TAG, "Could not read role holders", t);
3685             return StatsManager.PULL_SKIP;
3686         } finally {
3687             Binder.restoreCallingIdentity(callingToken);
3688         }
3689         return StatsManager.PULL_SUCCESS;
3690     }
3691 
3692     private void registerDangerousPermissionState() {
3693         int tagId = FrameworkStatsLog.DANGEROUS_PERMISSION_STATE;
3694         mStatsManager.setPullAtomCallback(
3695                 tagId,
3696                 null, // use default PullAtomMetadata values
3697                 DIRECT_EXECUTOR,
3698                 mStatsCallbackImpl
3699         );
3700     }
3701 
3702     int pullDangerousPermissionStateLocked(int atomTag, List<StatsEvent> pulledData) {
3703         final long token = Binder.clearCallingIdentity();
3704         float samplingRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_PERMISSIONS,
3705                 DANGEROUS_PERMISSION_STATE_SAMPLE_RATE, 0.015f);
3706         Set<Integer> reportedUids = new HashSet<>();
3707         try {
3708             PackageManager pm = mContext.getPackageManager();
3709 
3710             List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
3711 
3712             int numUsers = users.size();
3713             for (int userNum = 0; userNum < numUsers; userNum++) {
3714                 UserHandle user = users.get(userNum).getUserHandle();
3715 
3716                 List<PackageInfo> pkgs = pm.getInstalledPackagesAsUser(
3717                         PackageManager.GET_PERMISSIONS, user.getIdentifier());
3718 
3719                 int numPkgs = pkgs.size();
3720                 for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
3721                     PackageInfo pkg = pkgs.get(pkgNum);
3722 
3723                     if (pkg.requestedPermissions == null) {
3724                         continue;
3725                     }
3726 
3727                     if (reportedUids.contains(pkg.applicationInfo.uid)) {
3728                         // do not report same uid twice
3729                         continue;
3730                     }
3731                     reportedUids.add(pkg.applicationInfo.uid);
3732 
3733                     if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED
3734                             && ThreadLocalRandom.current().nextFloat() > samplingRate) {
3735                         continue;
3736                     }
3737 
3738                     int numPerms = pkg.requestedPermissions.length;
3739                     for (int permNum = 0; permNum < numPerms; permNum++) {
3740                         String permName = pkg.requestedPermissions[permNum];
3741 
3742                         PermissionInfo permissionInfo;
3743                         int permissionFlags = 0;
3744                         try {
3745                             permissionInfo = pm.getPermissionInfo(permName, 0);
3746                             permissionFlags =
3747                                     pm.getPermissionFlags(permName, pkg.packageName, user);
3748                         } catch (PackageManager.NameNotFoundException ignored) {
3749                             continue;
3750                         }
3751 
3752                         if (permName.startsWith(COMMON_PERMISSION_PREFIX)) {
3753                             permName = permName.substring(COMMON_PERMISSION_PREFIX.length());
3754                         }
3755 
3756                         StatsEvent e;
3757                         if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE) {
3758                             e = FrameworkStatsLog.buildStatsEvent(atomTag, permName,
3759                                     pkg.applicationInfo.uid, "",
3760                                     (pkg.requestedPermissionsFlags[permNum]
3761                                             & REQUESTED_PERMISSION_GRANTED)
3762                                             != 0,
3763                                     permissionFlags, permissionInfo.getProtection()
3764                                             | permissionInfo.getProtectionFlags());
3765                         } else {
3766                             // DangeorusPermissionStateSampled atom.
3767                             e = FrameworkStatsLog.buildStatsEvent(atomTag, permName,
3768                                     pkg.applicationInfo.uid,
3769                                     (pkg.requestedPermissionsFlags[permNum]
3770                                             & REQUESTED_PERMISSION_GRANTED)
3771                                             != 0,
3772                                     permissionFlags, permissionInfo.getProtection()
3773                                             | permissionInfo.getProtectionFlags());
3774                         }
3775                         pulledData.add(e);
3776                     }
3777                 }
3778             }
3779         } catch (Throwable t) {
3780             Log.e(TAG, "Could not read permissions", t);
3781             return StatsManager.PULL_SKIP;
3782         } finally {
3783             Binder.restoreCallingIdentity(token);
3784         }
3785         return StatsManager.PULL_SUCCESS;
3786     }
3787 
3788     private void registerTimeZoneDataInfo() {
3789         int tagId = FrameworkStatsLog.TIME_ZONE_DATA_INFO;
3790         mStatsManager.setPullAtomCallback(
3791                 tagId,
3792                 null, // use default PullAtomMetadata values
3793                 DIRECT_EXECUTOR,
3794                 mStatsCallbackImpl
3795         );
3796     }
3797 
3798     int pullTimeZoneDataInfoLocked(int atomTag, List<StatsEvent> pulledData) {
3799         String tzDbVersion = "Unknown";
3800         try {
3801             tzDbVersion = android.icu.util.TimeZone.getTZDataVersion();
3802         } catch (MissingResourceException e) {
3803             Slog.e(TAG, "Getting tzdb version failed: ", e);
3804             return StatsManager.PULL_SKIP;
3805         }
3806 
3807         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, tzDbVersion));
3808         return StatsManager.PULL_SUCCESS;
3809     }
3810 
3811     private void registerTimeZoneDetectorState() {
3812         int tagId = FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE;
3813         mStatsManager.setPullAtomCallback(
3814                 tagId,
3815                 null, // use default PullAtomMetadata values
3816                 DIRECT_EXECUTOR,
3817                 mStatsCallbackImpl
3818         );
3819     }
3820 
3821     int pullTimeZoneDetectorStateLocked(int atomTag, List<StatsEvent> pulledData) {
3822         final long token = Binder.clearCallingIdentity();
3823         try {
3824             TimeZoneDetectorInternal timeZoneDetectorInternal =
3825                     LocalServices.getService(TimeZoneDetectorInternal.class);
3826             MetricsTimeZoneDetectorState metricsState =
3827                     timeZoneDetectorInternal.generateMetricsState();
3828             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
3829                     metricsState.isTelephonyDetectionSupported(),
3830                     metricsState.isGeoDetectionSupported(),
3831                     metricsState.getUserLocationEnabledSetting(),
3832                     metricsState.getAutoDetectionEnabledSetting(),
3833                     metricsState.getGeoDetectionEnabledSetting(),
3834                     convertToMetricsDetectionMode(metricsState.getDetectionMode()),
3835                     metricsState.getDeviceTimeZoneIdOrdinal(),
3836                     convertTimeZoneSuggestionToProtoBytes(
3837                             metricsState.getLatestManualSuggestion()),
3838                     convertTimeZoneSuggestionToProtoBytes(
3839                             metricsState.getLatestTelephonySuggestion()),
3840                     convertTimeZoneSuggestionToProtoBytes(
3841                             metricsState.getLatestGeolocationSuggestion()),
3842                     metricsState.isTelephonyTimeZoneFallbackSupported(),
3843                     metricsState.getDeviceTimeZoneId(),
3844                     metricsState.isEnhancedMetricsCollectionEnabled(),
3845                     metricsState.getGeoDetectionRunInBackgroundEnabled()
3846             ));
3847         } catch (RuntimeException e) {
3848             Slog.e(TAG, "Getting time zone detection state failed: ", e);
3849             return StatsManager.PULL_SKIP;
3850         } finally {
3851             Binder.restoreCallingIdentity(token);
3852         }
3853         return StatsManager.PULL_SUCCESS;
3854     }
3855 
3856     private static int convertToMetricsDetectionMode(
3857             @MetricsTimeZoneDetectorState.DetectionMode int detectionMode) {
3858         switch (detectionMode) {
3859             case MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL:
3860                 return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
3861             case MetricsTimeZoneDetectorState.DETECTION_MODE_GEO:
3862                 return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__GEO;
3863             case MetricsTimeZoneDetectorState.DETECTION_MODE_TELEPHONY:
3864                 return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY;
3865             default:
3866                 return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN;
3867         }
3868     }
3869 
3870     @Nullable
3871     private static byte[] convertTimeZoneSuggestionToProtoBytes(
3872             @Nullable MetricsTimeZoneDetectorState.MetricsTimeZoneSuggestion suggestion) {
3873         if (suggestion == null) {
3874             return null;
3875         }
3876 
3877         // We don't get access to the atoms.proto definition for nested proto fields, so we use
3878         // an identically specified proto.
3879         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
3880         ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
3881         int typeProtoValue = suggestion.isCertain()
3882                 ? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
3883                 : android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
3884         protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
3885                 typeProtoValue);
3886         if (suggestion.isCertain()) {
3887             for (int zoneIdOrdinal : suggestion.getZoneIdOrdinals()) {
3888                 protoOutputStream.write(
3889                         android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
3890                         zoneIdOrdinal);
3891             }
3892             String[] zoneIds = suggestion.getZoneIds();
3893             if (zoneIds != null) {
3894                 for (String zoneId : zoneIds) {
3895                     protoOutputStream.write(
3896                             android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_IDS,
3897                             zoneId);
3898                 }
3899             }
3900         }
3901         protoOutputStream.flush();
3902         closeQuietly(byteArrayOutputStream);
3903         return byteArrayOutputStream.toByteArray();
3904     }
3905 
3906     private void registerExternalStorageInfo() {
3907         int tagId = FrameworkStatsLog.EXTERNAL_STORAGE_INFO;
3908         mStatsManager.setPullAtomCallback(
3909                 tagId,
3910                 null, // use default PullAtomMetadata values
3911                 DIRECT_EXECUTOR,
3912                 mStatsCallbackImpl
3913         );
3914     }
3915 
3916     int pullExternalStorageInfoLocked(int atomTag, List<StatsEvent> pulledData) {
3917         if (mStorageManager == null) {
3918             return StatsManager.PULL_SKIP;
3919         }
3920 
3921         List<VolumeInfo> volumes = mStorageManager.getVolumes();
3922         for (VolumeInfo vol : volumes) {
3923             final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
3924             final DiskInfo diskInfo = vol.getDisk();
3925             if (diskInfo != null && envState.equals(Environment.MEDIA_MOUNTED)) {
3926                 // Get the type of the volume, if it is adoptable or portable.
3927                 int volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER;
3928                 if (vol.getType() == TYPE_PUBLIC) {
3929                     volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC;
3930                 } else if (vol.getType() == TYPE_PRIVATE) {
3931                     volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE;
3932                 }
3933 
3934                 // Get the type of external storage inserted in the device (sd cards, usb, etc.)
3935                 int externalStorageType;
3936                 if (diskInfo.isSd()) {
3937                     externalStorageType = StorageEnums.SD_CARD;
3938                 } else if (diskInfo.isUsb()) {
3939                     externalStorageType = StorageEnums.USB;
3940                 } else {
3941                     externalStorageType = StorageEnums.OTHER;
3942                 }
3943 
3944                 pulledData.add(FrameworkStatsLog.buildStatsEvent(
3945                         atomTag, externalStorageType, volumeType, diskInfo.size));
3946             }
3947         }
3948         return StatsManager.PULL_SUCCESS;
3949     }
3950 
3951     private void registerAppsOnExternalStorageInfo() {
3952         int tagId = FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO;
3953         mStatsManager.setPullAtomCallback(
3954                 tagId,
3955                 null, // use default PullAtomMetadata values
3956                 DIRECT_EXECUTOR,
3957                 mStatsCallbackImpl
3958         );
3959     }
3960 
3961     int pullAppsOnExternalStorageInfoLocked(int atomTag, List<StatsEvent> pulledData) {
3962         if (mStorageManager == null) {
3963             return StatsManager.PULL_SKIP;
3964         }
3965 
3966         PackageManager pm = mContext.getPackageManager();
3967         List<ApplicationInfo> apps = pm.getInstalledApplications(/*flags=*/ 0);
3968         for (ApplicationInfo appInfo : apps) {
3969             UUID storageUuid = appInfo.storageUuid;
3970             if (storageUuid == null) {
3971                 continue;
3972             }
3973 
3974             VolumeInfo volumeInfo = mStorageManager.findVolumeByUuid(
3975                     appInfo.storageUuid.toString());
3976             if (volumeInfo == null) {
3977                 continue;
3978             }
3979 
3980             DiskInfo diskInfo = volumeInfo.getDisk();
3981             if (diskInfo == null) {
3982                 continue;
3983             }
3984 
3985             int externalStorageType = -1;
3986             if (diskInfo.isSd()) {
3987                 externalStorageType = StorageEnums.SD_CARD;
3988             } else if (diskInfo.isUsb()) {
3989                 externalStorageType = StorageEnums.USB;
3990             } else if (appInfo.isExternal()) {
3991                 externalStorageType = StorageEnums.OTHER;
3992             }
3993 
3994             // App is installed on external storage.
3995             if (externalStorageType != -1) {
3996                 pulledData.add(FrameworkStatsLog.buildStatsEvent(
3997                         atomTag, externalStorageType, appInfo.packageName));
3998             }
3999         }
4000         return StatsManager.PULL_SUCCESS;
4001     }
4002 
4003     private void registerFaceSettings() {
4004         int tagId = FrameworkStatsLog.FACE_SETTINGS;
4005         mStatsManager.setPullAtomCallback(
4006                 tagId,
4007                 null, // use default PullAtomMetadata values
4008                 DIRECT_EXECUTOR,
4009                 mStatsCallbackImpl
4010         );
4011     }
4012 
4013     int pullFaceSettingsLocked(int atomTag, List<StatsEvent> pulledData) {
4014         final long callingToken = Binder.clearCallingIdentity();
4015         try {
4016             UserManager manager = mContext.getSystemService(UserManager.class);
4017             if (manager == null) {
4018                 return StatsManager.PULL_SKIP;
4019             }
4020             List<UserInfo> users = manager.getUsers();
4021             int numUsers = users.size();
4022             for (int userNum = 0; userNum < numUsers; userNum++) {
4023                 int userId = users.get(userNum).getUserHandle().getIdentifier();
4024 
4025                 int unlockKeyguardEnabled = Settings.Secure.getIntForUser(
4026                         mContext.getContentResolver(),
4027                         Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED, 1, userId);
4028                 int unlockDismissesKeyguard = Settings.Secure.getIntForUser(
4029                         mContext.getContentResolver(),
4030                         Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 1, userId);
4031                 int unlockAttentionRequired = Settings.Secure.getIntForUser(
4032                         mContext.getContentResolver(),
4033                         Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, 0, userId);
4034                 int unlockAppEnabled = Settings.Secure.getIntForUser(
4035                         mContext.getContentResolver(),
4036                         Settings.Secure.FACE_UNLOCK_APP_ENABLED, 1, userId);
4037                 int unlockAlwaysRequireConfirmation = Settings.Secure.getIntForUser(
4038                         mContext.getContentResolver(),
4039                         Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 0, userId);
4040                 int unlockDiversityRequired = Settings.Secure.getIntForUser(
4041                         mContext.getContentResolver(),
4042                         Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED, 1, userId);
4043 
4044                 pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
4045                         unlockKeyguardEnabled != 0, unlockDismissesKeyguard != 0,
4046                         unlockAttentionRequired != 0, unlockAppEnabled != 0,
4047                         unlockAlwaysRequireConfirmation != 0, unlockDiversityRequired != 0));
4048             }
4049         } finally {
4050             Binder.restoreCallingIdentity(callingToken);
4051         }
4052         return StatsManager.PULL_SUCCESS;
4053     }
4054 
4055     private void registerAppOps() {
4056         int tagId = FrameworkStatsLog.APP_OPS;
4057         mStatsManager.setPullAtomCallback(
4058                 tagId,
4059                 null, // use default PullAtomMetadata values
4060                 DIRECT_EXECUTOR,
4061                 mStatsCallbackImpl
4062         );
4063     }
4064 
4065     private void registerRuntimeAppOpAccessMessage() {
4066         int tagId = FrameworkStatsLog.RUNTIME_APP_OP_ACCESS;
4067         mStatsManager.setPullAtomCallback(
4068                 tagId,
4069                 null, // use default PullAtomMetadata values
4070                 DIRECT_EXECUTOR,
4071                 mStatsCallbackImpl
4072         );
4073     }
4074 
4075     private class AppOpEntry {
4076         public final String mPackageName;
4077         public final String mAttributionTag;
4078         public final int mUid;
4079         public final HistoricalOp mOp;
4080         public final int mHash;
4081 
4082         AppOpEntry(String packageName, @Nullable String attributionTag, HistoricalOp op, int uid) {
4083             mPackageName = packageName;
4084             mAttributionTag = attributionTag;
4085             mUid = uid;
4086             mOp = op;
4087             mHash = ((packageName.hashCode() + RANDOM_SEED) & 0x7fffffff) % 100;
4088         }
4089     }
4090 
4091     int pullAppOpsLocked(int atomTag, List<StatsEvent> pulledData) {
4092         final long token = Binder.clearCallingIdentity();
4093         try {
4094             AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
4095 
4096             CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
4097             HistoricalOpsRequest histOpsRequest = new HistoricalOpsRequest.Builder(0,
4098                     Long.MAX_VALUE).setFlags(OP_FLAGS_PULLED).build();
4099             appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR, ops::complete);
4100             HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
4101                     TimeUnit.MILLISECONDS);
4102 
4103             List<AppOpEntry> opsList = processHistoricalOps(histOps, atomTag, 100);
4104             int samplingRate = sampleAppOps(pulledData, opsList, atomTag, 100);
4105             if (samplingRate != 100) {
4106                 Slog.e(TAG, "Atom 10060 downsampled - too many dimensions");
4107             }
4108         } catch (Throwable t) {
4109             // TODO: catch exceptions at a more granular level
4110             Slog.e(TAG, "Could not read appops", t);
4111             return StatsManager.PULL_SKIP;
4112         } finally {
4113             Binder.restoreCallingIdentity(token);
4114         }
4115         return StatsManager.PULL_SUCCESS;
4116     }
4117 
4118     private int sampleAppOps(List<StatsEvent> pulledData, List<AppOpEntry> opsList, int atomTag,
4119             int samplingRate) {
4120         int nOps = opsList.size();
4121         for (int i = 0; i < nOps; i++) {
4122             AppOpEntry entry = opsList.get(i);
4123             if (entry.mHash >= samplingRate || isHealthAppOp(entry.mOp.getOpCode())) {
4124                 continue;
4125             }
4126             StatsEvent e;
4127             if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
4128                 e = FrameworkStatsLog.buildStatsEvent(atomTag, entry.mUid, entry.mPackageName,
4129                         entry.mAttributionTag, entry.mOp.getOpCode(),
4130                         entry.mOp.getForegroundAccessCount(OP_FLAGS_PULLED),
4131                         entry.mOp.getBackgroundAccessCount(OP_FLAGS_PULLED),
4132                         entry.mOp.getForegroundRejectCount(OP_FLAGS_PULLED),
4133                         entry.mOp.getBackgroundRejectCount(OP_FLAGS_PULLED),
4134                         entry.mOp.getForegroundAccessDuration(OP_FLAGS_PULLED),
4135                         entry.mOp.getBackgroundAccessDuration(OP_FLAGS_PULLED),
4136                         mDangerousAppOpsList.contains(entry.mOp.getOpCode()), samplingRate);
4137             } else {
4138                 // AppOps atom.
4139                 e = FrameworkStatsLog.buildStatsEvent(atomTag, entry.mUid, entry.mPackageName,
4140                         entry.mOp.getOpCode(), entry.mOp.getForegroundAccessCount(OP_FLAGS_PULLED),
4141                         entry.mOp.getBackgroundAccessCount(OP_FLAGS_PULLED),
4142                         entry.mOp.getForegroundRejectCount(OP_FLAGS_PULLED),
4143                         entry.mOp.getBackgroundRejectCount(OP_FLAGS_PULLED),
4144                         entry.mOp.getForegroundAccessDuration(OP_FLAGS_PULLED),
4145                         entry.mOp.getBackgroundAccessDuration(OP_FLAGS_PULLED),
4146                         mDangerousAppOpsList.contains(entry.mOp.getOpCode()));
4147             }
4148             pulledData.add(e);
4149         }
4150         if (pulledData.size() > DIMENSION_KEY_SIZE_HARD_LIMIT) {
4151             int adjustedSamplingRate = constrain(
4152                     samplingRate * DIMENSION_KEY_SIZE_SOFT_LIMIT / pulledData.size(), 0,
4153                     samplingRate - 1);
4154             pulledData.clear();
4155             return sampleAppOps(pulledData, opsList, atomTag, adjustedSamplingRate);
4156         }
4157         return samplingRate;
4158     }
4159 
4160     private void registerAttributedAppOps() {
4161         int tagId = FrameworkStatsLog.ATTRIBUTED_APP_OPS;
4162         mStatsManager.setPullAtomCallback(
4163                 tagId,
4164                 null, // use default PullAtomMetadata values
4165                 DIRECT_EXECUTOR,
4166                 mStatsCallbackImpl
4167         );
4168     }
4169 
4170     int pullAttributedAppOpsLocked(int atomTag, List<StatsEvent> pulledData) {
4171         final long token = Binder.clearCallingIdentity();
4172         try {
4173             AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
4174             CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
4175             HistoricalOpsRequest histOpsRequest =
4176                     new HistoricalOpsRequest.Builder(0, Long.MAX_VALUE).setFlags(
4177                             OP_FLAGS_PULLED).build();
4178 
4179             appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR, ops::complete);
4180             HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
4181                     TimeUnit.MILLISECONDS);
4182 
4183             if (mAppOpsSamplingRate == 0) {
4184                 mContext.getMainThreadHandler().postDelayed(new Runnable() {
4185                     @Override
4186                     public void run() {
4187                         try {
4188                             estimateAppOpsSamplingRate();
4189                         } catch (Throwable e) {
4190                             Slog.e(TAG, "AppOps sampling ratio estimation failed: ", e);
4191                             synchronized (mAttributedAppOpsLock) {
4192                                 mAppOpsSamplingRate = min(mAppOpsSamplingRate, 10);
4193                             }
4194                         }
4195                     }
4196                 }, APP_OPS_SAMPLING_INITIALIZATION_DELAY_MILLIS);
4197                 mAppOpsSamplingRate = 100;
4198             }
4199 
4200             List<AppOpEntry> opsList =
4201                     processHistoricalOps(histOps, atomTag, mAppOpsSamplingRate);
4202 
4203             int newSamplingRate = sampleAppOps(pulledData, opsList, atomTag, mAppOpsSamplingRate);
4204 
4205             mAppOpsSamplingRate = min(mAppOpsSamplingRate, newSamplingRate);
4206         } catch (Throwable t) {
4207             // TODO: catch exceptions at a more granular level
4208             Slog.e(TAG, "Could not read appops", t);
4209             return StatsManager.PULL_SKIP;
4210         } finally {
4211             Binder.restoreCallingIdentity(token);
4212         }
4213         return StatsManager.PULL_SUCCESS;
4214     }
4215 
4216     private void estimateAppOpsSamplingRate() throws Exception {
4217         int appOpsTargetCollectionSize = DeviceConfig.getInt(
4218                 DeviceConfig.NAMESPACE_PERMISSIONS, APP_OPS_TARGET_COLLECTION_SIZE,
4219                 APP_OPS_SIZE_ESTIMATE);
4220         AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
4221 
4222         CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
4223         HistoricalOpsRequest histOpsRequest =
4224                 new HistoricalOpsRequest.Builder(
4225                         Math.max(Instant.now().minus(1, ChronoUnit.DAYS).toEpochMilli(), 0),
4226                         Long.MAX_VALUE).setFlags(
4227                         OP_FLAGS_PULLED).build();
4228         appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR, ops::complete);
4229         HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
4230                 TimeUnit.MILLISECONDS);
4231         List<AppOpEntry> opsList =
4232                 processHistoricalOps(histOps, FrameworkStatsLog.ATTRIBUTED_APP_OPS, 100);
4233 
4234         long estimatedSize = 0;
4235         int nOps = opsList.size();
4236         for (int i = 0; i < nOps; i++) {
4237             AppOpEntry entry = opsList.get(i);
4238             estimatedSize += 32 + entry.mPackageName.length() + (entry.mAttributionTag == null ? 1
4239                     : entry.mAttributionTag.length());
4240 
4241         }
4242         int estimatedSamplingRate = (int) constrain(
4243                 appOpsTargetCollectionSize * 100 / estimatedSize, 0, 100);
4244         synchronized (mAttributedAppOpsLock) {
4245             mAppOpsSamplingRate = min(mAppOpsSamplingRate, estimatedSamplingRate);
4246         }
4247     }
4248 
4249     private List<AppOpEntry> processHistoricalOps(
4250             HistoricalOps histOps, int atomTag, int samplingRatio) {
4251         List<AppOpEntry> opsList = new ArrayList<>();
4252         for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
4253             final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
4254             final int uid = uidOps.getUid();
4255             for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
4256                 final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
4257                 if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
4258                     for (int attributionIdx = 0;
4259                             attributionIdx < packageOps.getAttributedOpsCount(); attributionIdx++) {
4260                         final AppOpsManager.AttributedHistoricalOps attributedOps =
4261                                 packageOps.getAttributedOpsAt(attributionIdx);
4262                         for (int opIdx = 0; opIdx < attributedOps.getOpCount(); opIdx++) {
4263                             final AppOpsManager.HistoricalOp op = attributedOps.getOpAt(opIdx);
4264                             processHistoricalOp(op, opsList, uid, samplingRatio,
4265                                     packageOps.getPackageName(), attributedOps.getTag());
4266                         }
4267                     }
4268                 } else if (atomTag == FrameworkStatsLog.APP_OPS) {
4269                     for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) {
4270                         final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx);
4271                         processHistoricalOp(op, opsList, uid, samplingRatio,
4272                                 packageOps.getPackageName(), null);
4273                     }
4274                 }
4275             }
4276         }
4277         return opsList;
4278     }
4279 
4280     private void processHistoricalOp(AppOpsManager.HistoricalOp op,
4281             List<AppOpEntry> opsList, int uid, int samplingRatio, String packageName,
4282             @Nullable String attributionTag) {
4283         int firstChar = 0;
4284         if (attributionTag != null && attributionTag.startsWith(packageName)) {
4285             firstChar = packageName.length();
4286             if (firstChar < attributionTag.length() && attributionTag.charAt(firstChar) == '.') {
4287                 firstChar++;
4288             }
4289         }
4290         AppOpEntry entry = new AppOpEntry(packageName,
4291                 attributionTag == null ? null : attributionTag.substring(firstChar), op,
4292                 uid);
4293         if (entry.mHash < samplingRatio) {
4294             opsList.add(entry);
4295         }
4296     }
4297 
4298     int pullRuntimeAppOpAccessMessageLocked(int atomTag, List<StatsEvent> pulledData) {
4299         final long token = Binder.clearCallingIdentity();
4300         try {
4301             AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
4302 
4303             RuntimeAppOpAccessMessage message = appOps.collectRuntimeAppOpAccessMessage();
4304             if (message == null) {
4305                 Slog.i(TAG, "No runtime appop access message collected");
4306                 return StatsManager.PULL_SUCCESS;
4307             }
4308 
4309             if (isHealthAppOp(AppOpsManager.strOpToOp(message.getOp()))) {
4310                 // Not log sensitive health app ops.
4311                 return StatsManager.PULL_SKIP;
4312             }
4313 
4314             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, message.getUid(),
4315                     message.getPackageName(), "",
4316                     message.getAttributionTag() == null ? "" : message.getAttributionTag(),
4317                     message.getMessage(), message.getSamplingStrategy(),
4318                     AppOpsManager.strOpToOp(message.getOp())));
4319         } catch (Throwable t) {
4320             // TODO: catch exceptions at a more granular level
4321             Slog.e(TAG, "Could not read runtime appop access message", t);
4322             return StatsManager.PULL_SKIP;
4323         } finally {
4324             Binder.restoreCallingIdentity(token);
4325         }
4326         return StatsManager.PULL_SUCCESS;
4327     }
4328 
4329     static void unpackStreamedData(int atomTag, List<StatsEvent> pulledData,
4330             List<ParcelFileDescriptor> statsFiles) throws IOException {
4331         InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0));
4332         int[] len = new int[1];
4333         byte[] stats = readFully(stream, len);
4334         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, Arrays.copyOf(stats, len[0])));
4335     }
4336 
4337     static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
4338         int pos = 0;
4339         final int initialAvail = stream.available();
4340         byte[] data = new byte[initialAvail > 0 ? (initialAvail + 1) : 16384];
4341         while (true) {
4342             int amt = stream.read(data, pos, data.length - pos);
4343             if (DEBUG) {
4344                 Slog.i(TAG, "Read " + amt + " bytes at " + pos + " of avail " + data.length);
4345             }
4346             if (amt < 0) {
4347                 if (DEBUG) {
4348                     Slog.i(TAG, "**** FINISHED READING: pos=" + pos + " len=" + data.length);
4349                 }
4350                 outLen[0] = pos;
4351                 return data;
4352             }
4353             pos += amt;
4354             if (pos >= data.length) {
4355                 byte[] newData = new byte[pos + 16384];
4356                 if (DEBUG) {
4357                     Slog.i(TAG, "Copying " + pos + " bytes to new array len " + newData.length);
4358                 }
4359                 System.arraycopy(data, 0, newData, 0, pos);
4360                 data = newData;
4361             }
4362         }
4363     }
4364 
4365     private void registerNotificationRemoteViews() {
4366         int tagId = FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS;
4367         mStatsManager.setPullAtomCallback(
4368                 tagId,
4369                 null, // use default PullAtomMetadata values
4370                 DIRECT_EXECUTOR,
4371                 mStatsCallbackImpl
4372         );
4373     }
4374 
4375     int pullNotificationRemoteViewsLocked(int atomTag, List<StatsEvent> pulledData) {
4376         INotificationManager notificationManagerService = getINotificationManagerService();
4377         if (notificationManagerService == null) {
4378             return StatsManager.PULL_SKIP;
4379         }
4380         final long callingToken = Binder.clearCallingIdentity();
4381         try {
4382             // determine last pull tine. Copy file trick from pullProcStats?
4383             long wallClockNanos = SystemClock.currentTimeMicro() * 1000L;
4384             long lastNotificationStatsNs = wallClockNanos -
4385                     TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
4386 
4387             List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
4388             notificationManagerService.pullStats(lastNotificationStatsNs,
4389                     NotificationManagerService.REPORT_REMOTE_VIEWS, true, statsFiles);
4390             if (statsFiles.size() != 1) {
4391                 return StatsManager.PULL_SKIP;
4392             }
4393             unpackStreamedData(atomTag, pulledData, statsFiles);
4394         } catch (IOException e) {
4395             Slog.e(TAG, "Getting notistats failed: ", e);
4396             return StatsManager.PULL_SKIP;
4397         } catch (RemoteException e) {
4398             Slog.e(TAG, "Getting notistats failed: ", e);
4399             return StatsManager.PULL_SKIP;
4400         } catch (SecurityException e) {
4401             Slog.e(TAG, "Getting notistats failed: ", e);
4402             return StatsManager.PULL_SKIP;
4403         } finally {
4404             Binder.restoreCallingIdentity(callingToken);
4405         }
4406         return StatsManager.PULL_SUCCESS;
4407     }
4408 
4409     private void registerDangerousPermissionStateSampled() {
4410         int tagId = FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED;
4411         mStatsManager.setPullAtomCallback(
4412                 tagId,
4413                 null, // use default PullAtomMetadata values
4414                 DIRECT_EXECUTOR,
4415                 mStatsCallbackImpl
4416         );
4417     }
4418 
4419     private void registerBatteryLevel() {
4420         int tagId = FrameworkStatsLog.BATTERY_LEVEL;
4421         mStatsManager.setPullAtomCallback(
4422                 tagId,
4423                 null, // use default PullAtomMetadata values
4424                 DIRECT_EXECUTOR,
4425                 mStatsCallbackImpl
4426         );
4427     }
4428 
4429     private void registerRemainingBatteryCapacity() {
4430         int tagId = FrameworkStatsLog.REMAINING_BATTERY_CAPACITY;
4431         mStatsManager.setPullAtomCallback(
4432                 tagId,
4433                 null, // use default PullAtomMetadata values
4434                 DIRECT_EXECUTOR,
4435                 mStatsCallbackImpl
4436         );
4437     }
4438 
4439     private void registerFullBatteryCapacity() {
4440         int tagId = FrameworkStatsLog.FULL_BATTERY_CAPACITY;
4441         mStatsManager.setPullAtomCallback(
4442                 tagId,
4443                 null, // use default PullAtomMetadata values
4444                 DIRECT_EXECUTOR,
4445                 mStatsCallbackImpl
4446         );
4447     }
4448 
4449     private void registerBatteryVoltage() {
4450         int tagId = FrameworkStatsLog.BATTERY_VOLTAGE;
4451         mStatsManager.setPullAtomCallback(
4452                 tagId,
4453                 null, // use default PullAtomMetadata values
4454                 DIRECT_EXECUTOR,
4455                 mStatsCallbackImpl
4456         );
4457     }
4458 
4459     private void registerBatteryCycleCount() {
4460         int tagId = FrameworkStatsLog.BATTERY_CYCLE_COUNT;
4461         mStatsManager.setPullAtomCallback(
4462                 tagId,
4463                 null, // use default PullAtomMetadata values
4464                 DIRECT_EXECUTOR,
4465                 mStatsCallbackImpl
4466         );
4467     }
4468 
4469     private void registerBatteryHealth() {
4470         int tagId = FrameworkStatsLog.BATTERY_HEALTH;
4471         mStatsManager.setPullAtomCallback(tagId,
4472                 null, // use default PullAtomMetadata values
4473                 DIRECT_EXECUTOR, mStatsCallbackImpl);
4474     }
4475 
4476     @GuardedBy("mHealthHalLock")
4477     private int pullHealthHalLocked(int atomTag, List<StatsEvent> pulledData) {
4478         if (mHealthService == null) {
4479             return StatsManager.PULL_SKIP;
4480         }
4481         android.hardware.health.HealthInfo healthInfo;
4482         try {
4483             healthInfo = mHealthService.getHealthInfo();
4484         } catch (RemoteException | IllegalStateException e) {
4485             return StatsManager.PULL_SKIP;
4486         }
4487         if (healthInfo == null) {
4488             return StatsManager.PULL_SKIP;
4489         }
4490 
4491         int pulledValue;
4492         switch (atomTag) {
4493             case FrameworkStatsLog.BATTERY_LEVEL:
4494                 pulledValue = healthInfo.batteryLevel;
4495                 break;
4496             case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY:
4497                 pulledValue = healthInfo.batteryChargeCounterUah;
4498                 break;
4499             case FrameworkStatsLog.FULL_BATTERY_CAPACITY:
4500                 pulledValue = healthInfo.batteryFullChargeUah;
4501                 break;
4502             case FrameworkStatsLog.BATTERY_VOLTAGE:
4503                 pulledValue = healthInfo.batteryVoltageMillivolts;
4504                 break;
4505             case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
4506                 pulledValue = healthInfo.batteryCycleCount;
4507                 break;
4508             case FrameworkStatsLog.BATTERY_HEALTH:
4509                 android.hardware.health.BatteryHealthData bhd;
4510                 try {
4511                     bhd = mHealthService.getBatteryHealthData();
4512                 } catch (RemoteException | IllegalStateException e) {
4513                     return StatsManager.PULL_SKIP;
4514                 }
4515                 if (bhd == null) {
4516                     return StatsManager.PULL_SKIP;
4517                 }
4518 
4519                 StatsEvent batteryHealthEvent;
4520                 try {
4521                     BatteryProperty chargeStatusProperty = new BatteryProperty();
4522                     BatteryProperty chargePolicyProperty = new BatteryProperty();
4523 
4524                     if (0 > mHealthService.getProperty(
4525                                 BatteryManager.BATTERY_PROPERTY_STATUS, chargeStatusProperty)) {
4526                         return StatsManager.PULL_SKIP;
4527                     }
4528                     if (0 > mHealthService.getProperty(
4529                                 BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY,
4530                                 chargePolicyProperty)) {
4531                         return StatsManager.PULL_SKIP;
4532                     }
4533                     int chargeStatus = (int) chargeStatusProperty.getLong();
4534                     int chargePolicy = (int) chargePolicyProperty.getLong();
4535                     batteryHealthEvent = BatteryHealthUtility.buildStatsEvent(
4536                             atomTag, bhd, chargeStatus, chargePolicy);
4537                     pulledData.add(batteryHealthEvent);
4538 
4539                     return StatsManager.PULL_SUCCESS;
4540                 } catch (RemoteException | IllegalStateException e) {
4541                     Slog.e(TAG, "Failed to add pulled data", e);
4542                 } catch (NoSuchAlgorithmException e) {
4543                     Slog.e(TAG, "Could not find message digest algorithm", e);
4544                 }
4545                 return StatsManager.PULL_SKIP;
4546             default:
4547                 return StatsManager.PULL_SKIP;
4548         }
4549         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, pulledValue));
4550         return StatsManager.PULL_SUCCESS;
4551     }
4552 
4553     private void registerSettingsStats() {
4554         int tagId = FrameworkStatsLog.SETTING_SNAPSHOT;
4555         mStatsManager.setPullAtomCallback(
4556                 tagId,
4557                 null, // use default PullAtomMetadata values
4558                 DIRECT_EXECUTOR,
4559                 mStatsCallbackImpl
4560         );
4561     }
4562 
4563     int pullSettingsStatsLocked(int atomTag, List<StatsEvent> pulledData) {
4564         UserManager userManager = mContext.getSystemService(UserManager.class);
4565         if (userManager == null) {
4566             return StatsManager.PULL_SKIP;
4567         }
4568 
4569         final long token = Binder.clearCallingIdentity();
4570         try {
4571             for (UserInfo user : userManager.getUsers()) {
4572                 final int userId = user.getUserHandle().getIdentifier();
4573 
4574                 if (userId == UserHandle.USER_SYSTEM) {
4575                     pulledData.addAll(SettingsStatsUtil.logGlobalSettings(mContext, atomTag,
4576                             UserHandle.USER_SYSTEM));
4577                 }
4578                 pulledData.addAll(SettingsStatsUtil.logSystemSettings(mContext, atomTag, userId));
4579                 pulledData.addAll(SettingsStatsUtil.logSecureSettings(mContext, atomTag, userId));
4580             }
4581         } catch (Exception e) {
4582             Slog.e(TAG, "failed to pullSettingsStats", e);
4583             return StatsManager.PULL_SKIP;
4584         } finally {
4585             Binder.restoreCallingIdentity(token);
4586         }
4587         return StatsManager.PULL_SUCCESS;
4588     }
4589 
4590     private void registerInstalledIncrementalPackages() {
4591         int tagId = FrameworkStatsLog.INSTALLED_INCREMENTAL_PACKAGE;
4592         mStatsManager.setPullAtomCallback(
4593                 tagId,
4594                 null, // use default PullAtomMetadata values
4595                 DIRECT_EXECUTOR,
4596                 mStatsCallbackImpl
4597         );
4598     }
4599 
4600     int pullInstalledIncrementalPackagesLocked(int atomTag, List<StatsEvent> pulledData) {
4601         final PackageManager pm = mContext.getPackageManager();
4602         final PackageManagerInternal pmIntenral =
4603                 LocalServices.getService(PackageManagerInternal.class);
4604         if (!pm.hasSystemFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY)) {
4605             // Incremental is not enabled on this device. The result list will be empty.
4606             return StatsManager.PULL_SUCCESS;
4607         }
4608         final long token = Binder.clearCallingIdentity();
4609         try {
4610             final int[] userIds = LocalServices.getService(UserManagerInternal.class).getUserIds();
4611             for (int userId : userIds) {
4612                 final List<PackageInfo> installedPackages = pm.getInstalledPackagesAsUser(
4613                         0, userId);
4614                 for (PackageInfo pi : installedPackages) {
4615                     if (IncrementalManager.isIncrementalPath(
4616                             pi.applicationInfo.getBaseCodePath())) {
4617                         final IncrementalStatesInfo info = pmIntenral.getIncrementalStatesInfo(
4618                                 pi.packageName, SYSTEM_UID, userId);
4619                         pulledData.add(
4620                                 FrameworkStatsLog.buildStatsEvent(atomTag, pi.applicationInfo.uid,
4621                                         info.isLoading(), info.getLoadingCompletedTime()));
4622                     }
4623                 }
4624             }
4625         } catch (Exception e) {
4626             Slog.e(TAG, "failed to pullInstalledIncrementalPackagesLocked", e);
4627             return StatsManager.PULL_SKIP;
4628         } finally {
4629             Binder.restoreCallingIdentity(token);
4630         }
4631         return StatsManager.PULL_SUCCESS;
4632     }
4633 
4634     private void registerKeystoreStorageStats() {
4635         mStatsManager.setPullAtomCallback(
4636                 FrameworkStatsLog.KEYSTORE2_STORAGE_STATS,
4637                 null, // use default PullAtomMetadata values,
4638                 DIRECT_EXECUTOR,
4639                 mStatsCallbackImpl);
4640     }
4641 
4642     private void registerKeystoreKeyCreationWithGeneralInfo() {
4643         mStatsManager.setPullAtomCallback(
4644                 FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO,
4645                 null, // use default PullAtomMetadata values,
4646                 DIRECT_EXECUTOR,
4647                 mStatsCallbackImpl);
4648     }
4649 
4650     private void registerKeystoreKeyCreationWithAuthInfo() {
4651         mStatsManager.setPullAtomCallback(
4652                 FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO,
4653                 null, // use default PullAtomMetadata values,
4654                 DIRECT_EXECUTOR,
4655                 mStatsCallbackImpl);
4656     }
4657 
4658     private void registerKeystoreKeyCreationWithPurposeModesInfo() {
4659         mStatsManager.setPullAtomCallback(
4660                 FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO,
4661                 null, // use default PullAtomMetadata values,
4662                 DIRECT_EXECUTOR,
4663                 mStatsCallbackImpl);
4664     }
4665 
4666     private void registerKeystoreAtomWithOverflow() {
4667         mStatsManager.setPullAtomCallback(
4668                 FrameworkStatsLog.KEYSTORE2_ATOM_WITH_OVERFLOW,
4669                 null, // use default PullAtomMetadata values,
4670                 DIRECT_EXECUTOR,
4671                 mStatsCallbackImpl);
4672     }
4673 
4674     private void registerKeystoreKeyOperationWithPurposeAndModesInfo() {
4675         mStatsManager.setPullAtomCallback(
4676                 FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO,
4677                 null, // use default PullAtomMetadata values,
4678                 DIRECT_EXECUTOR,
4679                 mStatsCallbackImpl);
4680     }
4681 
4682     private void registerKeystoreKeyOperationWithGeneralInfo() {
4683         mStatsManager.setPullAtomCallback(
4684                 FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO,
4685                 null, // use default PullAtomMetadata values,
4686                 DIRECT_EXECUTOR,
4687                 mStatsCallbackImpl);
4688     }
4689 
4690     private void registerRkpErrorStats() {
4691         mStatsManager.setPullAtomCallback(
4692                 FrameworkStatsLog.RKP_ERROR_STATS,
4693                 null, // use default PullAtomMetadata values,
4694                 DIRECT_EXECUTOR,
4695                 mStatsCallbackImpl);
4696     }
4697 
4698     private void registerKeystoreCrashStats() {
4699         mStatsManager.setPullAtomCallback(
4700                 FrameworkStatsLog.KEYSTORE2_CRASH_STATS,
4701                 null, // use default PullAtomMetadata values,
4702                 DIRECT_EXECUTOR,
4703                 mStatsCallbackImpl);
4704     }
4705 
4706     private void registerAccessibilityShortcutStats() {
4707         int tagId = FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS;
4708         mStatsManager.setPullAtomCallback(
4709                 tagId,
4710                 null, // use default PullAtomMetadata values
4711                 DIRECT_EXECUTOR,
4712                 mStatsCallbackImpl
4713         );
4714     }
4715 
4716     private void registerAccessibilityFloatingMenuStats() {
4717         int tagId = FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS;
4718         mStatsManager.setPullAtomCallback(
4719                 tagId,
4720                 null, // use default PullAtomMetadata values
4721                 DIRECT_EXECUTOR,
4722                 mStatsCallbackImpl
4723         );
4724     }
4725 
4726     private void registerMediaCapabilitiesStats() {
4727         int tagId = FrameworkStatsLog.MEDIA_CAPABILITIES;
4728         mStatsManager.setPullAtomCallback(
4729                 tagId,
4730                 null, // use default PullAtomMetadata values
4731                 DIRECT_EXECUTOR,
4732                 mStatsCallbackImpl
4733         );
4734     }
4735 
4736     int parseKeystoreStorageStats(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
4737         for (KeystoreAtom atomWrapper : atoms) {
4738             if (atomWrapper.payload.getTag() != KeystoreAtomPayload.storageStats) {
4739                 return StatsManager.PULL_SKIP;
4740             }
4741             StorageStats atom = atomWrapper.payload.getStorageStats();
4742             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4743                     FrameworkStatsLog.KEYSTORE2_STORAGE_STATS, atom.storage_type,
4744                     atom.size, atom.unused_size));
4745         }
4746         return StatsManager.PULL_SUCCESS;
4747     }
4748 
4749     int parseKeystoreKeyCreationWithGeneralInfo(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
4750         for (KeystoreAtom atomWrapper : atoms) {
4751             if (atomWrapper.payload.getTag()
4752                     != KeystoreAtomPayload.keyCreationWithGeneralInfo) {
4753                 return StatsManager.PULL_SKIP;
4754             }
4755             KeyCreationWithGeneralInfo atom = atomWrapper.payload.getKeyCreationWithGeneralInfo();
4756             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4757                     FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO, atom.algorithm,
4758                     atom.key_size, atom.ec_curve, atom.key_origin, atom.error_code,
4759                     atom.attestation_requested, atomWrapper.count));
4760         }
4761         return StatsManager.PULL_SUCCESS;
4762     }
4763 
4764     int parseKeystoreKeyCreationWithAuthInfo(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
4765         for (KeystoreAtom atomWrapper : atoms) {
4766             if (atomWrapper.payload.getTag() != KeystoreAtomPayload.keyCreationWithAuthInfo) {
4767                 return StatsManager.PULL_SKIP;
4768             }
4769             KeyCreationWithAuthInfo atom = atomWrapper.payload.getKeyCreationWithAuthInfo();
4770             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4771                     FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO, atom.user_auth_type,
4772                     atom.log10_auth_key_timeout_seconds, atom.security_level, atomWrapper.count));
4773         }
4774         return StatsManager.PULL_SUCCESS;
4775     }
4776 
4777 
4778     int parseKeystoreKeyCreationWithPurposeModesInfo(KeystoreAtom[] atoms,
4779             List<StatsEvent> pulledData) {
4780         for (KeystoreAtom atomWrapper : atoms) {
4781             if (atomWrapper.payload.getTag()
4782                     != KeystoreAtomPayload.keyCreationWithPurposeAndModesInfo) {
4783                 return StatsManager.PULL_SKIP;
4784             }
4785             KeyCreationWithPurposeAndModesInfo atom =
4786                     atomWrapper.payload.getKeyCreationWithPurposeAndModesInfo();
4787             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4788                     FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO,
4789                     atom.algorithm, atom.purpose_bitmap,
4790                     atom.padding_mode_bitmap, atom.digest_bitmap, atom.block_mode_bitmap,
4791                     atomWrapper.count));
4792         }
4793         return StatsManager.PULL_SUCCESS;
4794     }
4795 
4796     int parseKeystoreAtomWithOverflow(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
4797         for (KeystoreAtom atomWrapper : atoms) {
4798             if (atomWrapper.payload.getTag()
4799                     != KeystoreAtomPayload.keystore2AtomWithOverflow) {
4800                 return StatsManager.PULL_SKIP;
4801             }
4802             Keystore2AtomWithOverflow atom = atomWrapper.payload.getKeystore2AtomWithOverflow();
4803             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4804                     FrameworkStatsLog.KEYSTORE2_ATOM_WITH_OVERFLOW, atom.atom_id,
4805                     atomWrapper.count));
4806         }
4807         return StatsManager.PULL_SUCCESS;
4808     }
4809 
4810     int parseKeystoreKeyOperationWithPurposeModesInfo(KeystoreAtom[] atoms,
4811             List<StatsEvent> pulledData) {
4812         for (KeystoreAtom atomWrapper : atoms) {
4813             if (atomWrapper.payload.getTag()
4814                     != KeystoreAtomPayload.keyOperationWithPurposeAndModesInfo) {
4815                 return StatsManager.PULL_SKIP;
4816             }
4817             KeyOperationWithPurposeAndModesInfo atom =
4818                     atomWrapper.payload.getKeyOperationWithPurposeAndModesInfo();
4819             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4820                     FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO,
4821                     atom.purpose, atom.padding_mode_bitmap, atom.digest_bitmap,
4822                     atom.block_mode_bitmap, atomWrapper.count));
4823         }
4824         return StatsManager.PULL_SUCCESS;
4825     }
4826 
4827     int parseKeystoreKeyOperationWithGeneralInfo(KeystoreAtom[] atoms,
4828             List<StatsEvent> pulledData) {
4829         for (KeystoreAtom atomWrapper : atoms) {
4830             if (atomWrapper.payload.getTag()
4831                     != KeystoreAtomPayload.keyOperationWithGeneralInfo) {
4832                 return StatsManager.PULL_SKIP;
4833             }
4834             KeyOperationWithGeneralInfo atom = atomWrapper.payload.getKeyOperationWithGeneralInfo();
4835             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4836                     FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO, atom.outcome,
4837                     atom.error_code, atom.key_upgraded, atom.security_level, atomWrapper.count));
4838         }
4839         return StatsManager.PULL_SUCCESS;
4840     }
4841 
4842     int parseRkpErrorStats(KeystoreAtom[] atoms,
4843             List<StatsEvent> pulledData) {
4844         for (KeystoreAtom atomWrapper : atoms) {
4845             if (atomWrapper.payload.getTag() != KeystoreAtomPayload.rkpErrorStats) {
4846                 return StatsManager.PULL_SKIP;
4847             }
4848             RkpErrorStats atom = atomWrapper.payload.getRkpErrorStats();
4849             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4850                     FrameworkStatsLog.RKP_ERROR_STATS, atom.rkpError, atomWrapper.count,
4851                     atom.security_level));
4852         }
4853         return StatsManager.PULL_SUCCESS;
4854     }
4855 
4856     int parseKeystoreCrashStats(KeystoreAtom[] atoms,
4857             List<StatsEvent> pulledData) {
4858         for (KeystoreAtom atomWrapper : atoms) {
4859             if (atomWrapper.payload.getTag() != KeystoreAtomPayload.crashStats) {
4860                 return StatsManager.PULL_SKIP;
4861             }
4862             CrashStats atom = atomWrapper.payload.getCrashStats();
4863             pulledData.add(FrameworkStatsLog.buildStatsEvent(
4864                     FrameworkStatsLog.KEYSTORE2_CRASH_STATS, atom.count_of_crash_events));
4865         }
4866         return StatsManager.PULL_SUCCESS;
4867     }
4868 
4869     int pullKeystoreAtoms(int atomTag, List<StatsEvent> pulledData) {
4870         IKeystoreMetrics keystoreMetricsService = getIKeystoreMetricsService();
4871         if (keystoreMetricsService == null) {
4872             Slog.w(TAG, "Keystore service is null");
4873             return StatsManager.PULL_SKIP;
4874         }
4875         final long callingToken = Binder.clearCallingIdentity();
4876         try {
4877             KeystoreAtom[] atoms = keystoreMetricsService.pullMetrics(atomTag);
4878             switch (atomTag) {
4879                 case FrameworkStatsLog.KEYSTORE2_STORAGE_STATS:
4880                     return parseKeystoreStorageStats(atoms, pulledData);
4881                 case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO:
4882                     return parseKeystoreKeyCreationWithGeneralInfo(atoms, pulledData);
4883                 case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO:
4884                     return parseKeystoreKeyCreationWithAuthInfo(atoms, pulledData);
4885                 case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO:
4886                     return parseKeystoreKeyCreationWithPurposeModesInfo(atoms, pulledData);
4887                 case FrameworkStatsLog.KEYSTORE2_ATOM_WITH_OVERFLOW:
4888                     return parseKeystoreAtomWithOverflow(atoms, pulledData);
4889                 case FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_PURPOSE_AND_MODES_INFO:
4890                     return parseKeystoreKeyOperationWithPurposeModesInfo(atoms, pulledData);
4891                 case FrameworkStatsLog.KEYSTORE2_KEY_OPERATION_WITH_GENERAL_INFO:
4892                     return parseKeystoreKeyOperationWithGeneralInfo(atoms, pulledData);
4893                 case FrameworkStatsLog.RKP_ERROR_STATS:
4894                     return parseRkpErrorStats(atoms, pulledData);
4895                 case FrameworkStatsLog.KEYSTORE2_CRASH_STATS:
4896                     return parseKeystoreCrashStats(atoms, pulledData);
4897                 default:
4898                     Slog.w(TAG, "Unsupported keystore atom: " + atomTag);
4899                     return StatsManager.PULL_SKIP;
4900             }
4901         } catch (RemoteException e) {
4902             // Should not happen.
4903             Slog.e(TAG, "Disconnected from keystore service. Cannot pull.", e);
4904             return StatsManager.PULL_SKIP;
4905         } catch (ServiceSpecificException e) {
4906             Slog.e(TAG, "Pulling keystore atom with tag " + atomTag + " failed", e);
4907             return StatsManager.PULL_SKIP;
4908         } finally {
4909             Binder.restoreCallingIdentity(callingToken);
4910         }
4911     }
4912 
4913     /**
4914      * Pulls ACCESSIBILITY_SHORTCUT_STATS atom
4915      */
4916     int pullAccessibilityShortcutStatsLocked(List<StatsEvent> pulledData) {
4917         UserManager userManager = mContext.getSystemService(UserManager.class);
4918         if (userManager == null) {
4919             return StatsManager.PULL_SKIP;
4920         }
4921         final long token = Binder.clearCallingIdentity();
4922         try {
4923             final ContentResolver resolver = mContext.getContentResolver();
4924             for (UserInfo userInfo : userManager.getUsers()) {
4925                 final int userId = userInfo.getUserHandle().getIdentifier();
4926 
4927                 if (isAccessibilityShortcutUser(mContext, userId)) {
4928                     final int software_shortcut_type = convertToAccessibilityShortcutType(
4929                             Settings.Secure.getIntForUser(resolver,
4930                                     Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 0, userId));
4931                     final String software_shortcut_list = Settings.Secure.getStringForUser(resolver,
4932                             Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);
4933                     final int software_shortcut_service_num = countAccessibilityServices(
4934                             software_shortcut_list);
4935 
4936                     final String hardware_shortcut_list = Settings.Secure.getStringForUser(resolver,
4937                             Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId);
4938                     final int hardware_shortcut_service_num = countAccessibilityServices(
4939                             hardware_shortcut_list);
4940 
4941                     final String qs_shortcut_list = Settings.Secure.getStringForUser(resolver,
4942                             Settings.Secure.ACCESSIBILITY_QS_TARGETS, userId);
4943                     final boolean qs_shortcut_enabled = !TextUtils.isEmpty(qs_shortcut_list);
4944 
4945                     // only allow magnification to use it for now
4946                     final int triple_tap_service_num = Settings.Secure.getIntForUser(resolver,
4947                             Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0, userId);
4948                     pulledData.add(FrameworkStatsLog.buildStatsEvent(
4949                             FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS,
4950                             software_shortcut_type, software_shortcut_service_num,
4951                             ACCESSIBILITY_SHORTCUT_STATS__HARDWARE_SHORTCUT_TYPE__VOLUME_KEY,
4952                             hardware_shortcut_service_num,
4953                             ACCESSIBILITY_SHORTCUT_STATS__GESTURE_SHORTCUT_TYPE__TRIPLE_TAP,
4954                             triple_tap_service_num,
4955                             ACCESSIBILITY_SHORTCUT_STATS__QS_SHORTCUT_TYPE__QUICK_SETTINGS,
4956                             qs_shortcut_enabled));
4957                 }
4958             }
4959         } catch (RuntimeException e) {
4960             Slog.e(TAG, "pulling accessibility shortcuts stats failed at getUsers", e);
4961             return StatsManager.PULL_SKIP;
4962         } finally {
4963             Binder.restoreCallingIdentity(token);
4964         }
4965         return StatsManager.PULL_SUCCESS;
4966     }
4967 
4968     int pullAccessibilityFloatingMenuStatsLocked(int atomTag, List<StatsEvent> pulledData) {
4969         UserManager userManager = mContext.getSystemService(UserManager.class);
4970         if (userManager == null) {
4971             return StatsManager.PULL_SKIP;
4972         }
4973         final long token = Binder.clearCallingIdentity();
4974         try {
4975             final ContentResolver resolver = mContext.getContentResolver();
4976             final int defaultSize = 0;
4977             final int defaultIconType = 0;
4978             final int defaultFadeEnabled = 1;
4979             final float defaultOpacity = 0.55f;
4980 
4981             for (UserInfo userInfo : userManager.getUsers()) {
4982                 final int userId = userInfo.getUserHandle().getIdentifier();
4983 
4984                 if (isAccessibilityFloatingMenuUser(mContext, userId)) {
4985                     final int size = Settings.Secure.getIntForUser(resolver,
4986                             Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, defaultSize, userId);
4987                     final int type = Settings.Secure.getIntForUser(resolver,
4988                             Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
4989                             defaultIconType, userId);
4990                     final boolean fadeEnabled = (Settings.Secure.getIntForUser(resolver,
4991                             Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
4992                             defaultFadeEnabled, userId)) == 1;
4993                     final float opacity = Settings.Secure.getFloatForUser(resolver,
4994                             Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
4995                             defaultOpacity, userId);
4996 
4997                     pulledData.add(
4998                             FrameworkStatsLog.buildStatsEvent(atomTag, size, type, fadeEnabled,
4999                                     opacity));
5000                 }
5001             }
5002         } catch (RuntimeException e) {
5003             Slog.e(TAG, "pulling accessibility floating menu stats failed at getUsers", e);
5004             return StatsManager.PULL_SKIP;
5005         } finally {
5006             Binder.restoreCallingIdentity(token);
5007         }
5008         return StatsManager.PULL_SUCCESS;
5009     }
5010 
5011     int pullMediaCapabilitiesStats(int atomTag, List<StatsEvent> pulledData) {
5012         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
5013             return StatsManager.PULL_SKIP;
5014         }
5015         AudioManager audioManager = mContext.getSystemService(AudioManager.class);
5016         if (audioManager == null) {
5017             return StatsManager.PULL_SKIP;
5018         }
5019 
5020         // get the surround sound metrics information
5021         Map<Integer, Boolean> surroundEncodingsMap = audioManager.getSurroundFormats();
5022         byte[] surroundEncodings = toBytes(new ArrayList(surroundEncodingsMap.keySet()));
5023         byte[] sinkSurroundEncodings = toBytes(audioManager.getReportedSurroundFormats());
5024         List<Integer> disabledSurroundEncodingsList = new ArrayList<>();
5025         List<Integer> enabledSurroundEncodingsList = new ArrayList<>();
5026         for (int surroundEncoding : surroundEncodingsMap.keySet()) {
5027             if (!audioManager.isSurroundFormatEnabled(surroundEncoding)) {
5028                 disabledSurroundEncodingsList.add(surroundEncoding);
5029             } else {
5030                 enabledSurroundEncodingsList.add(surroundEncoding);
5031             }
5032         }
5033         byte[] disabledSurroundEncodings = toBytes(disabledSurroundEncodingsList);
5034         byte[] enabledSurroundEncodings = toBytes(enabledSurroundEncodingsList);
5035         int surroundOutputMode = audioManager.getEncodedSurroundMode();
5036 
5037         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
5038         Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
5039         // get the display capabilities metrics information
5040         Display.HdrCapabilities hdrCapabilities = display.getHdrCapabilities();
5041         byte[] sinkHdrFormats = new byte[]{};
5042         if (hdrCapabilities != null) {
5043             sinkHdrFormats = toBytes(hdrCapabilities.getSupportedHdrTypes());
5044         }
5045         byte[] sinkDisplayModes = toBytes(display.getSupportedModes());
5046         int hdcpLevel = -1;
5047         List<UUID> uuids = MediaDrm.getSupportedCryptoSchemes();
5048         try {
5049             if (!uuids.isEmpty()) {
5050                 MediaDrm mediaDrm = new MediaDrm(uuids.get(0));
5051                 hdcpLevel = mediaDrm.getConnectedHdcpLevel();
5052             }
5053         } catch (UnsupportedSchemeException exception) {
5054             Slog.e(TAG, "pulling hdcp level failed.", exception);
5055             hdcpLevel = -1;
5056         }
5057 
5058         // get the display settings metrics information
5059         int matchContentFrameRateUserPreference =
5060                 displayManager.getMatchContentFrameRateUserPreference();
5061         byte[] userDisabledHdrTypes = toBytes(displayManager.getUserDisabledHdrTypes());
5062         Display.Mode userPreferredDisplayMode =
5063                 displayManager.getGlobalUserPreferredDisplayMode();
5064         int userPreferredWidth = userPreferredDisplayMode != null
5065                 ? userPreferredDisplayMode.getPhysicalWidth() : -1;
5066         int userPreferredHeight = userPreferredDisplayMode != null
5067                 ? userPreferredDisplayMode.getPhysicalHeight() : -1;
5068         float userPreferredRefreshRate = userPreferredDisplayMode != null
5069                 ? userPreferredDisplayMode.getRefreshRate() : 0.0f;
5070         boolean hasUserDisabledAllm = false;
5071         try {
5072             hasUserDisabledAllm = Settings.Secure.getIntForUser(
5073                     mContext.getContentResolver(),
5074                     Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED,
5075                     1) == 0;
5076         } catch (Settings.SettingNotFoundException exception) {
5077             Slog.e(
5078                     TAG, "unable to find setting for MINIMAL_POST_PROCESSING_ALLOWED.",
5079                     exception);
5080             hasUserDisabledAllm = false;
5081         }
5082 
5083         pulledData.add(
5084                 FrameworkStatsLog.buildStatsEvent(
5085                         atomTag, surroundEncodings, sinkSurroundEncodings,
5086                         disabledSurroundEncodings, enabledSurroundEncodings, surroundOutputMode,
5087                         sinkHdrFormats, sinkDisplayModes, hdcpLevel,
5088                         matchContentFrameRateUserPreference, userDisabledHdrTypes,
5089                         userPreferredWidth, userPreferredHeight, userPreferredRefreshRate,
5090                         hasUserDisabledAllm));
5091 
5092         return StatsManager.PULL_SUCCESS;
5093     }
5094 
5095     private void registerPendingIntentsPerPackagePuller() {
5096         int tagId = FrameworkStatsLog.PENDING_INTENTS_PER_PACKAGE;
5097         mStatsManager.setPullAtomCallback(
5098                 tagId,
5099                 null, // use default PullAtomMetadata values
5100                 DIRECT_EXECUTOR,
5101                 mStatsCallbackImpl
5102         );
5103     }
5104 
5105     private int pullHdrCapabilities(int atomTag, List<StatsEvent> pulledData) {
5106         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
5107         Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
5108 
5109         int hdrConversionMode = displayManager.getHdrConversionMode().getConversionMode();
5110         int preferredHdrType = displayManager.getHdrConversionMode().getPreferredHdrOutputType();
5111         boolean userDisabledHdrConversion = hdrConversionMode == HDR_CONVERSION_PASSTHROUGH;
5112         int forceHdrFormat = preferredHdrType == HDR_TYPE_INVALID ? 0 : preferredHdrType;
5113         boolean hasDolbyVisionIssue = hasDolbyVisionIssue(display);
5114         byte[] hdrOutputTypes = toBytes(displayManager.getSupportedHdrOutputTypes());
5115         boolean hdrOutputControlSupported = hdrConversionMode != HDR_CONVERSION_UNSUPPORTED;
5116 
5117         pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, hdrOutputTypes,
5118                 userDisabledHdrConversion, forceHdrFormat, hasDolbyVisionIssue,
5119                 hdrOutputControlSupported));
5120 
5121         return StatsManager.PULL_SUCCESS;
5122     }
5123 
5124     private int pullCachedAppsHighWatermark(int atomTag, List<StatsEvent> pulledData) {
5125         pulledData.add((StatsEvent) LocalServices.getService(ActivityManagerInternal.class)
5126                 .getCachedAppsHighWatermarkStats(atomTag, true));
5127         return StatsManager.PULL_SUCCESS;
5128     }
5129 
5130     private boolean hasDolbyVisionIssue(Display display) {
5131         AtomicInteger modesSupportingDolbyVision = new AtomicInteger();
5132         Arrays.stream(display.getSupportedModes())
5133                 .map(Display.Mode::getSupportedHdrTypes)
5134                 .filter(types -> Arrays.stream(types).anyMatch(hdrType -> hdrType == DOLBY_VISION))
5135                 .forEach(ignored -> modesSupportingDolbyVision.incrementAndGet());
5136 
5137         if (modesSupportingDolbyVision.get() != 0
5138                 && modesSupportingDolbyVision.get() < display.getSupportedModes().length) {
5139             return true;
5140         }
5141 
5142         return false;
5143     }
5144 
5145     private int pullPendingIntentsPerPackage(int atomTag, List<StatsEvent> pulledData) {
5146         List<PendingIntentStats> pendingIntentStats =
5147                 LocalServices.getService(ActivityManagerInternal.class).getPendingIntentStats();
5148         for (PendingIntentStats stats : pendingIntentStats) {
5149             pulledData.add(FrameworkStatsLog.buildStatsEvent(
5150                     atomTag, stats.uid, stats.count, stats.sizeKb));
5151         }
5152         return StatsManager.PULL_SUCCESS;
5153     }
5154 
5155     private void registerPinnerServiceStats() {
5156         int tagId = FrameworkStatsLog.PINNED_FILE_SIZES_PER_PACKAGE;
5157         mStatsManager.setPullAtomCallback(
5158                 tagId,
5159                 null, // use default PullAtomMetadata values
5160                 DIRECT_EXECUTOR,
5161                 mStatsCallbackImpl
5162         );
5163     }
5164 
5165     private void registerHdrCapabilitiesPuller() {
5166         int tagId = FrameworkStatsLog.HDR_CAPABILITIES;
5167         mStatsManager.setPullAtomCallback(
5168                 tagId,
5169                 null, // use default PullAtomMetadata values
5170                 DIRECT_EXECUTOR,
5171                 mStatsCallbackImpl
5172         );
5173     }
5174 
5175     private void registerCachedAppsHighWatermarkPuller() {
5176         final int tagId = FrameworkStatsLog.CACHED_APPS_HIGH_WATERMARK;
5177         mStatsManager.setPullAtomCallback(
5178                 tagId,
5179                 null, // use default PullAtomMetadata values
5180                 DIRECT_EXECUTOR,
5181                 mStatsCallbackImpl
5182         );
5183     }
5184 
5185     private void registerPressureStallInformation() {
5186         int tagId = FrameworkStatsLog.PRESSURE_STALL_INFORMATION;
5187         mStatsManager.setPullAtomCallback(
5188                 tagId,
5189                 null,
5190                 DIRECT_EXECUTOR,
5191                 mStatsCallbackImpl
5192         );
5193     }
5194 
5195     int pullPressureStallInformation(int atomTag, List<StatsEvent> pulledData) {
5196         PsiExtractor psiExtractor = new PsiExtractor();
5197         for (PsiData.ResourceType resourceType: PsiData.ResourceType.values()) {
5198             PsiData psiData = psiExtractor.getPsiData(resourceType);
5199             if (psiData == null) {
5200                 Slog.e(
5201                         TAG,
5202                         "Failed to pull PressureStallInformation atom for resource: "
5203                                 + resourceType.toString());
5204                 continue;
5205             }
5206             pulledData.add(FrameworkStatsLog.buildStatsEvent(
5207                     atomTag,
5208                     toProtoPsiResourceType(psiData.getResourceType()),
5209                     psiData.getSomeAvg10SecPercentage(),
5210                     psiData.getSomeAvg60SecPercentage(),
5211                     psiData.getSomeAvg300SecPercentage(),
5212                     psiData.getSomeTotalUsec(),
5213                     psiData.getFullAvg10SecPercentage(),
5214                     psiData.getFullAvg60SecPercentage(),
5215                     psiData.getFullAvg300SecPercentage(),
5216                     psiData.getFullTotalUsec()));
5217         }
5218         return StatsManager.PULL_SUCCESS;
5219     }
5220 
5221     private int toProtoPsiResourceType(PsiData.ResourceType resourceType) {
5222         if (resourceType == PsiData.ResourceType.CPU) {
5223             return PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_CPU;
5224         } else if (resourceType == PsiData.ResourceType.MEMORY) {
5225             return PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_MEMORY;
5226         } else if (resourceType == PsiData.ResourceType.IO) {
5227             return PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_IO;
5228         } else {
5229             return PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_UNKNOWN;
5230         }
5231     }
5232 
5233 
5234     int pullSystemServerPinnerStats(int atomTag, List<StatsEvent> pulledData) {
5235         PinnerService pinnerService = LocalServices.getService(PinnerService.class);
5236         List<PinnedFileStats> pinnedFileStats = pinnerService.dumpDataForStatsd();
5237         for (PinnedFileStats pfstats : pinnedFileStats) {
5238             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
5239                     pfstats.uid, pfstats.filename, pfstats.sizeKb));
5240         }
5241         return StatsManager.PULL_SUCCESS;
5242     }
5243 
5244     private byte[] toBytes(List<Integer> audioEncodings) {
5245         ProtoOutputStream protoOutputStream = new ProtoOutputStream();
5246         for (int audioEncoding : audioEncodings) {
5247             protoOutputStream.write(
5248                     ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
5249                     audioEncoding);
5250         }
5251         return protoOutputStream.getBytes();
5252     }
5253 
5254     private byte[] toBytes(int[] array) {
5255         ProtoOutputStream protoOutputStream = new ProtoOutputStream();
5256         for (int element : array) {
5257             protoOutputStream.write(
5258                     ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
5259                     element);
5260         }
5261         return protoOutputStream.getBytes();
5262     }
5263 
5264     private byte[] toBytes(Display.Mode[] displayModes) {
5265         Map<Integer, Integer> modeGroupIds = createModeGroups(displayModes);
5266         ProtoOutputStream protoOutputStream = new ProtoOutputStream();
5267         for (Display.Mode element : displayModes) {
5268             ProtoOutputStream protoOutputStreamMode = new ProtoOutputStream();
5269             protoOutputStreamMode.write(
5270                     ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 1,
5271                     element.getPhysicalHeight());
5272             protoOutputStreamMode.write(
5273                     ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 2,
5274                     element.getPhysicalWidth());
5275             protoOutputStreamMode.write(
5276                     ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_FLOAT | 3,
5277                     element.getRefreshRate());
5278             protoOutputStreamMode.write(
5279                     ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 4,
5280                     modeGroupIds.get(element.getModeId()));
5281             protoOutputStream.write(
5282                     ProtoOutputStream.FIELD_COUNT_REPEATED
5283                             | ProtoOutputStream.FIELD_TYPE_MESSAGE | 1,
5284                     protoOutputStreamMode.getBytes());
5285         }
5286         return protoOutputStream.getBytes();
5287     }
5288 
5289     // Returns map modeId -> groupId such that all modes with the same group have alternative
5290     // refresh rates
5291     private Map<Integer, Integer> createModeGroups(Display.Mode[] supportedModes) {
5292         Map<Integer, Integer> modeGroupIds = new ArrayMap<>();
5293         int groupId = 1;
5294         for (Display.Mode mode : supportedModes) {
5295             if (modeGroupIds.containsKey(mode.getModeId())) {
5296                 continue;
5297             }
5298             modeGroupIds.put(mode.getModeId(), groupId);
5299             for (float refreshRate : mode.getAlternativeRefreshRates()) {
5300                 int alternativeModeId = findModeId(supportedModes, mode.getPhysicalWidth(),
5301                         mode.getPhysicalHeight(), refreshRate);
5302                 if (alternativeModeId != -1 && !modeGroupIds.containsKey(alternativeModeId)) {
5303                     modeGroupIds.put(alternativeModeId, groupId);
5304                 }
5305             }
5306             groupId++;
5307         }
5308         return modeGroupIds;
5309     }
5310 
5311     private int findModeId(Display.Mode[] modes, int width, int height, float refreshRate) {
5312         for (Display.Mode mode : modes) {
5313             if (mode.matches(width, height, refreshRate)) {
5314                 return mode.getModeId();
5315             }
5316         }
5317         return -1;
5318     }
5319 
5320     /**
5321      * Counts how many accessibility services (including features) there are in the colon-separated
5322      * string list.
5323      *
5324      * @param semicolonList colon-separated string, it should be
5325      *                      {@link Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS} or
5326      *                      {@link Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE}.
5327      * @return The number of accessibility services
5328      */
5329     private int countAccessibilityServices(String semicolonList) {
5330         if (TextUtils.isEmpty(semicolonList)) {
5331             return 0;
5332         }
5333         final int semiColonNums = (int) semicolonList.chars().filter(ch -> ch == ':').count();
5334         return TextUtils.isEmpty(semicolonList) ? 0 : semiColonNums + 1;
5335     }
5336 
5337     private boolean isAccessibilityShortcutUser(Context context, @UserIdInt int userId) {
5338         final ContentResolver resolver = context.getContentResolver();
5339 
5340         final String software_shortcut_list = Settings.Secure.getStringForUser(resolver,
5341                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);
5342         final String hardware_shortcut_list = Settings.Secure.getStringForUser(resolver,
5343                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId);
5344         final String qs_shortcut_list = Settings.Secure.getStringForUser(resolver,
5345                 Settings.Secure.ACCESSIBILITY_QS_TARGETS, userId);
5346         final boolean hardware_shortcut_dialog_shown = Settings.Secure.getIntForUser(resolver,
5347                 Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, userId) == 1;
5348         final boolean software_shortcut_enabled = !TextUtils.isEmpty(software_shortcut_list);
5349         final boolean hardware_shortcut_enabled =
5350                 hardware_shortcut_dialog_shown && !TextUtils.isEmpty(hardware_shortcut_list);
5351         final boolean qs_shortcut_enabled = !TextUtils.isEmpty(qs_shortcut_list);
5352         final boolean triple_tap_shortcut_enabled = Settings.Secure.getIntForUser(resolver,
5353                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0, userId) == 1;
5354 
5355         return software_shortcut_enabled || hardware_shortcut_enabled
5356                 || triple_tap_shortcut_enabled || qs_shortcut_enabled;
5357     }
5358 
5359     private boolean isAccessibilityFloatingMenuUser(Context context, @UserIdInt int userId) {
5360         final ContentResolver resolver = context.getContentResolver();
5361         final int mode = Settings.Secure.getIntForUser(resolver,
5362                 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 0, userId);
5363         final String software_string = Settings.Secure.getStringForUser(resolver,
5364                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);
5365 
5366         return (mode == Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU)
5367                 && !TextUtils.isEmpty(software_string);
5368     }
5369 
5370     private int convertToAccessibilityShortcutType(int shortcutType) {
5371         switch (shortcutType) {
5372             case Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR:
5373                 return ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__A11Y_BUTTON;
5374             case Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU:
5375                 return ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__A11Y_FLOATING_MENU;
5376             case Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE:
5377                 return ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__A11Y_GESTURE;
5378             default:
5379                 return ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__UNKNOWN_TYPE;
5380         }
5381     }
5382 
5383     private boolean isHealthAppOp(int opCode) {
5384         String permission = AppOpsManager.opToPermission(opCode);
5385         return permission != null && HealthConnectManager.isHealthPermission(mContext, permission);
5386     }
5387 
5388     // Thermal event received from vendor thermal management subsystem
5389     private static final class ThermalEventListener extends IThermalEventListener.Stub {
5390         @Override
5391         public void notifyThrottling(Temperature temp) {
5392             FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED,
5393                     temp.getType(), temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
5394         }
5395     }
5396 
5397     private static final class ConnectivityStatsCallback extends
5398             ConnectivityManager.NetworkCallback {
5399         @Override
5400         public void onAvailable(Network network) {
5401             FrameworkStatsLog.write(FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED,
5402                     network.getNetId(),
5403                     FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
5404         }
5405 
5406         @Override
5407         public void onLost(Network network) {
5408             FrameworkStatsLog.write(FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED,
5409                     network.getNetId(),
5410                     FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
5411         }
5412     }
5413 
5414     private final class StatsSubscriptionsListener
5415             extends SubscriptionManager.OnSubscriptionsChangedListener {
5416         @NonNull
5417         private final SubscriptionManager mSm;
5418 
5419         StatsSubscriptionsListener(@NonNull SubscriptionManager sm) {
5420             mSm = sm;
5421         }
5422 
5423         @Override
5424         public void onSubscriptionsChanged() {
5425             synchronized (mDataBytesTransferLock) {
5426                 onSubscriptionsChangedLocked();
5427             }
5428         }
5429 
5430         @GuardedBy("mDataBytesTransferLock")
5431         private void onSubscriptionsChangedLocked() {
5432             final List<SubscriptionInfo> currentSubs = mSm.getCompleteActiveSubscriptionInfoList();
5433             for (final SubscriptionInfo sub : currentSubs) {
5434                 final SubInfo match = CollectionUtils.find(mHistoricalSubs,
5435                         (SubInfo it) -> it.subId == sub.getSubscriptionId());
5436                 // SubInfo exists, ignore.
5437                 if (match != null) continue;
5438 
5439                 // Ignore if no valid mcc, mnc, imsi, carrierId.
5440                 final int subId = sub.getSubscriptionId();
5441                 final String mcc = sub.getMccString();
5442                 final String mnc = sub.getMncString();
5443                 final String subscriberId = mTelephony.getSubscriberId(subId);
5444                 if (TextUtils.isEmpty(subscriberId) || TextUtils.isEmpty(mcc)
5445                         || TextUtils.isEmpty(mnc) || sub.getCarrierId() == UNKNOWN_CARRIER_ID) {
5446                     Slog.e(TAG, "subInfo of subId " + subId + " is invalid, ignored.");
5447                     continue;
5448                 }
5449 
5450                 final SubInfo subInfo = new SubInfo(subId, sub.getCarrierId(), mcc, mnc,
5451                         subscriberId, sub.isOpportunistic());
5452                 Slog.i(TAG, "subId " + subId + " added into historical sub list");
5453 
5454                 mHistoricalSubs.add(subInfo);
5455                 // Since getting snapshot when pulling will also include data before boot,
5456                 // query stats as baseline to prevent double count is needed.
5457                 mNetworkStatsBaselines.addAll(
5458                         getDataUsageBytesTransferSnapshotForSubLocked(subInfo));
5459             }
5460         }
5461     }
5462 }
5463