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