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