Fix statsd NPE on setPullAtomCallback

Suspected root cause: if a process crashes right after calling
setPullAtomCallback, it's possible that oneway binder calls can queue
but do not execute before the process crashes. Then, when the process
crashes, nothing has a strong reference to the IPullAtomCallback, so
it gets deallocated. Then, when the oneway call actually executes, the
callback is null. This is being followed up in b/155793159

Regardless, statsd should handle null input properly.

Test: GTS test in ag/11348719 now passes
Test: atest GtsStatsdHostTestCases
Bug: 153822941
Change-Id: Ic6d415e10eca8d133290de80cb61e1634590ca6a
This commit is contained in:
Tej Singh
2020-05-01 17:30:00 -07:00
parent 5a61909275
commit baed5257ad
3 changed files with 9 additions and 4 deletions

View File

@@ -28,7 +28,6 @@ import android.os.Binder;
import android.os.IPullAtomCallback;
import android.os.IPullAtomResultReceiver;
import android.os.IStatsManagerService;
import android.os.IStatsd;
import android.os.RemoteException;
import android.os.StatsFrameworkInitializer;
import android.util.AndroidException;
@@ -56,9 +55,6 @@ public final class StatsManager {
private static final Object sLock = new Object();
private final Context mContext;
@GuardedBy("sLock")
private IStatsd mService;
@GuardedBy("sLock")
private IStatsManagerService mStatsManagerService;

View File

@@ -172,6 +172,10 @@ public class StatsManagerService extends IStatsManagerService.Stub {
public void registerPullAtomCallback(int atomTag, long coolDownMillis, long timeoutMillis,
int[] additiveFields, IPullAtomCallback pullerCallback) {
enforceRegisterStatsPullAtomPermission();
if (pullerCallback == null) {
Log.w(TAG, "Puller callback is null for atom " + atomTag);
return;
}
int callingUid = Binder.getCallingUid();
PullerKey key = new PullerKey(callingUid, atomTag);
PullerValue val =

View File

@@ -354,6 +354,11 @@ void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t a
std::lock_guard<std::mutex> _l(mLock);
VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
if (callback == nullptr) {
ALOGW("SetPullAtomCallback called with null callback for atom %d.", atomTag);
return;
}
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
int64_t actualCoolDownNs = coolDownNs < kMinCoolDownNs ? kMinCoolDownNs : coolDownNs;
int64_t actualTimeoutNs = timeoutNs > kMaxTimeoutNs ? kMaxTimeoutNs : timeoutNs;