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