diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index a174fe34ce..d16a6f5508 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -2589,9 +2589,24 @@ public class ConnectivityManager { * {@hide} */ public ConnectivityManager(Context context, IConnectivityManager service) { + this(context, service, true /* newStatic */); + } + + private ConnectivityManager(Context context, IConnectivityManager service, boolean newStatic) { mContext = Objects.requireNonNull(context, "missing context"); mService = Objects.requireNonNull(service, "missing IConnectivityManager"); - sInstance = this; + // sInstance is accessed without a lock, so it may actually be reassigned several times with + // different ConnectivityManager, but that's still OK considering its usage. + if (sInstance == null && newStatic) { + final Context appContext = mContext.getApplicationContext(); + // Don't create static ConnectivityManager instance again to prevent infinite loop. + // If the application context is null, we're either in the system process or + // it's the application context very early in app initialization. In both these + // cases, the passed-in Context will not be freed, so it's safe to pass it to the + // service. http://b/27532714 . + sInstance = new ConnectivityManager(appContext != null ? appContext : context, service, + false /* newStatic */); + } } /** {@hide} */ diff --git a/tests/unit/java/android/net/ConnectivityManagerTest.java b/tests/unit/java/android/net/ConnectivityManagerTest.java index f64ae5816a..c327868b41 100644 --- a/tests/unit/java/android/net/ConnectivityManagerTest.java +++ b/tests/unit/java/android/net/ConnectivityManagerTest.java @@ -41,6 +41,7 @@ import static com.android.testutils.MiscAsserts.assertThrows; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -506,8 +507,7 @@ public class ConnectivityManagerTest { Thread.sleep(waitIntervalMs); } - // TODO: fix memory leak then assertNull here. - assertNotNull("Couldn't find the Context leak in ConnectivityManager after " + attempts - + " attempts", ref.get()); + assertNull("ConnectivityManager weak reference still not null after " + attempts + + " attempts", ref.get()); } }