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