Loading core/java/android/view/IWindowManager.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -955,4 +955,10 @@ interface IWindowManager * @hide */ Bitmap snapshotTaskForRecents(int taskId); /** * Informs the system whether the recents app is currently behind the system bars. If so, * means the recents app can control the SystemUI flags, and vice-versa. */ void setRecentsAppBehindSystemBars(boolean behindSystemBars); } core/java/android/view/WindowManagerGlobal.java +8 −0 Original line number Diff line number Diff line Loading @@ -754,6 +754,14 @@ public final class WindowManagerGlobal { mWindowlessRoots.remove(impl); } } public void setRecentsAppBehindSystemBars(boolean behindSystemBars) { try { getWindowManagerService().setRecentsAppBehindSystemBars(behindSystemBars); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } final class WindowLeaked extends AndroidRuntimeException { Loading services/core/java/com/android/server/wm/Transition.java +34 −1 Original line number Diff line number Diff line Loading @@ -80,9 +80,12 @@ import android.window.TransitionInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.inputmethod.InputMethodManagerInternal; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -552,14 +555,24 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe asyncRotationController.onTransitionFinished(); } if (mTransientLaunches != null) { InsetsControlTarget prevImeTarget = dc.getImeTarget( DisplayContent.IME_TARGET_CONTROL); InsetsControlTarget newImeTarget = null; // Transient-launch activities cannot be IME target (WindowState#canBeImeTarget), // so re-compute in case the IME target is changed after transition. for (int t = 0; t < mTransientLaunches.size(); ++t) { if (mTransientLaunches.keyAt(t).getDisplayContent() == dc) { dc.computeImeTarget(true /* updateImeTarget */); newImeTarget = dc.computeImeTarget(true /* updateImeTarget */); break; } } if (mRecentsDisplayId != INVALID_DISPLAY && prevImeTarget == newImeTarget) { // Restore IME icon only when moving the original app task to front from // recents, in case IME icon may missing if the moving task has already been // the current focused task. InputMethodManagerInternal.get().updateImeWindowStatus( false /* disableImeIcon */); } } dc.handleCompleteDeferredRemoval(); } Loading Loading @@ -781,6 +794,26 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } } // Hiding IME/IME icon when starting quick-step with resents animation. if (!mTargetDisplays.get(mRecentsDisplayId).isImeAttachedToApp()) { // Hiding IME if IME window is not attached to app. // Since some windowing mode is not proper to snapshot Task with IME window // while the app transitioning to the next task (e.g. split-screen mode) final InputMethodManagerInternal inputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class); if (inputMethodManagerInternal != null) { inputMethodManagerInternal.hideCurrentInputMethod( SoftInputShowHideReason.HIDE_RECENTS_ANIMATION); } } else { // Disable IME icon explicitly when IME attached to the app in case // IME icon might flickering while swiping to the next app task still // in animating before the next app window focused, or IME icon // persists on the bottom when swiping the task to recents. InputMethodManagerInternal.get().updateImeWindowStatus( true /* disableImeIcon */); } // The rest of this function handles nav-bar reparenting if (!dc.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() Loading services/core/java/com/android/server/wm/TransitionController.java +6 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; Loading Loading @@ -514,8 +513,13 @@ class TransitionController { // TODO(b/188669821): Remove once legacy recents behavior is moved to shell. // Also interpret HOME transient launch as recents if (activity.getActivityType() == ACTIVITY_TYPE_HOME) { if (activity.isActivityTypeHomeOrRecents()) { mCollectingTransition.addFlag(TRANSIT_FLAG_IS_RECENTS); // When starting recents animation, we assume the recents activity is behind the app // task and should not affect system bar appearance, // until WMS#setRecentsAppBehindSystemBars be called from launcher when passing // the gesture threshold. activity.getTask().setCanAffectSystemUiFlags(false); } } Loading services/core/java/com/android/server/wm/WindowManagerService.java +21 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE; import static android.Manifest.permission.READ_FRAME_BUFFER; import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS; import static android.Manifest.permission.RESTRICTED_VR_ACCESS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; Loading Loading @@ -8983,4 +8984,24 @@ public class WindowManagerService extends IWindowManager.Stub return Bitmap.wrapHardwareBuffer(taskSnapshot.getHardwareBuffer(), taskSnapshot.getColorSpace()); } @Override public void setRecentsAppBehindSystemBars(boolean behindSystemBars) { if (!checkCallingPermission(START_TASKS_FROM_RECENTS, "setRecentsAppBehindSystemBars()")) { throw new SecurityException("Requires START_TASKS_FROM_RECENTS permission"); } final long token = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { final Task recentsApp = mRoot.getTask(task -> task.isActivityTypeHomeOrRecents() && task.getTopVisibleActivity() != null); if (recentsApp != null) { recentsApp.getTask().setCanAffectSystemUiFlags(behindSystemBars); mWindowPlacerLocked.requestTraversal(); } } } finally { Binder.restoreCallingIdentity(token); } } } Loading
core/java/android/view/IWindowManager.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -955,4 +955,10 @@ interface IWindowManager * @hide */ Bitmap snapshotTaskForRecents(int taskId); /** * Informs the system whether the recents app is currently behind the system bars. If so, * means the recents app can control the SystemUI flags, and vice-versa. */ void setRecentsAppBehindSystemBars(boolean behindSystemBars); }
core/java/android/view/WindowManagerGlobal.java +8 −0 Original line number Diff line number Diff line Loading @@ -754,6 +754,14 @@ public final class WindowManagerGlobal { mWindowlessRoots.remove(impl); } } public void setRecentsAppBehindSystemBars(boolean behindSystemBars) { try { getWindowManagerService().setRecentsAppBehindSystemBars(behindSystemBars); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } final class WindowLeaked extends AndroidRuntimeException { Loading
services/core/java/com/android/server/wm/Transition.java +34 −1 Original line number Diff line number Diff line Loading @@ -80,9 +80,12 @@ import android.window.TransitionInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.inputmethod.InputMethodManagerInternal; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -552,14 +555,24 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe asyncRotationController.onTransitionFinished(); } if (mTransientLaunches != null) { InsetsControlTarget prevImeTarget = dc.getImeTarget( DisplayContent.IME_TARGET_CONTROL); InsetsControlTarget newImeTarget = null; // Transient-launch activities cannot be IME target (WindowState#canBeImeTarget), // so re-compute in case the IME target is changed after transition. for (int t = 0; t < mTransientLaunches.size(); ++t) { if (mTransientLaunches.keyAt(t).getDisplayContent() == dc) { dc.computeImeTarget(true /* updateImeTarget */); newImeTarget = dc.computeImeTarget(true /* updateImeTarget */); break; } } if (mRecentsDisplayId != INVALID_DISPLAY && prevImeTarget == newImeTarget) { // Restore IME icon only when moving the original app task to front from // recents, in case IME icon may missing if the moving task has already been // the current focused task. InputMethodManagerInternal.get().updateImeWindowStatus( false /* disableImeIcon */); } } dc.handleCompleteDeferredRemoval(); } Loading Loading @@ -781,6 +794,26 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } } // Hiding IME/IME icon when starting quick-step with resents animation. if (!mTargetDisplays.get(mRecentsDisplayId).isImeAttachedToApp()) { // Hiding IME if IME window is not attached to app. // Since some windowing mode is not proper to snapshot Task with IME window // while the app transitioning to the next task (e.g. split-screen mode) final InputMethodManagerInternal inputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class); if (inputMethodManagerInternal != null) { inputMethodManagerInternal.hideCurrentInputMethod( SoftInputShowHideReason.HIDE_RECENTS_ANIMATION); } } else { // Disable IME icon explicitly when IME attached to the app in case // IME icon might flickering while swiping to the next app task still // in animating before the next app window focused, or IME icon // persists on the bottom when swiping the task to recents. InputMethodManagerInternal.get().updateImeWindowStatus( true /* disableImeIcon */); } // The rest of this function handles nav-bar reparenting if (!dc.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() Loading
services/core/java/com/android/server/wm/TransitionController.java +6 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; Loading Loading @@ -514,8 +513,13 @@ class TransitionController { // TODO(b/188669821): Remove once legacy recents behavior is moved to shell. // Also interpret HOME transient launch as recents if (activity.getActivityType() == ACTIVITY_TYPE_HOME) { if (activity.isActivityTypeHomeOrRecents()) { mCollectingTransition.addFlag(TRANSIT_FLAG_IS_RECENTS); // When starting recents animation, we assume the recents activity is behind the app // task and should not affect system bar appearance, // until WMS#setRecentsAppBehindSystemBars be called from launcher when passing // the gesture threshold. activity.getTask().setCanAffectSystemUiFlags(false); } } Loading
services/core/java/com/android/server/wm/WindowManagerService.java +21 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE; import static android.Manifest.permission.READ_FRAME_BUFFER; import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS; import static android.Manifest.permission.RESTRICTED_VR_ACCESS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; Loading Loading @@ -8983,4 +8984,24 @@ public class WindowManagerService extends IWindowManager.Stub return Bitmap.wrapHardwareBuffer(taskSnapshot.getHardwareBuffer(), taskSnapshot.getColorSpace()); } @Override public void setRecentsAppBehindSystemBars(boolean behindSystemBars) { if (!checkCallingPermission(START_TASKS_FROM_RECENTS, "setRecentsAppBehindSystemBars()")) { throw new SecurityException("Requires START_TASKS_FROM_RECENTS permission"); } final long token = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { final Task recentsApp = mRoot.getTask(task -> task.isActivityTypeHomeOrRecents() && task.getTopVisibleActivity() != null); if (recentsApp != null) { recentsApp.getTask().setCanAffectSystemUiFlags(behindSystemBars); mWindowPlacerLocked.requestTraversal(); } } } finally { Binder.restoreCallingIdentity(token); } } }