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