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