Fix NetworkStatsObersers thread leak in the NetworkStatsServiceTest
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.net.NetworkStatsServiceTest
(with debug code that dump all threads at the end of tests)
Fix: 308544001
Change-Id: I597054633bbb008ffd0edebe34dcf6935958aa5d
This commit is contained in:
@@ -142,6 +142,11 @@ class NetworkStatsObservers {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected Looper getHandlerLooperLocked() {
|
protected Looper getHandlerLooperLocked() {
|
||||||
|
// TODO: Currently, callbacks are dispatched on this thread if the caller register
|
||||||
|
// callback without supplying a Handler. To ensure that the service handler thread
|
||||||
|
// is not blocked by client code, the observers must create their own thread. Once
|
||||||
|
// all callbacks are dispatched outside of the handler thread, the service handler
|
||||||
|
// thread can be used here.
|
||||||
HandlerThread handlerThread = new HandlerThread(TAG);
|
HandlerThread handlerThread = new HandlerThread(TAG);
|
||||||
handlerThread.start();
|
handlerThread.start();
|
||||||
return handlerThread.getLooper();
|
return handlerThread.getLooper();
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class NetworkStatsObserversTest {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
mObserverHandlerThread = new HandlerThread("HandlerThread");
|
mObserverHandlerThread = new HandlerThread("NetworkStatsObserversTest");
|
||||||
mObserverHandlerThread.start();
|
mObserverHandlerThread.start();
|
||||||
final Looper observerLooper = mObserverHandlerThread.getLooper();
|
final Looper observerLooper = mObserverHandlerThread.getLooper();
|
||||||
mStatsObservers = new NetworkStatsObservers() {
|
mStatsObservers = new NetworkStatsObservers() {
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ import android.os.DropBoxManager;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SimpleClock;
|
import android.os.SimpleClock;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -284,6 +285,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
|||||||
private @Mock PersistentInt mImportLegacyFallbacksCounter;
|
private @Mock PersistentInt mImportLegacyFallbacksCounter;
|
||||||
private @Mock Resources mResources;
|
private @Mock Resources mResources;
|
||||||
private Boolean mIsDebuggable;
|
private Boolean mIsDebuggable;
|
||||||
|
private HandlerThread mObserverHandlerThread;
|
||||||
|
|
||||||
private class MockContext extends BroadcastInterceptingContext {
|
private class MockContext extends BroadcastInterceptingContext {
|
||||||
private final Context mBaseContext;
|
private final Context mBaseContext;
|
||||||
@@ -365,10 +367,23 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
|||||||
PowerManager.WakeLock wakeLock =
|
PowerManager.WakeLock wakeLock =
|
||||||
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||||
|
|
||||||
mHandlerThread = new HandlerThread("HandlerThread");
|
mHandlerThread = new HandlerThread("NetworkStatsServiceTest-HandlerThread");
|
||||||
final NetworkStatsService.Dependencies deps = makeDependencies();
|
final NetworkStatsService.Dependencies deps = makeDependencies();
|
||||||
|
// Create a separate thread for observers to run on. This thread cannot be the same
|
||||||
|
// as the handler thread, because the observer callback is fired on this thread, and
|
||||||
|
// it should not be blocked by client code. Additionally, creating the observers
|
||||||
|
// object requires a looper, which can only be obtained after a thread has been started.
|
||||||
|
mObserverHandlerThread = new HandlerThread("NetworkStatsServiceTest-ObserversThread");
|
||||||
|
mObserverHandlerThread.start();
|
||||||
|
final Looper observerLooper = mObserverHandlerThread.getLooper();
|
||||||
|
final NetworkStatsObservers statsObservers = new NetworkStatsObservers() {
|
||||||
|
@Override
|
||||||
|
protected Looper getHandlerLooperLocked() {
|
||||||
|
return observerLooper;
|
||||||
|
}
|
||||||
|
};
|
||||||
mService = new NetworkStatsService(mServiceContext, mNetd, mAlarmManager, wakeLock,
|
mService = new NetworkStatsService(mServiceContext, mNetd, mAlarmManager, wakeLock,
|
||||||
mClock, mSettings, mStatsFactory, new NetworkStatsObservers(), deps);
|
mClock, mSettings, mStatsFactory, statsObservers, deps);
|
||||||
|
|
||||||
mElapsedRealtime = 0L;
|
mElapsedRealtime = 0L;
|
||||||
|
|
||||||
@@ -545,8 +560,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
|||||||
mSession.close();
|
mSession.close();
|
||||||
mService = null;
|
mService = null;
|
||||||
|
|
||||||
mHandlerThread.quitSafely();
|
if (mHandlerThread != null) {
|
||||||
mHandlerThread.join();
|
mHandlerThread.quitSafely();
|
||||||
|
mHandlerThread.join();
|
||||||
|
}
|
||||||
|
if (mObserverHandlerThread != null) {
|
||||||
|
mObserverHandlerThread.quitSafely();
|
||||||
|
mObserverHandlerThread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception {
|
private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user