Home | History | Annotate | Download | only in stats
      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 
    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
    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
    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 
    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 
    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")
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 
    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      */
    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      */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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
    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
    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 
   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      */
   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 
   1031         public Lifecycle(Context context) {
   1032             super(context);
   1033         }
   1034 
   1035         @Override
   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
   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      */
   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      */
   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
   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 
   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
   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