Loading apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +176 −143 Original line number Original line Diff line number Diff line Loading @@ -54,6 +54,7 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.List; Loading Loading @@ -102,9 +103,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final OnAlarmListener mAnomalyAlarmListener = new AnomalyAlarmListener(); private final OnAlarmListener mAnomalyAlarmListener = new AnomalyAlarmListener(); private final OnAlarmListener mPullingAlarmListener = new PullingAlarmListener(); private final OnAlarmListener mPullingAlarmListener = new PullingAlarmListener(); private final OnAlarmListener mPeriodicAlarmListener = new PeriodicAlarmListener(); private final OnAlarmListener mPeriodicAlarmListener = new PeriodicAlarmListener(); private final BroadcastReceiver mAppUpdateReceiver; private final BroadcastReceiver mUserUpdateReceiver; private final ShutdownEventReceiver mShutdownEventReceiver; private StatsManagerService mStatsManagerService; private StatsManagerService mStatsManagerService; Loading @@ -118,27 +116,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { super(); super(); mContext = context; mContext = context; mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mAppUpdateReceiver = new AppUpdateReceiver(); mUserUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized (sStatsdLock) { if (sStatsd == null) { Log.w(TAG, "Could not access statsd for UserUpdateReceiver"); return; } try { // Pull the latest state of UID->app name, version mapping. // Needed since the new user basically has a version of every app. informAllUidsLocked(context); } catch (RemoteException e) { Log.e(TAG, "Failed to inform statsd latest update of all apps", e); forgetEverythingLocked(); } } } }; mShutdownEventReceiver = new ShutdownEventReceiver(); if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED."); if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED."); HandlerThread handlerThread = new HandlerThread(TAG); HandlerThread handlerThread = new HandlerThread(TAG); handlerThread.start(); handlerThread.start(); Loading @@ -162,9 +139,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { return ret; return ret; } } // Assumes that sStatsdLock is held. /** @GuardedBy("sStatsdLock") * Non-blocking call to retrieve a reference to statsd private void informAllUidsLocked(Context context) throws RemoteException { * * @return IStatsd object if statsd is ready, null otherwise. */ private static IStatsd getStatsdNonblocking() { synchronized (sStatsdLock) { return sStatsd; } } private static void informAllUidsLocked(Context context) throws RemoteException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); PackageManager pm = context.getPackageManager(); PackageManager pm = context.getPackageManager(); final List<UserHandle> users = um.getUserHandles(true); final List<UserHandle> users = um.getUserHandles(true); Loading Loading @@ -273,7 +259,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (!replacing) { if (!replacing) { // Don't bother sending an update if we're right about to get another // Don't bother sending an update if we're right about to get another // intent for the new version that's added. // intent for the new version that's added. PackageManager pm = context.getPackageManager(); String app = intent.getData().getSchemeSpecificPart(); String app = intent.getData().getSchemeSpecificPart(); sStatsd.informOnePackageRemoved(app, uid); sStatsd.informOnePackageRemoved(app, uid); } } Loading Loading @@ -303,23 +288,43 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } public final static class AnomalyAlarmListener implements OnAlarmListener { private static final class UserUpdateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { synchronized (sStatsdLock) { if (sStatsd == null) { Log.w(TAG, "Could not access statsd for UserUpdateReceiver"); return; } try { // Pull the latest state of UID->app name, version mapping. // Needed since the new user basically has a version of every app. informAllUidsLocked(context); } catch (RemoteException e) { Log.e(TAG, "Failed to inform statsd latest update of all apps", e); } } } } public static final class AnomalyAlarmListener implements OnAlarmListener { @Override @Override public void onAlarm() { public void onAlarm() { if (DEBUG) { Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time " Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time " + System.currentTimeMillis() + "ms."); + System.currentTimeMillis() + "ms."); synchronized (sStatsdLock) { } if (sStatsd == null) { IStatsd statsd = getStatsdNonblocking(); if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing"); Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing"); return; return; } } try { try { // Two-way call to statsd to retain AlarmManager wakelock // Two-way call to statsd to retain AlarmManager wakelock sStatsd.informAnomalyAlarmFired(); statsd.informAnomalyAlarmFired(); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e); Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e); } } } // AlarmManager releases its own wakelock here. // AlarmManager releases its own wakelock here. } } } } Loading @@ -330,20 +335,19 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (DEBUG) { if (DEBUG) { Log.d(TAG, "Time to poll something."); Log.d(TAG, "Time to poll something."); } } synchronized (sStatsdLock) { IStatsd statsd = getStatsdNonblocking(); if (sStatsd == null) { if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing."); Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing."); return; return; } } try { try { // Two-way call to statsd to retain AlarmManager wakelock // Two-way call to statsd to retain AlarmManager wakelock sStatsd.informPollAlarmFired(); statsd.informPollAlarmFired(); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e); Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e); } } } } } } } public final static class PeriodicAlarmListener implements OnAlarmListener { public final static class PeriodicAlarmListener implements OnAlarmListener { @Override @Override Loading @@ -351,18 +355,17 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (DEBUG) { if (DEBUG) { Log.d(TAG, "Time to trigger periodic alarm."); Log.d(TAG, "Time to trigger periodic alarm."); } } synchronized (sStatsdLock) { IStatsd statsd = getStatsdNonblocking(); if (sStatsd == null) { if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing."); Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing."); return; return; } } try { try { // Two-way call to statsd to retain AlarmManager wakelock // Two-way call to statsd to retain AlarmManager wakelock sStatsd.informAlarmForSubscriberTriggeringFired(); statsd.informAlarmForSubscriberTriggeringFired(); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e); Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e); } } } // AlarmManager releases its own wakelock here. // AlarmManager releases its own wakelock here. } } } } Loading @@ -379,20 +382,22 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { return; return; } } if (DEBUG) { Log.i(TAG, "StatsCompanionService noticed a shutdown."); Log.i(TAG, "StatsCompanionService noticed a shutdown."); synchronized (sStatsdLock) { } if (sStatsd == null) { IStatsd statsd = getStatsdNonblocking(); if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of a shutdown event."); Log.w(TAG, "Could not access statsd to inform it of a shutdown event."); return; return; } } try { try { sStatsd.informDeviceShutdown(); // two way binder call statsd.informDeviceShutdown(); } catch (Exception e) { } catch (Exception e) { Log.w(TAG, "Failed to inform statsd of a shutdown event.", e); Log.w(TAG, "Failed to inform statsd of a shutdown event.", e); } } } } } } } @Override // Binder call @Override // Binder call public void setAnomalyAlarm(long timestampMs) { public void setAnomalyAlarm(long timestampMs) { Loading Loading @@ -515,7 +520,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } @Override @Override // Binder call public void triggerUidSnapshot() { public void triggerUidSnapshot() { StatsCompanion.enforceStatsdCallingUid(); StatsCompanion.enforceStatsdCallingUid(); synchronized (sStatsdLock) { synchronized (sStatsdLock) { Loading @@ -525,7 +530,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Failed to trigger uid snapshot.", e); Log.e(TAG, "Failed to trigger uid snapshot.", e); } finally { } finally { restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } } } } } Loading @@ -539,15 +544,28 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // Statsd related code // Statsd related code /** /** * Fetches the statsd IBinder service. * Fetches the statsd IBinder service. This is a blocking call. * Note: This should only be called from sayHiToStatsd. All other clients should use the cached * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use * sStatsd with a null check. * the cached sStatsd via {@link #getStatsdNonblocking()}. */ */ private static IStatsd fetchStatsdService() { private IStatsd fetchStatsdService(StatsdDeathRecipient deathRecipient) { return IStatsd.Stub.asInterface(StatsFrameworkInitializer synchronized (sStatsdLock) { if (sStatsd == null) { sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer .getStatsServiceManager() .getStatsServiceManager() .getStatsdServiceRegisterer() .getStatsdServiceRegisterer() .get()); .get()); if (sStatsd != null) { try { sStatsd.asBinder().linkToDeath(deathRecipient, /* flags */ 0); } catch (RemoteException e) { Log.e(TAG, "linkToDeath(StatsdDeathRecipient) failed"); statsdNotReadyLocked(); } } } return sStatsd; } } } /** /** Loading @@ -567,67 +585,84 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { * statsd. * statsd. */ */ private void sayHiToStatsd() { private void sayHiToStatsd() { synchronized (sStatsdLock) { if (getStatsdNonblocking() != null) { if (sStatsd != null) { Log.e(TAG, "Trying to fetch statsd, but it was already fetched", Log.e(TAG, "Trying to fetch statsd, but it was already fetched", new IllegalStateException( new IllegalStateException( "sStatsd is not null when being fetched")); "sStatsd is not null when being fetched")); return; return; } } sStatsd = fetchStatsdService(); StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(); if (sStatsd == null) { IStatsd statsd = fetchStatsdService(deathRecipient); if (statsd == null) { Log.i(TAG, Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is " "Could not yet find statsd to tell it that StatsCompanion is " + "alive."); + "alive."); return; return; } } mStatsManagerService.statsdReady(sStatsd); mStatsManagerService.statsdReady(statsd); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); try { try { sStatsd.statsCompanionReady(); statsd.statsCompanionReady(); // If the statsCompanionReady two-way binder call returns, link to statsd. try { cancelAnomalyAlarm(); sStatsd.asBinder().linkToDeath(new StatsdDeathRecipient(), 0); cancelPullingAlarm(); } catch (RemoteException e) { Log.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e); BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver(); forgetEverythingLocked(); BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver(); } BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver(); // Setup broadcast receiver for updates. // Setup broadcast receiver for updates. IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); filter.addDataScheme("package"); mContext.registerReceiverForAllUsers(mAppUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); // Setup receiver for user initialize (which happens once for a new user) // Setup receiver for user initialize (which happens once for a new user) // and // and // if a user is removed. // if a user is removed. filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_REMOVED); mContext.registerReceiverForAllUsers(mUserUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); // Setup receiver for device reboots or shutdowns. // Setup receiver for device reboots or shutdowns. filter = new IntentFilter(Intent.ACTION_REBOOT); filter = new IntentFilter(Intent.ACTION_REBOOT); filter.addAction(Intent.ACTION_SHUTDOWN); filter.addAction(Intent.ACTION_SHUTDOWN); mContext.registerReceiverForAllUsers( mContext.registerReceiverForAllUsers( mShutdownEventReceiver, filter, null, null); shutdownEventReceiver, filter, null, null); // Only add the receivers if the registration is successful. deathRecipient.addRegisteredBroadcastReceivers( List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver)); final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity(); try { try { // Pull the latest state of UID->app name, version mapping when // Pull the latest state of UID->app name, version mapping when // statsd starts. // statsd starts. informAllUidsLocked(mContext); informAllUidsLocked(mContext); } finally { } finally { restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } Log.i(TAG, "Told statsd that StatsCompanionService is alive."); Log.i(TAG, "Told statsd that StatsCompanionService is alive."); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e); Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e); forgetEverythingLocked(); } } } } } private class StatsdDeathRecipient implements IBinder.DeathRecipient { private class StatsdDeathRecipient implements IBinder.DeathRecipient { private List<BroadcastReceiver> mReceiversToUnregister; StatsdDeathRecipient() { mReceiversToUnregister = new ArrayList<>(); } public void addRegisteredBroadcastReceivers(List<BroadcastReceiver> receivers) { synchronized (sStatsdLock) { mReceiversToUnregister.addAll(receivers); } } @Override @Override public void binderDied() { public void binderDied() { Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Loading Loading @@ -656,20 +691,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } } } forgetEverythingLocked(); // We only unregister in binder death becaseu receivers can only be unregistered // once, or an IllegalArgumentException is thrown. for (BroadcastReceiver receiver: mReceiversToUnregister) { mContext.unregisterReceiver(receiver); } statsdNotReadyLocked(); } } } } } } @GuardedBy("StatsCompanionService.sStatsdLock") private void statsdNotReadyLocked() { private void forgetEverythingLocked() { sStatsd = null; sStatsd = null; mContext.unregisterReceiver(mAppUpdateReceiver); mContext.unregisterReceiver(mUserUpdateReceiver); mContext.unregisterReceiver(mShutdownEventReceiver); cancelAnomalyAlarm(); cancelPullingAlarm(); mStatsManagerService.statsdNotReady(); mStatsManagerService.statsdNotReady(); } } Loading Loading
apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +176 −143 Original line number Original line Diff line number Diff line Loading @@ -54,6 +54,7 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.List; Loading Loading @@ -102,9 +103,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final OnAlarmListener mAnomalyAlarmListener = new AnomalyAlarmListener(); private final OnAlarmListener mAnomalyAlarmListener = new AnomalyAlarmListener(); private final OnAlarmListener mPullingAlarmListener = new PullingAlarmListener(); private final OnAlarmListener mPullingAlarmListener = new PullingAlarmListener(); private final OnAlarmListener mPeriodicAlarmListener = new PeriodicAlarmListener(); private final OnAlarmListener mPeriodicAlarmListener = new PeriodicAlarmListener(); private final BroadcastReceiver mAppUpdateReceiver; private final BroadcastReceiver mUserUpdateReceiver; private final ShutdownEventReceiver mShutdownEventReceiver; private StatsManagerService mStatsManagerService; private StatsManagerService mStatsManagerService; Loading @@ -118,27 +116,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { super(); super(); mContext = context; mContext = context; mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mAppUpdateReceiver = new AppUpdateReceiver(); mUserUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized (sStatsdLock) { if (sStatsd == null) { Log.w(TAG, "Could not access statsd for UserUpdateReceiver"); return; } try { // Pull the latest state of UID->app name, version mapping. // Needed since the new user basically has a version of every app. informAllUidsLocked(context); } catch (RemoteException e) { Log.e(TAG, "Failed to inform statsd latest update of all apps", e); forgetEverythingLocked(); } } } }; mShutdownEventReceiver = new ShutdownEventReceiver(); if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED."); if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED."); HandlerThread handlerThread = new HandlerThread(TAG); HandlerThread handlerThread = new HandlerThread(TAG); handlerThread.start(); handlerThread.start(); Loading @@ -162,9 +139,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { return ret; return ret; } } // Assumes that sStatsdLock is held. /** @GuardedBy("sStatsdLock") * Non-blocking call to retrieve a reference to statsd private void informAllUidsLocked(Context context) throws RemoteException { * * @return IStatsd object if statsd is ready, null otherwise. */ private static IStatsd getStatsdNonblocking() { synchronized (sStatsdLock) { return sStatsd; } } private static void informAllUidsLocked(Context context) throws RemoteException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); PackageManager pm = context.getPackageManager(); PackageManager pm = context.getPackageManager(); final List<UserHandle> users = um.getUserHandles(true); final List<UserHandle> users = um.getUserHandles(true); Loading Loading @@ -273,7 +259,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (!replacing) { if (!replacing) { // Don't bother sending an update if we're right about to get another // Don't bother sending an update if we're right about to get another // intent for the new version that's added. // intent for the new version that's added. PackageManager pm = context.getPackageManager(); String app = intent.getData().getSchemeSpecificPart(); String app = intent.getData().getSchemeSpecificPart(); sStatsd.informOnePackageRemoved(app, uid); sStatsd.informOnePackageRemoved(app, uid); } } Loading Loading @@ -303,23 +288,43 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } public final static class AnomalyAlarmListener implements OnAlarmListener { private static final class UserUpdateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { synchronized (sStatsdLock) { if (sStatsd == null) { Log.w(TAG, "Could not access statsd for UserUpdateReceiver"); return; } try { // Pull the latest state of UID->app name, version mapping. // Needed since the new user basically has a version of every app. informAllUidsLocked(context); } catch (RemoteException e) { Log.e(TAG, "Failed to inform statsd latest update of all apps", e); } } } } public static final class AnomalyAlarmListener implements OnAlarmListener { @Override @Override public void onAlarm() { public void onAlarm() { if (DEBUG) { Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time " Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time " + System.currentTimeMillis() + "ms."); + System.currentTimeMillis() + "ms."); synchronized (sStatsdLock) { } if (sStatsd == null) { IStatsd statsd = getStatsdNonblocking(); if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing"); Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing"); return; return; } } try { try { // Two-way call to statsd to retain AlarmManager wakelock // Two-way call to statsd to retain AlarmManager wakelock sStatsd.informAnomalyAlarmFired(); statsd.informAnomalyAlarmFired(); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e); Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e); } } } // AlarmManager releases its own wakelock here. // AlarmManager releases its own wakelock here. } } } } Loading @@ -330,20 +335,19 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (DEBUG) { if (DEBUG) { Log.d(TAG, "Time to poll something."); Log.d(TAG, "Time to poll something."); } } synchronized (sStatsdLock) { IStatsd statsd = getStatsdNonblocking(); if (sStatsd == null) { if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing."); Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing."); return; return; } } try { try { // Two-way call to statsd to retain AlarmManager wakelock // Two-way call to statsd to retain AlarmManager wakelock sStatsd.informPollAlarmFired(); statsd.informPollAlarmFired(); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e); Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e); } } } } } } } public final static class PeriodicAlarmListener implements OnAlarmListener { public final static class PeriodicAlarmListener implements OnAlarmListener { @Override @Override Loading @@ -351,18 +355,17 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { if (DEBUG) { if (DEBUG) { Log.d(TAG, "Time to trigger periodic alarm."); Log.d(TAG, "Time to trigger periodic alarm."); } } synchronized (sStatsdLock) { IStatsd statsd = getStatsdNonblocking(); if (sStatsd == null) { if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing."); Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing."); return; return; } } try { try { // Two-way call to statsd to retain AlarmManager wakelock // Two-way call to statsd to retain AlarmManager wakelock sStatsd.informAlarmForSubscriberTriggeringFired(); statsd.informAlarmForSubscriberTriggeringFired(); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e); Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e); } } } // AlarmManager releases its own wakelock here. // AlarmManager releases its own wakelock here. } } } } Loading @@ -379,20 +382,22 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { return; return; } } if (DEBUG) { Log.i(TAG, "StatsCompanionService noticed a shutdown."); Log.i(TAG, "StatsCompanionService noticed a shutdown."); synchronized (sStatsdLock) { } if (sStatsd == null) { IStatsd statsd = getStatsdNonblocking(); if (statsd == null) { Log.w(TAG, "Could not access statsd to inform it of a shutdown event."); Log.w(TAG, "Could not access statsd to inform it of a shutdown event."); return; return; } } try { try { sStatsd.informDeviceShutdown(); // two way binder call statsd.informDeviceShutdown(); } catch (Exception e) { } catch (Exception e) { Log.w(TAG, "Failed to inform statsd of a shutdown event.", e); Log.w(TAG, "Failed to inform statsd of a shutdown event.", e); } } } } } } } @Override // Binder call @Override // Binder call public void setAnomalyAlarm(long timestampMs) { public void setAnomalyAlarm(long timestampMs) { Loading Loading @@ -515,7 +520,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } @Override @Override // Binder call public void triggerUidSnapshot() { public void triggerUidSnapshot() { StatsCompanion.enforceStatsdCallingUid(); StatsCompanion.enforceStatsdCallingUid(); synchronized (sStatsdLock) { synchronized (sStatsdLock) { Loading @@ -525,7 +530,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Failed to trigger uid snapshot.", e); Log.e(TAG, "Failed to trigger uid snapshot.", e); } finally { } finally { restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } } } } } Loading @@ -539,15 +544,28 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // Statsd related code // Statsd related code /** /** * Fetches the statsd IBinder service. * Fetches the statsd IBinder service. This is a blocking call. * Note: This should only be called from sayHiToStatsd. All other clients should use the cached * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use * sStatsd with a null check. * the cached sStatsd via {@link #getStatsdNonblocking()}. */ */ private static IStatsd fetchStatsdService() { private IStatsd fetchStatsdService(StatsdDeathRecipient deathRecipient) { return IStatsd.Stub.asInterface(StatsFrameworkInitializer synchronized (sStatsdLock) { if (sStatsd == null) { sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer .getStatsServiceManager() .getStatsServiceManager() .getStatsdServiceRegisterer() .getStatsdServiceRegisterer() .get()); .get()); if (sStatsd != null) { try { sStatsd.asBinder().linkToDeath(deathRecipient, /* flags */ 0); } catch (RemoteException e) { Log.e(TAG, "linkToDeath(StatsdDeathRecipient) failed"); statsdNotReadyLocked(); } } } return sStatsd; } } } /** /** Loading @@ -567,67 +585,84 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { * statsd. * statsd. */ */ private void sayHiToStatsd() { private void sayHiToStatsd() { synchronized (sStatsdLock) { if (getStatsdNonblocking() != null) { if (sStatsd != null) { Log.e(TAG, "Trying to fetch statsd, but it was already fetched", Log.e(TAG, "Trying to fetch statsd, but it was already fetched", new IllegalStateException( new IllegalStateException( "sStatsd is not null when being fetched")); "sStatsd is not null when being fetched")); return; return; } } sStatsd = fetchStatsdService(); StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(); if (sStatsd == null) { IStatsd statsd = fetchStatsdService(deathRecipient); if (statsd == null) { Log.i(TAG, Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is " "Could not yet find statsd to tell it that StatsCompanion is " + "alive."); + "alive."); return; return; } } mStatsManagerService.statsdReady(sStatsd); mStatsManagerService.statsdReady(statsd); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); try { try { sStatsd.statsCompanionReady(); statsd.statsCompanionReady(); // If the statsCompanionReady two-way binder call returns, link to statsd. try { cancelAnomalyAlarm(); sStatsd.asBinder().linkToDeath(new StatsdDeathRecipient(), 0); cancelPullingAlarm(); } catch (RemoteException e) { Log.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e); BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver(); forgetEverythingLocked(); BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver(); } BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver(); // Setup broadcast receiver for updates. // Setup broadcast receiver for updates. IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); filter.addDataScheme("package"); mContext.registerReceiverForAllUsers(mAppUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); // Setup receiver for user initialize (which happens once for a new user) // Setup receiver for user initialize (which happens once for a new user) // and // and // if a user is removed. // if a user is removed. filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_REMOVED); mContext.registerReceiverForAllUsers(mUserUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); // Setup receiver for device reboots or shutdowns. // Setup receiver for device reboots or shutdowns. filter = new IntentFilter(Intent.ACTION_REBOOT); filter = new IntentFilter(Intent.ACTION_REBOOT); filter.addAction(Intent.ACTION_SHUTDOWN); filter.addAction(Intent.ACTION_SHUTDOWN); mContext.registerReceiverForAllUsers( mContext.registerReceiverForAllUsers( mShutdownEventReceiver, filter, null, null); shutdownEventReceiver, filter, null, null); // Only add the receivers if the registration is successful. deathRecipient.addRegisteredBroadcastReceivers( List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver)); final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity(); try { try { // Pull the latest state of UID->app name, version mapping when // Pull the latest state of UID->app name, version mapping when // statsd starts. // statsd starts. informAllUidsLocked(mContext); informAllUidsLocked(mContext); } finally { } finally { restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } Log.i(TAG, "Told statsd that StatsCompanionService is alive."); Log.i(TAG, "Told statsd that StatsCompanionService is alive."); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e); Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e); forgetEverythingLocked(); } } } } } private class StatsdDeathRecipient implements IBinder.DeathRecipient { private class StatsdDeathRecipient implements IBinder.DeathRecipient { private List<BroadcastReceiver> mReceiversToUnregister; StatsdDeathRecipient() { mReceiversToUnregister = new ArrayList<>(); } public void addRegisteredBroadcastReceivers(List<BroadcastReceiver> receivers) { synchronized (sStatsdLock) { mReceiversToUnregister.addAll(receivers); } } @Override @Override public void binderDied() { public void binderDied() { Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Loading Loading @@ -656,20 +691,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } } } forgetEverythingLocked(); // We only unregister in binder death becaseu receivers can only be unregistered // once, or an IllegalArgumentException is thrown. for (BroadcastReceiver receiver: mReceiversToUnregister) { mContext.unregisterReceiver(receiver); } statsdNotReadyLocked(); } } } } } } @GuardedBy("StatsCompanionService.sStatsdLock") private void statsdNotReadyLocked() { private void forgetEverythingLocked() { sStatsd = null; sStatsd = null; mContext.unregisterReceiver(mAppUpdateReceiver); mContext.unregisterReceiver(mUserUpdateReceiver); mContext.unregisterReceiver(mShutdownEventReceiver); cancelAnomalyAlarm(); cancelPullingAlarm(); mStatsManagerService.statsdNotReady(); mStatsManagerService.statsdNotReady(); } } Loading