Loading core/java/android/window/DesktopExperienceFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -244,6 +244,8 @@ public enum DesktopExperienceFlags { Flags.FLAG_ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS), ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY(Flags::enablePerDisplayDesktopWallpaperActivity, true, Flags.FLAG_ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY), ENABLE_PER_DISPLAY_WINDOW_DECOR_VIEW_HOST_POOL(Flags::enablePerDisplayWindowDecorViewHostPool, false, Flags.FLAG_ENABLE_PER_DISPLAY_WINDOW_DECOR_VIEW_HOST_POOL), ENABLE_PINNING_APP_WITH_CONTEXT_MENU(Flags::enablePinningAppWithContextMenu, true, Flags.FLAG_ENABLE_PINNING_APP_WITH_CONTEXT_MENU), ENABLE_PIP_PARAMS_UPDATE_NOTIFICATION_BUGFIX( Loading core/java/android/window/flags/lse_desktop_experience.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1246,6 +1246,16 @@ flag { } } flag { name: "enable_per_display_window_decor_view_host_pool" namespace: "lse_desktop_experience" description: "Enables per-display WindowDecoration ViewHost pooling" bug: "440247561" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_persisting_display_size_for_connected_displays" namespace: "lse_desktop_experience" Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -509,13 +509,15 @@ public abstract class WMShellModule { @NonNull Context context, @ShellMainThread @NonNull CoroutineScope mainScope, @NonNull ShellInit shellInit, DisplayController displayController, DesktopState desktopState, DesktopConfig desktopConfig) { final int poolSize = desktopConfig.getWindowDecorScvhPoolSize(); final int preWarmSize = desktopConfig.getWindowDecorPreWarmSize(); if (desktopState.canEnterDesktopModeOrShowAppHandle() && poolSize > 0) { return new PooledWindowDecorViewHostSupplier( context, mainScope, shellInit, poolSize, preWarmSize); context, mainScope, shellInit, desktopState, displayController, poolSize, preWarmSize); } return new DefaultWindowDecorViewHostSupplier(mainScope); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/viewhost/DefaultWindowDecorViewHost.kt +4 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ import kotlinx.coroutines.launch class DefaultWindowDecorViewHost( context: Context, @ShellMainThread private val mainScope: CoroutineScope, display: Display, private val display: Display, @VisibleForTesting val viewHostAdapter: SurfaceControlViewHostAdapter = SurfaceControlViewHostAdapter(context, display), Loading @@ -48,6 +48,9 @@ class DefaultWindowDecorViewHost( override val surfaceControl: SurfaceControl get() = viewHostAdapter.rootSurface override val displayId: Int get() = display.displayId override fun updateView( view: View, attrs: WindowManager.LayoutParams, Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/viewhost/PooledWindowDecorViewHostSupplier.kt +65 −9 Original line number Diff line number Diff line Loading @@ -19,9 +19,12 @@ import android.content.Context import android.os.Trace import android.util.Pools import android.view.Display import android.view.Display.DEFAULT_DISPLAY import android.view.SurfaceControl import android.window.DesktopExperienceFlags import com.android.wm.shell.common.DisplayController import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopState import com.android.wm.shell.sysui.ShellInit import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch Loading @@ -42,12 +45,16 @@ class PooledWindowDecorViewHostSupplier( private val context: Context, @ShellMainThread private val mainScope: CoroutineScope, shellInit: ShellInit, maxPoolSize: Int, private val desktopState: DesktopState, private val displayController: DisplayController, private val maxPoolSize: Int, private val preWarmSize: Int, ) : WindowDecorViewHostSupplier<WindowDecorViewHost> { private val pool: Pools.Pool<WindowDecorViewHost> = Pools.SynchronizedPool(maxPoolSize) private val displayPools: HashMap<Int, Pools.Pool<WindowDecorViewHost>> = HashMap() private var nextDecorViewHostId = 0 private val enablePerDisplayPool = DesktopExperienceFlags.ENABLE_PER_DISPLAY_WINDOW_DECOR_VIEW_HOST_POOL.isTrue init { require(preWarmSize <= maxPoolSize) { "Pre-warm size should not exceed pool size" } Loading @@ -55,18 +62,57 @@ class PooledWindowDecorViewHostSupplier( } private fun onShellInit() { if (!enablePerDisplayPool) { if (preWarmSize <= 0) { return } preWarmViewHosts(preWarmSize) return } displayController.addDisplayWindowListener( object : DisplayController.OnDisplaysChangedListener { override fun onDisplayAdded(displayId: Int) { if (displayPools.containsKey(displayId)) { return } displayPools[displayId] = Pools.SynchronizedPool(maxPoolSize) private fun preWarmViewHosts(preWarmSize: Int) { if ( preWarmSize > 0 && desktopState.isDesktopModeSupportedOnDisplay(displayId) ) { preWarmViewHosts(preWarmSize, displayId) } } override fun onDisplayRemoved(displayId: Int) { val displayPool = displayPools.remove(displayId) // Release all the viewHosts in the pool var pooledViewHost = displayPool?.acquire() val transaction = SurfaceControl.Transaction() while (pooledViewHost != null) { pooledViewHost.release(transaction) pooledViewHost = displayPool?.acquire() } transaction.apply() } } ) } private fun preWarmViewHosts(preWarmSize: Int, displayId: Int = DEFAULT_DISPLAY) { mainScope.launch { // Applying isn't needed, as the surface was never actually shown. val t = SurfaceControl.Transaction() val displayContext = if (enablePerDisplayPool) { displayController.getDisplayContext(displayId) ?: return@launch } else { context } repeat(preWarmSize) { val warmedViewHost = newInstance(context, context.display).apply { warmUp() } val warmedViewHost = newInstance(displayContext, displayContext.display).apply { warmUp() } // Put the warmed view host in the pool by releasing it. release(warmedViewHost, t) } Loading @@ -74,7 +120,12 @@ class PooledWindowDecorViewHostSupplier( } override fun acquire(context: Context, display: Display): WindowDecorViewHost { val pooledViewHost = pool.acquire() val pooledViewHost = if (enablePerDisplayPool) { displayPools[display.displayId]?.acquire() } else { pool.acquire() } if (pooledViewHost != null) { return pooledViewHost } Loading @@ -88,8 +139,13 @@ class PooledWindowDecorViewHostSupplier( if (DesktopExperienceFlags.ENABLE_CLEAR_REUSABLE_SCVH_ON_RELEASE.isTrue) { viewHost.reset() } val pooled = pool.release(viewHost) if (!pooled) { val displayPool = if (enablePerDisplayPool) { displayPools[viewHost.displayId] } else { pool } if (displayPool == null || !displayPool.release(viewHost)) { viewHost.release(t) } } Loading Loading
core/java/android/window/DesktopExperienceFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -244,6 +244,8 @@ public enum DesktopExperienceFlags { Flags.FLAG_ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS), ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY(Flags::enablePerDisplayDesktopWallpaperActivity, true, Flags.FLAG_ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY), ENABLE_PER_DISPLAY_WINDOW_DECOR_VIEW_HOST_POOL(Flags::enablePerDisplayWindowDecorViewHostPool, false, Flags.FLAG_ENABLE_PER_DISPLAY_WINDOW_DECOR_VIEW_HOST_POOL), ENABLE_PINNING_APP_WITH_CONTEXT_MENU(Flags::enablePinningAppWithContextMenu, true, Flags.FLAG_ENABLE_PINNING_APP_WITH_CONTEXT_MENU), ENABLE_PIP_PARAMS_UPDATE_NOTIFICATION_BUGFIX( Loading
core/java/android/window/flags/lse_desktop_experience.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1246,6 +1246,16 @@ flag { } } flag { name: "enable_per_display_window_decor_view_host_pool" namespace: "lse_desktop_experience" description: "Enables per-display WindowDecoration ViewHost pooling" bug: "440247561" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_persisting_display_size_for_connected_displays" namespace: "lse_desktop_experience" Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -509,13 +509,15 @@ public abstract class WMShellModule { @NonNull Context context, @ShellMainThread @NonNull CoroutineScope mainScope, @NonNull ShellInit shellInit, DisplayController displayController, DesktopState desktopState, DesktopConfig desktopConfig) { final int poolSize = desktopConfig.getWindowDecorScvhPoolSize(); final int preWarmSize = desktopConfig.getWindowDecorPreWarmSize(); if (desktopState.canEnterDesktopModeOrShowAppHandle() && poolSize > 0) { return new PooledWindowDecorViewHostSupplier( context, mainScope, shellInit, poolSize, preWarmSize); context, mainScope, shellInit, desktopState, displayController, poolSize, preWarmSize); } return new DefaultWindowDecorViewHostSupplier(mainScope); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/viewhost/DefaultWindowDecorViewHost.kt +4 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ import kotlinx.coroutines.launch class DefaultWindowDecorViewHost( context: Context, @ShellMainThread private val mainScope: CoroutineScope, display: Display, private val display: Display, @VisibleForTesting val viewHostAdapter: SurfaceControlViewHostAdapter = SurfaceControlViewHostAdapter(context, display), Loading @@ -48,6 +48,9 @@ class DefaultWindowDecorViewHost( override val surfaceControl: SurfaceControl get() = viewHostAdapter.rootSurface override val displayId: Int get() = display.displayId override fun updateView( view: View, attrs: WindowManager.LayoutParams, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/viewhost/PooledWindowDecorViewHostSupplier.kt +65 −9 Original line number Diff line number Diff line Loading @@ -19,9 +19,12 @@ import android.content.Context import android.os.Trace import android.util.Pools import android.view.Display import android.view.Display.DEFAULT_DISPLAY import android.view.SurfaceControl import android.window.DesktopExperienceFlags import com.android.wm.shell.common.DisplayController import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopState import com.android.wm.shell.sysui.ShellInit import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch Loading @@ -42,12 +45,16 @@ class PooledWindowDecorViewHostSupplier( private val context: Context, @ShellMainThread private val mainScope: CoroutineScope, shellInit: ShellInit, maxPoolSize: Int, private val desktopState: DesktopState, private val displayController: DisplayController, private val maxPoolSize: Int, private val preWarmSize: Int, ) : WindowDecorViewHostSupplier<WindowDecorViewHost> { private val pool: Pools.Pool<WindowDecorViewHost> = Pools.SynchronizedPool(maxPoolSize) private val displayPools: HashMap<Int, Pools.Pool<WindowDecorViewHost>> = HashMap() private var nextDecorViewHostId = 0 private val enablePerDisplayPool = DesktopExperienceFlags.ENABLE_PER_DISPLAY_WINDOW_DECOR_VIEW_HOST_POOL.isTrue init { require(preWarmSize <= maxPoolSize) { "Pre-warm size should not exceed pool size" } Loading @@ -55,18 +62,57 @@ class PooledWindowDecorViewHostSupplier( } private fun onShellInit() { if (!enablePerDisplayPool) { if (preWarmSize <= 0) { return } preWarmViewHosts(preWarmSize) return } displayController.addDisplayWindowListener( object : DisplayController.OnDisplaysChangedListener { override fun onDisplayAdded(displayId: Int) { if (displayPools.containsKey(displayId)) { return } displayPools[displayId] = Pools.SynchronizedPool(maxPoolSize) private fun preWarmViewHosts(preWarmSize: Int) { if ( preWarmSize > 0 && desktopState.isDesktopModeSupportedOnDisplay(displayId) ) { preWarmViewHosts(preWarmSize, displayId) } } override fun onDisplayRemoved(displayId: Int) { val displayPool = displayPools.remove(displayId) // Release all the viewHosts in the pool var pooledViewHost = displayPool?.acquire() val transaction = SurfaceControl.Transaction() while (pooledViewHost != null) { pooledViewHost.release(transaction) pooledViewHost = displayPool?.acquire() } transaction.apply() } } ) } private fun preWarmViewHosts(preWarmSize: Int, displayId: Int = DEFAULT_DISPLAY) { mainScope.launch { // Applying isn't needed, as the surface was never actually shown. val t = SurfaceControl.Transaction() val displayContext = if (enablePerDisplayPool) { displayController.getDisplayContext(displayId) ?: return@launch } else { context } repeat(preWarmSize) { val warmedViewHost = newInstance(context, context.display).apply { warmUp() } val warmedViewHost = newInstance(displayContext, displayContext.display).apply { warmUp() } // Put the warmed view host in the pool by releasing it. release(warmedViewHost, t) } Loading @@ -74,7 +120,12 @@ class PooledWindowDecorViewHostSupplier( } override fun acquire(context: Context, display: Display): WindowDecorViewHost { val pooledViewHost = pool.acquire() val pooledViewHost = if (enablePerDisplayPool) { displayPools[display.displayId]?.acquire() } else { pool.acquire() } if (pooledViewHost != null) { return pooledViewHost } Loading @@ -88,8 +139,13 @@ class PooledWindowDecorViewHostSupplier( if (DesktopExperienceFlags.ENABLE_CLEAR_REUSABLE_SCVH_ON_RELEASE.isTrue) { viewHost.reset() } val pooled = pool.release(viewHost) if (!pooled) { val displayPool = if (enablePerDisplayPool) { displayPools[viewHost.displayId] } else { pool } if (displayPool == null || !displayPool.release(viewHost)) { viewHost.release(t) } } Loading