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