1 /*
2  * Copyright (C) 2017 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 package com.android.server.stats;
17 
18 import android.annotation.Nullable;
19 import android.app.ActivityManagerInternal;
20 import android.app.AlarmManager;
21 import android.app.PendingIntent;
22 import android.app.ProcessMemoryState;
23 import android.app.StatsManager;
24 import android.bluetooth.BluetoothActivityEnergyInfo;
25 import android.bluetooth.BluetoothAdapter;
26 import android.bluetooth.UidTraffic;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.IntentSender;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.PackageManager;
34 import android.content.pm.UserInfo;
35 import android.net.NetworkStats;
36 import android.net.wifi.IWifiManager;
37 import android.net.wifi.WifiActivityEnergyInfo;
38 import android.os.BatteryStatsInternal;
39 import android.os.Binder;
40 import android.os.Bundle;
41 import android.os.Environment;
42 import android.os.FileUtils;
43 import android.os.IBinder;
44 import android.os.IStatsCompanionService;
45 import android.os.IStatsManager;
46 import android.os.Parcelable;
47 import android.os.Process;
48 import android.os.RemoteException;
49 import android.os.ServiceManager;
50 import android.os.StatFs;
51 import android.os.StatsDimensionsValue;
52 import android.os.StatsLogEventWrapper;
53 import android.os.SynchronousResultReceiver;
54 import android.os.SystemClock;
55 import android.os.UserHandle;
56 import android.os.UserManager;
57 import android.telephony.ModemActivityInfo;
58 import android.telephony.TelephonyManager;
59 import android.util.Slog;
60 import android.util.StatsLog;
61 
62 import com.android.internal.annotations.GuardedBy;
63 import com.android.internal.net.NetworkStatsFactory;
64 import com.android.internal.os.KernelCpuSpeedReader;
65 import com.android.internal.os.KernelUidCpuTimeReader;
66 import com.android.internal.os.KernelUidCpuClusterTimeReader;
67 import com.android.internal.os.KernelUidCpuActiveTimeReader;
68 import com.android.internal.os.KernelUidCpuFreqTimeReader;
69 import com.android.internal.os.KernelWakelockReader;
70 import com.android.internal.os.KernelWakelockStats;
71 import com.android.internal.os.PowerProfile;
72 import com.android.internal.util.DumpUtils;
73 import com.android.server.LocalServices;
74 import com.android.server.SystemService;
75 
76 import java.io.File;
77 import java.io.FileDescriptor;
78 import java.io.IOException;
79 import java.io.PrintWriter;
80 import java.util.ArrayList;
81 import java.util.Arrays;
82 import java.util.HashMap;
83 import java.util.HashSet;
84 import java.util.List;
85 import java.util.Map;
86 import java.util.concurrent.TimeUnit;
87 import java.util.concurrent.TimeoutException;
88 
89 /**
90  * Helper service for statsd (the native stats management service in cmds/statsd/).
91  * Used for registering and receiving alarms on behalf of statsd.
92  *
93  * @hide
94  */
95 public class StatsCompanionService extends IStatsCompanionService.Stub {
96     /**
97      * How long to wait on an individual subsystem to return its stats.
98      */
99     private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
100     private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
101 
102     public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
103     public static final String CONFIG_DIR = "/data/misc/stats-service";
104 
105     static final String TAG = "StatsCompanionService";
106     static final boolean DEBUG = false;
107 
108     public static final int CODE_DATA_BROADCAST = 1;
109     public static final int CODE_SUBSCRIBER_BROADCAST = 1;
110     /**
111      * The last report time is provided with each intent registered to
112      * StatsManager#setFetchReportsOperation. This allows easy de-duping in the receiver if
113      * statsd is requesting the client to retrieve the same statsd data. The last report time
114      * corresponds to the last_report_elapsed_nanos that will provided in the current
115      * ConfigMetricsReport, and this timestamp also corresponds to the
116      * current_report_elapsed_nanos of the most recently obtained ConfigMetricsReport.
117      */
118     public static final String EXTRA_LAST_REPORT_TIME = "android.app.extra.LAST_REPORT_TIME";
119     public static final int DEATH_THRESHOLD = 10;
120 
121     private final Context mContext;
122     private final AlarmManager mAlarmManager;
123     @GuardedBy("sStatsdLock")
124     private static IStatsManager sStatsd;
125     private static final Object sStatsdLock = new Object();
126 
127     private final PendingIntent mAnomalyAlarmIntent;
128     private final PendingIntent mPullingAlarmIntent;
129     private final PendingIntent mPeriodicAlarmIntent;
130     private final BroadcastReceiver mAppUpdateReceiver;
131     private final BroadcastReceiver mUserUpdateReceiver;
132     private final ShutdownEventReceiver mShutdownEventReceiver;
133     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
134     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
135     private IWifiManager mWifiManager = null;
136     private TelephonyManager mTelephony = null;
137     private final StatFs mStatFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
138     private final StatFs mStatFsSystem =
139             new StatFs(Environment.getRootDirectory().getAbsolutePath());
140     private final StatFs mStatFsTemp =
141             new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
142     @GuardedBy("sStatsdLock")
143     private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
144     @GuardedBy("sStatsdLock")
145     private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
146 
147     private KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
148     private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
149     private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
150             new KernelUidCpuFreqTimeReader();
151     private KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
152             new KernelUidCpuActiveTimeReader();
153     private KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
154             new KernelUidCpuClusterTimeReader();
155 
StatsCompanionService(Context context)156     public StatsCompanionService(Context context) {
157         super();
158         mContext = context;
159         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
160 
161         mAnomalyAlarmIntent = PendingIntent.getBroadcast(mContext, 0,
162                 new Intent(mContext, AnomalyAlarmReceiver.class), 0);
163         mPullingAlarmIntent = PendingIntent.getBroadcast(
164                 mContext, 0, new Intent(mContext, PullingAlarmReceiver.class), 0);
165         mPeriodicAlarmIntent = PendingIntent.getBroadcast(
166                 mContext, 0, new Intent(mContext, PeriodicAlarmReceiver.class), 0);
167         mAppUpdateReceiver = new AppUpdateReceiver();
168         mUserUpdateReceiver = new BroadcastReceiver() {
169             @Override
170             public void onReceive(Context context, Intent intent) {
171                 synchronized (sStatsdLock) {
172                     sStatsd = fetchStatsdService();
173                     if (sStatsd == null) {
174                         Slog.w(TAG, "Could not access statsd for UserUpdateReceiver");
175                         return;
176                     }
177                     try {
178                         // Pull the latest state of UID->app name, version mapping.
179                         // Needed since the new user basically has a version of every app.
180                         informAllUidsLocked(context);
181                     } catch (RemoteException e) {
182                         Slog.e(TAG, "Failed to inform statsd latest update of all apps", e);
183                         forgetEverythingLocked();
184                     }
185                 }
186             }
187         };
188         mShutdownEventReceiver = new ShutdownEventReceiver();
189         if (DEBUG) Slog.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
190         PowerProfile powerProfile = new PowerProfile(context);
191         final int numClusters = powerProfile.getNumCpuClusters();
192         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
193         int firstCpuOfCluster = 0;
194         for (int i = 0; i < numClusters; i++) {
195             final int numSpeedSteps = powerProfile.getNumSpeedStepsInCpuCluster(i);
196             mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
197                     numSpeedSteps);
198             firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
199         }
200         // use default throttling in
201         // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
202         mKernelUidCpuFreqTimeReader.setThrottleInterval(0);
203         long[] freqs = mKernelUidCpuFreqTimeReader.readFreqs(powerProfile);
204         mKernelUidCpuClusterTimeReader.setThrottleInterval(0);
205         mKernelUidCpuActiveTimeReader.setThrottleInterval(0);
206     }
207 
208     @Override
sendDataBroadcast(IBinder intentSenderBinder, long lastReportTimeNs)209     public void sendDataBroadcast(IBinder intentSenderBinder, long lastReportTimeNs) {
210         enforceCallingPermission();
211         IntentSender intentSender = new IntentSender(intentSenderBinder);
212         Intent intent = new Intent();
213         intent.putExtra(EXTRA_LAST_REPORT_TIME, lastReportTimeNs);
214         try {
215             intentSender.sendIntent(mContext, CODE_DATA_BROADCAST, intent, null, null);
216         } catch (IntentSender.SendIntentException e) {
217             Slog.w(TAG, "Unable to send using IntentSender");
218         }
219     }
220 
221     @Override
sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey, long subscriptionId, long subscriptionRuleId, String[] cookies, StatsDimensionsValue dimensionsValue)222     public void sendSubscriberBroadcast(IBinder intentSenderBinder, long configUid, long configKey,
223                                         long subscriptionId, long subscriptionRuleId,
224                                         String[] cookies,
225                                         StatsDimensionsValue dimensionsValue) {
226         enforceCallingPermission();
227         IntentSender intentSender = new IntentSender(intentSenderBinder);
228         Intent intent = new Intent()
229                 .putExtra(StatsManager.EXTRA_STATS_CONFIG_UID, configUid)
230                 .putExtra(StatsManager.EXTRA_STATS_CONFIG_KEY, configKey)
231                 .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_ID, subscriptionId)
232                 .putExtra(StatsManager.EXTRA_STATS_SUBSCRIPTION_RULE_ID, subscriptionRuleId)
233                 .putExtra(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, dimensionsValue);
234 
235         ArrayList<String> cookieList = new ArrayList<>(cookies.length);
236         for (String cookie : cookies) { cookieList.add(cookie); }
237         intent.putStringArrayListExtra(
238                 StatsManager.EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES, cookieList);
239 
240         if (DEBUG) {
241             Slog.d(TAG, String.format(
242                     "Statsd sendSubscriberBroadcast with params {%d %d %d %d %s %s}",
243                     configUid, configKey, subscriptionId, subscriptionRuleId,
244                     Arrays.toString(cookies), dimensionsValue));
245         }
246         try {
247             intentSender.sendIntent(mContext, CODE_SUBSCRIBER_BROADCAST, intent, null, null);
248         } catch (IntentSender.SendIntentException e) {
249             Slog.w(TAG, "Unable to send using IntentSender from uid " + configUid
250                     + "; presumably it had been cancelled.");
251         }
252     }
253 
toIntArray(List<Integer> list)254     private final static int[] toIntArray(List<Integer> list) {
255         int[] ret = new int[list.size()];
256         for (int i = 0; i < ret.length; i++) {
257             ret[i] = list.get(i);
258         }
259         return ret;
260     }
261 
toLongArray(List<Long> list)262     private final static long[] toLongArray(List<Long> list) {
263         long[] ret = new long[list.size()];
264         for (int i = 0; i < ret.length; i++) {
265             ret[i] = list.get(i);
266         }
267         return ret;
268     }
269 
270     // Assumes that sStatsdLock is held.
271     @GuardedBy("sStatsdLock")
informAllUidsLocked(Context context)272     private final void informAllUidsLocked(Context context) throws RemoteException {
273         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
274         PackageManager pm = context.getPackageManager();
275         final List<UserInfo> users = um.getUsers(true);
276         if (DEBUG) {
277             Slog.d(TAG, "Iterating over " + users.size() + " profiles.");
278         }
279 
280         List<Integer> uids = new ArrayList<>();
281         List<Long> versions = new ArrayList<>();
282         List<String> apps = new ArrayList<>();
283 
284         // Add in all the apps for every user/profile.
285         for (UserInfo profile : users) {
286             List<PackageInfo> pi =
287                 pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
288             for (int j = 0; j < pi.size(); j++) {
289                 if (pi.get(j).applicationInfo != null) {
290                     uids.add(pi.get(j).applicationInfo.uid);
291                     versions.add(pi.get(j).getLongVersionCode());
292                     apps.add(pi.get(j).packageName);
293                 }
294             }
295         }
296         sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions), apps.toArray(new
297                 String[apps.size()]));
298         if (DEBUG) {
299             Slog.d(TAG, "Sent data for " + uids.size() + " apps");
300         }
301     }
302 
303     private final static class AppUpdateReceiver extends BroadcastReceiver {
304         @Override
onReceive(Context context, Intent intent)305         public void onReceive(Context context, Intent intent) {
306             /**
307              * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid
308              * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag.
309              * If we can't find the value for EXTRA_REPLACING, we default to false.
310              */
311             if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)
312                     && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
313                 return; // Keep only replacing or normal add and remove.
314             }
315             if (DEBUG) Slog.d(TAG, "StatsCompanionService noticed an app was updated.");
316             synchronized (sStatsdLock) {
317                 if (sStatsd == null) {
318                     Slog.w(TAG, "Could not access statsd to inform it of an app update");
319                     return;
320                 }
321                 try {
322                     if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
323                         Bundle b = intent.getExtras();
324                         int uid = b.getInt(Intent.EXTRA_UID);
325                         boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
326                         if (!replacing) {
327                             // Don't bother sending an update if we're right about to get another
328                             // intent for the new version that's added.
329                             PackageManager pm = context.getPackageManager();
330                             String app = intent.getData().getSchemeSpecificPart();
331                             sStatsd.informOnePackageRemoved(app, uid);
332                         }
333                     } else {
334                         PackageManager pm = context.getPackageManager();
335                         Bundle b = intent.getExtras();
336                         int uid = b.getInt(Intent.EXTRA_UID);
337                         String app = intent.getData().getSchemeSpecificPart();
338                         PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
339                         sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
340                     }
341                 } catch (Exception e) {
342                     Slog.w(TAG, "Failed to inform statsd of an app update", e);
343                 }
344             }
345         }
346     }
347 
348     public final static class AnomalyAlarmReceiver extends BroadcastReceiver {
349         @Override
onReceive(Context context, Intent intent)350         public void onReceive(Context context, Intent intent) {
351             Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred at time "
352                     + System.currentTimeMillis() + "ms.");
353             synchronized (sStatsdLock) {
354                 if (sStatsd == null) {
355                     Slog.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
356                     return;
357                 }
358                 try {
359                     // Two-way call to statsd to retain AlarmManager wakelock
360                     sStatsd.informAnomalyAlarmFired();
361                 } catch (RemoteException e) {
362                     Slog.w(TAG, "Failed to inform statsd of anomaly alarm firing", e);
363                 }
364             }
365             // AlarmManager releases its own wakelock here.
366         }
367     }
368 
369     public final static class PullingAlarmReceiver extends BroadcastReceiver {
370         @Override
onReceive(Context context, Intent intent)371         public void onReceive(Context context, Intent intent) {
372             if (DEBUG)
373                 Slog.d(TAG, "Time to poll something.");
374             synchronized (sStatsdLock) {
375                 if (sStatsd == null) {
376                     Slog.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
377                     return;
378                 }
379                 try {
380                     // Two-way call to statsd to retain AlarmManager wakelock
381                     sStatsd.informPollAlarmFired();
382                 } catch (RemoteException e) {
383                     Slog.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
384                 }
385             }
386         }
387     }
388 
389     public final static class PeriodicAlarmReceiver extends BroadcastReceiver {
390         @Override
onReceive(Context context, Intent intent)391         public void onReceive(Context context, Intent intent) {
392             if (DEBUG)
393                 Slog.d(TAG, "Time to trigger periodic alarm.");
394             synchronized (sStatsdLock) {
395                 if (sStatsd == null) {
396                     Slog.w(TAG, "Could not access statsd to inform it of periodic alarm firing.");
397                     return;
398                 }
399                 try {
400                     // Two-way call to statsd to retain AlarmManager wakelock
401                     sStatsd.informAlarmForSubscriberTriggeringFired();
402                 } catch (RemoteException e) {
403                     Slog.w(TAG, "Failed to inform statsd of periodic alarm firing.", e);
404                 }
405             }
406             // AlarmManager releases its own wakelock here.
407         }
408     }
409 
410     public final static class ShutdownEventReceiver extends BroadcastReceiver {
411         @Override
onReceive(Context context, Intent intent)412         public void onReceive(Context context, Intent intent) {
413             /**
414              * Skip immediately if intent is not relevant to device shutdown.
415              */
416             if (!intent.getAction().equals(Intent.ACTION_REBOOT)
417                     && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
418                     && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
419                 return;
420             }
421 
422             Slog.i(TAG, "StatsCompanionService noticed a shutdown.");
423             synchronized (sStatsdLock) {
424                 if (sStatsd == null) {
425                     Slog.w(TAG, "Could not access statsd to inform it of a shutdown event.");
426                     return;
427                 }
428                 try {
429                   sStatsd.informDeviceShutdown();
430                 } catch (Exception e) {
431                     Slog.w(TAG, "Failed to inform statsd of a shutdown event.", e);
432                 }
433             }
434         }
435     }
436 
437     @Override // Binder call
setAnomalyAlarm(long timestampMs)438     public void setAnomalyAlarm(long timestampMs) {
439         enforceCallingPermission();
440         if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs);
441         final long callingToken = Binder.clearCallingIdentity();
442         try {
443             // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
444             // only fire when it awakens.
445             // This alarm is inexact, leaving its exactness completely up to the OS optimizations.
446             // AlarmManager will automatically cancel any previous mAnomalyAlarmIntent alarm.
447             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, mAnomalyAlarmIntent);
448         } finally {
449             Binder.restoreCallingIdentity(callingToken);
450         }
451     }
452 
453     @Override // Binder call
cancelAnomalyAlarm()454     public void cancelAnomalyAlarm() {
455         enforceCallingPermission();
456         if (DEBUG) Slog.d(TAG, "Cancelling anomaly alarm");
457         final long callingToken = Binder.clearCallingIdentity();
458         try {
459             mAlarmManager.cancel(mAnomalyAlarmIntent);
460         } finally {
461             Binder.restoreCallingIdentity(callingToken);
462         }
463     }
464 
465     @Override // Binder call
setAlarmForSubscriberTriggering(long timestampMs)466     public void setAlarmForSubscriberTriggering(long timestampMs) {
467         enforceCallingPermission();
468         if (DEBUG)
469             Slog.d(TAG, "Setting periodic alarm in about " +
470                     (timestampMs - SystemClock.elapsedRealtime()));
471         final long callingToken = Binder.clearCallingIdentity();
472         try {
473             // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
474             // only fire when it awakens.
475             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, mPeriodicAlarmIntent);
476         } finally {
477             Binder.restoreCallingIdentity(callingToken);
478         }
479     }
480 
481     @Override // Binder call
cancelAlarmForSubscriberTriggering()482     public void cancelAlarmForSubscriberTriggering() {
483         enforceCallingPermission();
484         if (DEBUG)
485             Slog.d(TAG, "Cancelling periodic alarm");
486         final long callingToken = Binder.clearCallingIdentity();
487         try {
488             mAlarmManager.cancel(mPeriodicAlarmIntent);
489         } finally {
490             Binder.restoreCallingIdentity(callingToken);
491         }
492     }
493 
494     @Override // Binder call
setPullingAlarm(long nextPullTimeMs)495     public void setPullingAlarm(long nextPullTimeMs) {
496       enforceCallingPermission();
497       if (DEBUG)
498         Slog.d(TAG,
499             "Setting pulling alarm in about " + (nextPullTimeMs - SystemClock.elapsedRealtime()));
500       final long callingToken = Binder.clearCallingIdentity();
501       try {
502         // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
503         // only fire when it awakens.
504         mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, mPullingAlarmIntent);
505       } finally {
506         Binder.restoreCallingIdentity(callingToken);
507       }
508     }
509 
510     @Override // Binder call
cancelPullingAlarm()511     public void cancelPullingAlarm() {
512       enforceCallingPermission();
513       if (DEBUG)
514         Slog.d(TAG, "Cancelling pulling alarm");
515       final long callingToken = Binder.clearCallingIdentity();
516       try {
517         mAlarmManager.cancel(mPullingAlarmIntent);
518       } finally {
519         Binder.restoreCallingIdentity(callingToken);
520       }
521     }
522 
addNetworkStats( int tag, List<StatsLogEventWrapper> ret, NetworkStats stats, boolean withFGBG)523     private void addNetworkStats(
524             int tag, List<StatsLogEventWrapper> ret, NetworkStats stats, boolean withFGBG) {
525         int size = stats.size();
526         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
527         NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
528         for (int j = 0; j < size; j++) {
529             stats.getValues(j, entry);
530             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tag, withFGBG ? 6 : 5);
531             e.writeInt(entry.uid);
532             if (withFGBG) {
533                 e.writeInt(entry.set);
534             }
535             e.writeLong(entry.rxBytes);
536             e.writeLong(entry.rxPackets);
537             e.writeLong(entry.txBytes);
538             e.writeLong(entry.txPackets);
539             ret.add(e);
540         }
541     }
542 
543     /**
544      * Allows rollups per UID but keeping the set (foreground/background) slicing.
545      * Adapted from groupedByUid in frameworks/base/core/java/android/net/NetworkStats.java
546      */
rollupNetworkStatsByFGBG(NetworkStats stats)547     private NetworkStats rollupNetworkStatsByFGBG(NetworkStats stats) {
548         final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
549 
550         final NetworkStats.Entry entry = new NetworkStats.Entry();
551         entry.iface = NetworkStats.IFACE_ALL;
552         entry.tag = NetworkStats.TAG_NONE;
553         entry.metered = NetworkStats.METERED_ALL;
554         entry.roaming = NetworkStats.ROAMING_ALL;
555 
556         int size = stats.size();
557         NetworkStats.Entry recycle = new NetworkStats.Entry(); // Used for retrieving values
558         for (int i = 0; i < size; i++) {
559             stats.getValues(i, recycle);
560 
561             // Skip specific tags, since already counted in TAG_NONE
562             if (recycle.tag != NetworkStats.TAG_NONE) continue;
563 
564             entry.set = recycle.set; // Allows slicing by background/foreground
565             entry.uid = recycle.uid;
566             entry.rxBytes = recycle.rxBytes;
567             entry.rxPackets = recycle.rxPackets;
568             entry.txBytes = recycle.txBytes;
569             entry.txPackets = recycle.txPackets;
570             // Operations purposefully omitted since we don't use them for statsd.
571             ret.combineValues(entry);
572         }
573         return ret;
574     }
575 
576     /**
577      * Helper method to extract the Parcelable controller info from a
578      * SynchronousResultReceiver.
579      */
awaitControllerInfo( @ullable SynchronousResultReceiver receiver)580     private static <T extends Parcelable> T awaitControllerInfo(
581             @Nullable SynchronousResultReceiver receiver) {
582         if (receiver == null) {
583             return null;
584         }
585 
586         try {
587             final SynchronousResultReceiver.Result result =
588                     receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
589             if (result.bundle != null) {
590                 // This is the final destination for the Bundle.
591                 result.bundle.setDefusable(true);
592 
593                 final T data = result.bundle.getParcelable(
594                         RESULT_RECEIVER_CONTROLLER_KEY);
595                 if (data != null) {
596                     return data;
597                 }
598             }
599             Slog.e(TAG, "no controller energy info supplied for " + receiver.getName());
600         } catch (TimeoutException e) {
601             Slog.w(TAG, "timeout reading " + receiver.getName() + " stats");
602         }
603         return null;
604     }
605 
pullKernelWakelock(int tagId, List<StatsLogEventWrapper> pulledData)606     private void pullKernelWakelock(int tagId, List<StatsLogEventWrapper> pulledData) {
607         final KernelWakelockStats wakelockStats =
608                 mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
609         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
610         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
611             String name = ent.getKey();
612             KernelWakelockStats.Entry kws = ent.getValue();
613             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 4);
614             e.writeString(name);
615             e.writeInt(kws.mCount);
616             e.writeInt(kws.mVersion);
617             e.writeLong(kws.mTotalTime);
618             pulledData.add(e);
619         }
620     }
621 
pullWifiBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData)622     private void pullWifiBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
623         long token = Binder.clearCallingIdentity();
624         try {
625             // TODO: Consider caching the following call to get BatteryStatsInternal.
626             BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
627             String[] ifaces = bs.getWifiIfaces();
628             if (ifaces.length == 0) {
629                 return;
630             }
631             NetworkStatsFactory nsf = new NetworkStatsFactory();
632             // Combine all the metrics per Uid into one record.
633             NetworkStats stats =
634                     nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
635                             .groupedByUid();
636             addNetworkStats(tagId, pulledData, stats, false);
637         } catch (java.io.IOException e) {
638             Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
639         } finally {
640             Binder.restoreCallingIdentity(token);
641         }
642     }
643 
pullWifiBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData)644     private void pullWifiBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData) {
645         long token = Binder.clearCallingIdentity();
646         try {
647             BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
648             String[] ifaces = bs.getWifiIfaces();
649             if (ifaces.length == 0) {
650                 return;
651             }
652             NetworkStatsFactory nsf = new NetworkStatsFactory();
653             NetworkStats stats = rollupNetworkStatsByFGBG(
654                     nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
655             addNetworkStats(tagId, pulledData, stats, true);
656         } catch (java.io.IOException e) {
657             Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
658         } finally {
659             Binder.restoreCallingIdentity(token);
660         }
661     }
662 
pullMobileBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData)663     private void pullMobileBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
664         long token = Binder.clearCallingIdentity();
665         try {
666             BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
667             String[] ifaces = bs.getMobileIfaces();
668             if (ifaces.length == 0) {
669                 return;
670             }
671             NetworkStatsFactory nsf = new NetworkStatsFactory();
672             // Combine all the metrics per Uid into one record.
673             NetworkStats stats =
674                     nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
675                             .groupedByUid();
676             addNetworkStats(tagId, pulledData, stats, false);
677         } catch (java.io.IOException e) {
678             Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
679         } finally {
680             Binder.restoreCallingIdentity(token);
681         }
682     }
683 
pullBluetoothBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData)684     private void pullBluetoothBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
685         BluetoothActivityEnergyInfo info = pullBluetoothData();
686         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
687         if (info.getUidTraffic() != null) {
688             for (UidTraffic traffic : info.getUidTraffic()) {
689                 StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
690                 e.writeInt(traffic.getUid());
691                 e.writeLong(traffic.getRxBytes());
692                 e.writeLong(traffic.getTxBytes());
693                 pulledData.add(e);
694             }
695         }
696     }
697 
pullMobileBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData)698     private void pullMobileBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData) {
699         long token = Binder.clearCallingIdentity();
700         try {
701             BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
702             String[] ifaces = bs.getMobileIfaces();
703             if (ifaces.length == 0) {
704                 return;
705             }
706             NetworkStatsFactory nsf = new NetworkStatsFactory();
707             NetworkStats stats = rollupNetworkStatsByFGBG(
708                     nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
709             addNetworkStats(tagId, pulledData, stats, true);
710         } catch (java.io.IOException e) {
711             Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
712         } finally {
713             Binder.restoreCallingIdentity(token);
714         }
715     }
716 
pullCpuTimePerFreq(int tagId, List<StatsLogEventWrapper> pulledData)717     private void pullCpuTimePerFreq(int tagId, List<StatsLogEventWrapper> pulledData) {
718         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
719         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
720             long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
721             if (clusterTimeMs != null) {
722                 for (int speed = clusterTimeMs.length - 1; speed >= 0; --speed) {
723                     StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
724                     e.writeInt(cluster);
725                     e.writeInt(speed);
726                     e.writeLong(clusterTimeMs[speed]);
727                     pulledData.add(e);
728                 }
729             }
730         }
731     }
732 
pullKernelUidCpuTime(int tagId, List<StatsLogEventWrapper> pulledData)733     private void pullKernelUidCpuTime(int tagId, List<StatsLogEventWrapper> pulledData) {
734         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
735         mKernelUidCpuTimeReader.readAbsolute((uid, userTimeUs, systemTimeUs) -> {
736             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
737             e.writeInt(uid);
738             e.writeLong(userTimeUs);
739             e.writeLong(systemTimeUs);
740             pulledData.add(e);
741         });
742     }
743 
pullKernelUidCpuFreqTime(int tagId, List<StatsLogEventWrapper> pulledData)744     private void pullKernelUidCpuFreqTime(int tagId, List<StatsLogEventWrapper> pulledData) {
745         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
746         mKernelUidCpuFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
747             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
748                 if(cpuFreqTimeMs[freqIndex] != 0) {
749                     StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
750                     e.writeInt(uid);
751                     e.writeInt(freqIndex);
752                     e.writeLong(cpuFreqTimeMs[freqIndex]);
753                     pulledData.add(e);
754                 }
755             }
756         });
757     }
758 
pullKernelUidCpuClusterTime(int tagId, List<StatsLogEventWrapper> pulledData)759     private void pullKernelUidCpuClusterTime(int tagId, List<StatsLogEventWrapper> pulledData) {
760         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
761         mKernelUidCpuClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
762             for (int i = 0; i < cpuClusterTimesMs.length; i++) {
763                 StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
764                 e.writeInt(uid);
765                 e.writeInt(i);
766                 e.writeLong(cpuClusterTimesMs[i]);
767                 pulledData.add(e);
768             }
769         });
770     }
771 
pullKernelUidCpuActiveTime(int tagId, List<StatsLogEventWrapper> pulledData)772     private void pullKernelUidCpuActiveTime(int tagId, List<StatsLogEventWrapper> pulledData) {
773         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
774         mKernelUidCpuActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
775             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 2);
776             e.writeInt(uid);
777             e.writeLong((long)cpuActiveTimesMs);
778             pulledData.add(e);
779         });
780     }
781 
pullWifiActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData)782     private void pullWifiActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
783         long token = Binder.clearCallingIdentity();
784         if (mWifiManager == null) {
785             mWifiManager =
786                     IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
787         }
788         if (mWifiManager != null) {
789             try {
790                 SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
791                 mWifiManager.requestActivityInfo(wifiReceiver);
792                 final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
793                 StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 6);
794                 e.writeLong(wifiInfo.getTimeStamp());
795                 e.writeInt(wifiInfo.getStackState());
796                 e.writeLong(wifiInfo.getControllerTxTimeMillis());
797                 e.writeLong(wifiInfo.getControllerRxTimeMillis());
798                 e.writeLong(wifiInfo.getControllerIdleTimeMillis());
799                 e.writeLong(wifiInfo.getControllerEnergyUsed());
800                 pulledData.add(e);
801             } catch (RemoteException e) {
802                 Slog.e(TAG, "Pulling wifiManager for wifi controller activity energy info has error", e);
803             } finally {
804                 Binder.restoreCallingIdentity(token);
805             }
806         }
807     }
808 
pullModemActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData)809     private void pullModemActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
810         long token = Binder.clearCallingIdentity();
811         if (mTelephony == null) {
812             mTelephony = TelephonyManager.from(mContext);
813         }
814         if (mTelephony != null) {
815             SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
816             mTelephony.requestModemActivityInfo(modemReceiver);
817             final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
818             StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 10);
819             e.writeLong(modemInfo.getTimestamp());
820             e.writeLong(modemInfo.getSleepTimeMillis());
821             e.writeLong(modemInfo.getIdleTimeMillis());
822             e.writeLong(modemInfo.getTxTimeMillis()[0]);
823             e.writeLong(modemInfo.getTxTimeMillis()[1]);
824             e.writeLong(modemInfo.getTxTimeMillis()[2]);
825             e.writeLong(modemInfo.getTxTimeMillis()[3]);
826             e.writeLong(modemInfo.getTxTimeMillis()[4]);
827             e.writeLong(modemInfo.getRxTimeMillis());
828             e.writeLong(modemInfo.getEnergyUsed());
829             pulledData.add(e);
830         }
831     }
832 
pullBluetoothActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData)833     private void pullBluetoothActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
834         BluetoothActivityEnergyInfo info = pullBluetoothData();
835         StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 6);
836         e.writeLong(info.getTimeStamp());
837         e.writeInt(info.getBluetoothStackState());
838         e.writeLong(info.getControllerTxTimeMillis());
839         e.writeLong(info.getControllerRxTimeMillis());
840         e.writeLong(info.getControllerIdleTimeMillis());
841         e.writeLong(info.getControllerEnergyUsed());
842         pulledData.add(e);
843     }
844 
pullBluetoothData()845     private synchronized BluetoothActivityEnergyInfo pullBluetoothData() {
846         final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
847         if (adapter != null) {
848             SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver("bluetooth");
849             adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
850             return awaitControllerInfo(bluetoothReceiver);
851         } else {
852             Slog.e(TAG, "Failed to get bluetooth adapter!");
853             return null;
854         }
855     }
856 
pullSystemElapsedRealtime(int tagId, List<StatsLogEventWrapper> pulledData)857     private void pullSystemElapsedRealtime(int tagId, List<StatsLogEventWrapper> pulledData) {
858         StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 1);
859         e.writeLong(SystemClock.elapsedRealtime());
860         pulledData.add(e);
861     }
862 
pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData)863     private void pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData) {
864         StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 3);
865         e.writeLong(mStatFsData.getAvailableBytes());
866         e.writeLong(mStatFsSystem.getAvailableBytes());
867         e.writeLong(mStatFsTemp.getAvailableBytes());
868         pulledData.add(e);
869     }
870 
pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData)871     private void pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData) {
872         StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 1);
873         e.writeLong(SystemClock.uptimeMillis());
874         pulledData.add(e);
875     }
876 
pullProcessMemoryState(int tagId, List<StatsLogEventWrapper> pulledData)877     private void pullProcessMemoryState(int tagId, List<StatsLogEventWrapper> pulledData) {
878         List<ProcessMemoryState> processMemoryStates =
879                 LocalServices.getService(ActivityManagerInternal.class)
880                         .getMemoryStateForProcesses();
881         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
882         for (ProcessMemoryState processMemoryState : processMemoryStates) {
883             StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 8 /* fields */);
884             e.writeInt(processMemoryState.uid);
885             e.writeString(processMemoryState.processName);
886             e.writeInt(processMemoryState.oomScore);
887             e.writeLong(processMemoryState.pgfault);
888             e.writeLong(processMemoryState.pgmajfault);
889             e.writeLong(processMemoryState.rssInBytes);
890             e.writeLong(processMemoryState.cacheInBytes);
891             e.writeLong(processMemoryState.swapInBytes);
892             pulledData.add(e);
893         }
894     }
895 
896     /**
897      * Pulls various data.
898      */
899     @Override // Binder call
pullData(int tagId)900     public StatsLogEventWrapper[] pullData(int tagId) {
901         enforceCallingPermission();
902         if (DEBUG)
903             Slog.d(TAG, "Pulling " + tagId);
904         List<StatsLogEventWrapper> ret = new ArrayList<>();
905         switch (tagId) {
906             case StatsLog.WIFI_BYTES_TRANSFER: {
907                 pullWifiBytesTransfer(tagId, ret);
908                 break;
909             }
910             case StatsLog.MOBILE_BYTES_TRANSFER: {
911                 pullMobileBytesTransfer(tagId, ret);
912                 break;
913             }
914             case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
915                 pullWifiBytesTransferByFgBg(tagId, ret);
916                 break;
917             }
918             case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
919                 pullMobileBytesTransferByFgBg(tagId, ret);
920                 break;
921             }
922             case StatsLog.BLUETOOTH_BYTES_TRANSFER: {
923                 pullBluetoothBytesTransfer(tagId, ret);
924                 break;
925             }
926             case StatsLog.KERNEL_WAKELOCK: {
927                 pullKernelWakelock(tagId, ret);
928                 break;
929             }
930             case StatsLog.CPU_TIME_PER_FREQ: {
931                 pullCpuTimePerFreq(tagId, ret);
932                 break;
933             }
934             case StatsLog.CPU_TIME_PER_UID: {
935                 pullKernelUidCpuTime(tagId, ret);
936                 break;
937             }
938             case StatsLog.CPU_TIME_PER_UID_FREQ: {
939                 pullKernelUidCpuFreqTime(tagId, ret);
940                 break;
941             }
942             case StatsLog.CPU_CLUSTER_TIME: {
943                 pullKernelUidCpuClusterTime(tagId, ret);
944                 break;
945             }
946             case StatsLog.CPU_ACTIVE_TIME: {
947                 pullKernelUidCpuActiveTime(tagId, ret);
948                 break;
949             }
950             case StatsLog.WIFI_ACTIVITY_INFO: {
951                 pullWifiActivityInfo(tagId, ret);
952                 break;
953             }
954             case StatsLog.MODEM_ACTIVITY_INFO: {
955                 pullModemActivityInfo(tagId, ret);
956                 break;
957             }
958             case StatsLog.BLUETOOTH_ACTIVITY_INFO: {
959                 pullBluetoothActivityInfo(tagId, ret);
960                 break;
961             }
962             case StatsLog.SYSTEM_UPTIME: {
963                 pullSystemUpTime(tagId, ret);
964                 break;
965             }
966             case StatsLog.SYSTEM_ELAPSED_REALTIME: {
967                 pullSystemElapsedRealtime(tagId, ret);
968                 break;
969             }
970             case StatsLog.DISK_SPACE: {
971                 pullDiskSpace(tagId, ret);
972                 break;
973             }
974             case StatsLog.PROCESS_MEMORY_STATE: {
975                 pullProcessMemoryState(tagId, ret);
976                 break;
977             }
978             default:
979                 Slog.w(TAG, "No such tagId data as " + tagId);
980                 return null;
981         }
982         return ret.toArray(new StatsLogEventWrapper[ret.size()]);
983     }
984 
985     @Override // Binder call
statsdReady()986     public void statsdReady() {
987         enforceCallingPermission();
988         if (DEBUG) Slog.d(TAG, "learned that statsdReady");
989         sayHiToStatsd(); // tell statsd that we're ready too and link to it
990         mContext.sendBroadcastAsUser(
991                 new Intent(StatsManager.ACTION_STATSD_STARTED)
992                         .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND),
993                 UserHandle.SYSTEM,
994                 android.Manifest.permission.DUMP);
995     }
996 
997     @Override
triggerUidSnapshot()998     public void triggerUidSnapshot() {
999         enforceCallingPermission();
1000         synchronized (sStatsdLock) {
1001             final long token = Binder.clearCallingIdentity();
1002             try {
1003                 informAllUidsLocked(mContext);
1004             } catch (RemoteException e) {
1005                 Slog.e(TAG, "Failed to trigger uid snapshot.", e);
1006             } finally {
1007                 restoreCallingIdentity(token);
1008             }
1009         }
1010     }
1011 
enforceCallingPermission()1012     private void enforceCallingPermission() {
1013         if (Binder.getCallingPid() == Process.myPid()) {
1014             return;
1015         }
1016         mContext.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null);
1017     }
1018 
1019     // Lifecycle and related code
1020 
1021     /**
1022      * Fetches the statsd IBinder service
1023      */
fetchStatsdService()1024     private static IStatsManager fetchStatsdService() {
1025         return IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
1026     }
1027 
1028     public static final class Lifecycle extends SystemService {
1029         private StatsCompanionService mStatsCompanionService;
1030 
Lifecycle(Context context)1031         public Lifecycle(Context context) {
1032             super(context);
1033         }
1034 
1035         @Override
onStart()1036         public void onStart() {
1037             mStatsCompanionService = new StatsCompanionService(getContext());
1038             try {
1039                 publishBinderService(Context.STATS_COMPANION_SERVICE, mStatsCompanionService);
1040                 if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE);
1041             } catch (Exception e) {
1042                 Slog.e(TAG, "Failed to publishBinderService", e);
1043             }
1044         }
1045 
1046         @Override
onBootPhase(int phase)1047         public void onBootPhase(int phase) {
1048             super.onBootPhase(phase);
1049             if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
1050                 mStatsCompanionService.systemReady();
1051             }
1052         }
1053     }
1054 
1055     /**
1056      * Now that the android system is ready, StatsCompanion is ready too, so inform statsd.
1057      */
systemReady()1058     private void systemReady() {
1059         if (DEBUG) Slog.d(TAG, "Learned that systemReady");
1060         sayHiToStatsd();
1061     }
1062 
1063     /**
1064      * Tells statsd that statscompanion is ready. If the binder call returns, link to statsd.
1065      */
sayHiToStatsd()1066     private void sayHiToStatsd() {
1067         synchronized (sStatsdLock) {
1068             if (sStatsd != null) {
1069                 Slog.e(TAG, "Trying to fetch statsd, but it was already fetched",
1070                         new IllegalStateException("sStatsd is not null when being fetched"));
1071                 return;
1072             }
1073             sStatsd = fetchStatsdService();
1074             if (sStatsd == null) {
1075                 Slog.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive.");
1076                 return;
1077             }
1078             if (DEBUG) Slog.d(TAG, "Saying hi to statsd");
1079             try {
1080                 sStatsd.statsCompanionReady();
1081                 // If the statsCompanionReady two-way binder call returns, link to statsd.
1082                 try {
1083                     sStatsd.asBinder().linkToDeath(new StatsdDeathRecipient(), 0);
1084                 } catch (RemoteException e) {
1085                     Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e);
1086                     forgetEverythingLocked();
1087                 }
1088                 // Setup broadcast receiver for updates.
1089                 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED);
1090                 filter.addAction(Intent.ACTION_PACKAGE_ADDED);
1091                 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1092                 filter.addDataScheme("package");
1093                 mContext.registerReceiverAsUser(mAppUpdateReceiver, UserHandle.ALL, filter, null,
1094                         null);
1095 
1096                 // Setup receiver for user initialize (which happens once for a new user) and
1097                 // if a user is removed.
1098                 filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE);
1099                 filter.addAction(Intent.ACTION_USER_REMOVED);
1100                 mContext.registerReceiverAsUser(mUserUpdateReceiver, UserHandle.ALL,
1101                         filter, null, null);
1102 
1103                 // Setup receiver for device reboots or shutdowns.
1104                 filter = new IntentFilter(Intent.ACTION_REBOOT);
1105                 filter.addAction(Intent.ACTION_SHUTDOWN);
1106                 mContext.registerReceiverAsUser(
1107                         mShutdownEventReceiver, UserHandle.ALL, filter, null, null);
1108                 final long token = Binder.clearCallingIdentity();
1109                 try {
1110                     // Pull the latest state of UID->app name, version mapping when statsd starts.
1111                     informAllUidsLocked(mContext);
1112                 } finally {
1113                     restoreCallingIdentity(token);
1114                 }
1115                 Slog.i(TAG, "Told statsd that StatsCompanionService is alive.");
1116             } catch (RemoteException e) {
1117                 Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
1118                 forgetEverythingLocked();
1119             }
1120         }
1121     }
1122 
1123     private class StatsdDeathRecipient implements IBinder.DeathRecipient {
1124         @Override
binderDied()1125         public void binderDied() {
1126             Slog.i(TAG, "Statsd is dead - erase all my knowledge.");
1127             synchronized (sStatsdLock) {
1128                 long now = SystemClock.elapsedRealtime();
1129                 for (Long timeMillis : mDeathTimeMillis) {
1130                     long ageMillis = now - timeMillis;
1131                     if (ageMillis > MILLIS_IN_A_DAY) {
1132                         mDeathTimeMillis.remove(timeMillis);
1133                     }
1134                 }
1135                 for (Long timeMillis : mDeletedFiles.keySet()) {
1136                     long ageMillis = now - timeMillis;
1137                     if (ageMillis > MILLIS_IN_A_DAY * 7) {
1138                         mDeletedFiles.remove(timeMillis);
1139                     }
1140                 }
1141                 mDeathTimeMillis.add(now);
1142                 if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) {
1143                     mDeathTimeMillis.clear();
1144                     File[] configs = FileUtils.listFilesOrEmpty(new File(CONFIG_DIR));
1145                     if (configs.length > 0) {
1146                         String fileName = configs[0].getName();
1147                         if (configs[0].delete()) {
1148                             mDeletedFiles.put(now, fileName);
1149                         }
1150                     }
1151                 }
1152                 forgetEverythingLocked();
1153             }
1154         }
1155     }
1156 
forgetEverythingLocked()1157     private void forgetEverythingLocked() {
1158         sStatsd = null;
1159         mContext.unregisterReceiver(mAppUpdateReceiver);
1160         mContext.unregisterReceiver(mUserUpdateReceiver);
1161         mContext.unregisterReceiver(mShutdownEventReceiver);
1162         cancelAnomalyAlarm();
1163         cancelPullingAlarm();
1164     }
1165 
1166     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)1167     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1168         if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
1169 
1170         synchronized (sStatsdLock) {
1171             writer.println("Number of configuration files deleted: " + mDeletedFiles.size());
1172             if (mDeletedFiles.size() > 0) {
1173                 writer.println("  timestamp, deleted file name");
1174             }
1175             long lastBootMillis =
1176                     SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime();
1177             for (Long elapsedMillis : mDeletedFiles.keySet()) {
1178                 long deletionMillis = lastBootMillis + elapsedMillis;
1179                 writer.println("  " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis));
1180             }
1181         }
1182     }
1183 
1184 }
1185