Merge "Cleanup threading in StatsCompanionService" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c7a08b57d4
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user