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