Loading core/java/android/app/ContextImpl.java +11 −5 Original line number Diff line number Diff line Loading @@ -3431,9 +3431,7 @@ class ContextImpl extends Context { // if this Context is not a WindowContext. WindowContext finalization is handled in // WindowContext class. try { if (!(com.android.window.flags.Flags.cleanUpWindowContextWithCleaner() || com.android.window.flags.Flags.trackSystemUiContextBeforeWms()) && mToken instanceof WindowTokenClient && mOwnsToken) { if (!isCleanerEnabled() && mToken instanceof WindowTokenClient && mOwnsToken) { WindowTokenClientController.getInstance() .detachIfNeeded((WindowTokenClient) mToken); } Loading @@ -3442,6 +3440,15 @@ class ContextImpl extends Context { } } /** * Returns {@code true} if {@link WindowContext#registerCleaner} is enabled. */ private static boolean isCleanerEnabled() { return com.android.window.flags.Flags.cleanUpWindowContextWithCleaner() // Cleaner only works on SystemUiContext or WindowContext. && com.android.window.flags.Flags.trackSystemUiContextBeforeWms(); } @UnsupportedAppUsage static ContextImpl createSystemContext(ActivityThread mainThread) { LoadedApk packageInfo = new LoadedApk(mainThread); Loading Loading @@ -3482,8 +3489,7 @@ class ContextImpl extends Context { WindowTokenClientController.getInstance().attachToDisplayContent(token, displayId); context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI; context.mOwnsToken = true; if (!com.android.window.flags.Flags.trackSystemUiContextBeforeWms()) { // #registerCleaner only support SystemUiContext or WindowContext. if (isCleanerEnabled()) { registerCleaner(systemUiContext); } return systemUiContext; Loading core/tests/coretests/src/android/content/ContextTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,13 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import android.app.ActivityThread; import android.content.res.Configuration; Loading @@ -46,18 +53,22 @@ import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.ravenwood.RavenwoodRule; import android.view.Display; import android.window.WindowTokenClient; import android.window.WindowTokenClientController; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.util.GcUtils; import com.android.window.flags.Flags; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.ref.WeakReference; /** * Build/Install/Run: * atest FrameworksCoreTests:ContextTest Loading Loading @@ -331,4 +342,27 @@ public class ContextTest { assertWithMessage("ComponentCallbacks should delegate to SystemUiContext " + "if the flag is enabled.").that(callbacks.mConfiguration).isEqualTo(config); } @Test @DisabledOnRavenwood(blockedBy = Context.class) public void testSystemUiContextCleanUp() { final WindowTokenClientController origController = WindowTokenClientController.getInstance(); final WindowTokenClientController mockController = mock(WindowTokenClientController.class); doReturn(true).when(mockController).attachToDisplayContent(any(), anyInt()); doNothing().when(mockController).detachIfNeeded(any()); WindowTokenClientController.overrideForTesting(mockController); WeakReference<Context> windowContextRef = new WeakReference<>( ActivityThread.currentActivityThread() .createSystemUiContextForTesting(DEFAULT_DISPLAY)); final WindowTokenClient token = (WindowTokenClient) windowContextRef.get().getWindowContextToken(); GcUtils.runGcAndFinalizersSync(); verify(mockController).detachIfNeeded(eq(token)); WindowTokenClientController.overrideForTesting(origController); } } core/tests/coretests/src/android/window/WindowContextTest.java +12 −10 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; Loading Loading @@ -82,6 +84,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.ref.WeakReference; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -527,20 +530,19 @@ public class WindowContextTest { @Test public void testWindowContextCleanup() { final WindowContext windowContext = createWindowContext(); final WindowTokenClientController mockController = mock(WindowTokenClientController.class); doReturn(true).when(mockController).attachToDisplayArea( any(), anyInt(), anyInt(), any()); doNothing().when(mockController).detachIfNeeded(any()); WindowTokenClientController.overrideForTesting(mockController); windowContext.getSystemService(WindowManager.class).getCurrentWindowMetrics(); WeakReference<WindowContext> windowContextRef = new WeakReference<>(createWindowContext()); final WindowTokenClient token = (WindowTokenClient) windowContextRef.get().getWindowContextToken(); GcUtils.runGcAndFinalizersSync(); PollingCheck.waitFor(() -> { try { return !mWms.isWindowToken(windowContext.getWindowContextToken()); } catch (RemoteException e) { fail("Fail due to " + e); } return false; }); verify(mockController).detachIfNeeded(eq(token)); } private static class ConfigurationListener implements ComponentCallbacks { Loading Loading
core/java/android/app/ContextImpl.java +11 −5 Original line number Diff line number Diff line Loading @@ -3431,9 +3431,7 @@ class ContextImpl extends Context { // if this Context is not a WindowContext. WindowContext finalization is handled in // WindowContext class. try { if (!(com.android.window.flags.Flags.cleanUpWindowContextWithCleaner() || com.android.window.flags.Flags.trackSystemUiContextBeforeWms()) && mToken instanceof WindowTokenClient && mOwnsToken) { if (!isCleanerEnabled() && mToken instanceof WindowTokenClient && mOwnsToken) { WindowTokenClientController.getInstance() .detachIfNeeded((WindowTokenClient) mToken); } Loading @@ -3442,6 +3440,15 @@ class ContextImpl extends Context { } } /** * Returns {@code true} if {@link WindowContext#registerCleaner} is enabled. */ private static boolean isCleanerEnabled() { return com.android.window.flags.Flags.cleanUpWindowContextWithCleaner() // Cleaner only works on SystemUiContext or WindowContext. && com.android.window.flags.Flags.trackSystemUiContextBeforeWms(); } @UnsupportedAppUsage static ContextImpl createSystemContext(ActivityThread mainThread) { LoadedApk packageInfo = new LoadedApk(mainThread); Loading Loading @@ -3482,8 +3489,7 @@ class ContextImpl extends Context { WindowTokenClientController.getInstance().attachToDisplayContent(token, displayId); context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI; context.mOwnsToken = true; if (!com.android.window.flags.Flags.trackSystemUiContextBeforeWms()) { // #registerCleaner only support SystemUiContext or WindowContext. if (isCleanerEnabled()) { registerCleaner(systemUiContext); } return systemUiContext; Loading
core/tests/coretests/src/android/content/ContextTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,13 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import android.app.ActivityThread; import android.content.res.Configuration; Loading @@ -46,18 +53,22 @@ import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.ravenwood.RavenwoodRule; import android.view.Display; import android.window.WindowTokenClient; import android.window.WindowTokenClientController; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.util.GcUtils; import com.android.window.flags.Flags; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.ref.WeakReference; /** * Build/Install/Run: * atest FrameworksCoreTests:ContextTest Loading Loading @@ -331,4 +342,27 @@ public class ContextTest { assertWithMessage("ComponentCallbacks should delegate to SystemUiContext " + "if the flag is enabled.").that(callbacks.mConfiguration).isEqualTo(config); } @Test @DisabledOnRavenwood(blockedBy = Context.class) public void testSystemUiContextCleanUp() { final WindowTokenClientController origController = WindowTokenClientController.getInstance(); final WindowTokenClientController mockController = mock(WindowTokenClientController.class); doReturn(true).when(mockController).attachToDisplayContent(any(), anyInt()); doNothing().when(mockController).detachIfNeeded(any()); WindowTokenClientController.overrideForTesting(mockController); WeakReference<Context> windowContextRef = new WeakReference<>( ActivityThread.currentActivityThread() .createSystemUiContextForTesting(DEFAULT_DISPLAY)); final WindowTokenClient token = (WindowTokenClient) windowContextRef.get().getWindowContextToken(); GcUtils.runGcAndFinalizersSync(); verify(mockController).detachIfNeeded(eq(token)); WindowTokenClientController.overrideForTesting(origController); } }
core/tests/coretests/src/android/window/WindowContextTest.java +12 −10 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; Loading Loading @@ -82,6 +84,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.ref.WeakReference; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -527,20 +530,19 @@ public class WindowContextTest { @Test public void testWindowContextCleanup() { final WindowContext windowContext = createWindowContext(); final WindowTokenClientController mockController = mock(WindowTokenClientController.class); doReturn(true).when(mockController).attachToDisplayArea( any(), anyInt(), anyInt(), any()); doNothing().when(mockController).detachIfNeeded(any()); WindowTokenClientController.overrideForTesting(mockController); windowContext.getSystemService(WindowManager.class).getCurrentWindowMetrics(); WeakReference<WindowContext> windowContextRef = new WeakReference<>(createWindowContext()); final WindowTokenClient token = (WindowTokenClient) windowContextRef.get().getWindowContextToken(); GcUtils.runGcAndFinalizersSync(); PollingCheck.waitFor(() -> { try { return !mWms.isWindowToken(windowContext.getWindowContextToken()); } catch (RemoteException e) { fail("Fail due to " + e); } return false; }); verify(mockController).detachIfNeeded(eq(token)); } private static class ConfigurationListener implements ComponentCallbacks { Loading