Loading core/java/android/app/IActivityTaskManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.os.StrictMode; import android.os.WorkSource; import android.service.voice.IVoiceInteractionSession; import android.view.IRecentsAnimationRunner; import android.view.ITaskOrganizer; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationAdapter; import android.view.WindowContainerTransaction; Loading Loading @@ -121,6 +122,9 @@ interface IActivityTaskManager { in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options, IBinder permissionToken, boolean ignoreTargetSecurity, int userId); void registerTaskOrganizer(in ITaskOrganizer organizer, int windowingMode); boolean isActivityStartAllowedOnDisplay(int displayId, in Intent intent, in String resolvedType, int userId); Loading core/java/android/view/ITaskOrganizer.aidl 0 → 100644 +38 −0 Original line number Diff line number Diff line /* //device/java/android/android/view/ITaskOrganizer.aidl ** ** Copyright 2019, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ package android.view; import android.view.IWindowContainer; import android.view.SurfaceControl; import android.app.ActivityManager; /** * Interface for ActivityTaskManager/WindowManager to delegate control of tasks. * {@hide} */ oneway interface ITaskOrganizer { void taskAppeared(in IWindowContainer container, in ActivityManager.RunningTaskInfo taskInfo); void taskVanished(in IWindowContainer container); /** * Called upon completion of * ActivityTaskManagerService#applyTaskOrganizerTransaction */ void transactionReady(int id, in SurfaceControl.Transaction t); } No newline at end of file core/java/android/view/WindowContainerTransaction.java +33 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,18 @@ public class WindowContainerTransaction implements Parcelable { return this; } /** * Notify activies within the hiearchy of a container that they have entered picture-in-picture * mode with the given bounds. */ public WindowContainerTransaction scheduleFinishEnterPip(IWindowContainer container, Rect bounds) { Change chg = getOrCreateChange(container.asBinder()); chg.mSchedulePipCallback = true; chg.mPinnedBounds = new Rect(bounds); return this; } public Map<IBinder, Change> getChanges() { return mChanges; } Loading Loading @@ -104,12 +116,20 @@ public class WindowContainerTransaction implements Parcelable { private @ActivityInfo.Config int mConfigSetMask = 0; private @WindowConfiguration.WindowConfig int mWindowSetMask = 0; private boolean mSchedulePipCallback = false; private Rect mPinnedBounds = null; public Change() {} protected Change(Parcel in) { mConfiguration.readFromParcel(in); mConfigSetMask = in.readInt(); mWindowSetMask = in.readInt(); mSchedulePipCallback = (in.readInt() != 0); if (mSchedulePipCallback ) { mPinnedBounds = new Rect(); mPinnedBounds.readFromParcel(in); } } public Configuration getConfiguration() { Loading @@ -126,6 +146,14 @@ public class WindowContainerTransaction implements Parcelable { return mWindowSetMask; } /** * Returns the bounds to be used for scheduling the enter pip callback * or null if no callback is to be scheduled. */ public Rect getEnterPipBounds() { return mPinnedBounds; } @Override public String toString() { final boolean changesBounds = Loading @@ -151,6 +179,11 @@ public class WindowContainerTransaction implements Parcelable { mConfiguration.writeToParcel(dest, flags); dest.writeInt(mConfigSetMask); dest.writeInt(mWindowSetMask); dest.writeInt(mSchedulePipCallback ? 1 : 0); if (mSchedulePipCallback ) { mPinnedBounds.writeToParcel(dest, flags); } } @Override Loading services/core/java/com/android/server/wm/ActivityStack.java +47 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,7 @@ import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.ITaskOrganizer; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -803,6 +804,16 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, false /* creating */); windowingMode = getWindowingMode(); /* * Different windowing modes may be managed by different task organizers. If * getTaskOrganizer returns null, we still call transferToTaskOrganizer to * make sure we clear it. */ final ITaskOrganizer org = mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode); transferToTaskOrganizer(org); } /** Loading Loading @@ -1649,6 +1660,33 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn return topActivity != null && topActivity.mVisibleRequested; } /** * Indicate whether the first task in this stack is controlled by a TaskOrganizer. We aren't * expecting to use the TaskOrganizer in multiple task per stack scenarios so checking * the first one is ok. */ boolean isControlledByTaskOrganizer() { return getChildCount() > 0 && getTopMostTask().mTaskOrganizer != null; } private static void transferSingleTaskToOrganizer(Task tr, ITaskOrganizer organizer) { tr.setTaskOrganizer(organizer); } /** * Transfer control of the leashes and IWindowContainers to the given ITaskOrganizer. * This will (or shortly there-after) invoke the taskAppeared callbacks. * If the tasks had a previous TaskOrganizer, setTaskOrganizer will take care of * emitting the taskVanished callbacks. */ void transferToTaskOrganizer(ITaskOrganizer organizer) { final PooledConsumer c = PooledLambda.obtainConsumer( ActivityStack::transferSingleTaskToOrganizer, PooledLambda.__(Task.class), organizer); forAllTasks(c); c.recycle(); } /** * Returns true if the stack should be visible. * Loading Loading @@ -3577,6 +3615,15 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds, int animationDuration, boolean fromFullscreen) { if (!inPinnedWindowingMode()) return; /** * TODO(b/146594635): Remove all PIP animation code from WM once SysUI handles animation. * If this PIP Task is controlled by a TaskOrganizer, the animation occurs entirely * on the TaskOrganizer side, so we just hand over the leash without doing any animation. * We have to be careful to not schedule the enter-pip callback as the TaskOrganizer * needs to have flexibility to schedule that at an appropriate point in the animation. */ if (isControlledByTaskOrganizer()) return; if (toBounds == null /* toFullscreen */) { final Configuration parentConfig = getParent().getConfiguration(); final ActivityRecord top = topRunningNonOverlayTaskActivity(); Loading services/core/java/com/android/server/wm/ActivityStackSupervisor.java +1 −0 Original line number Diff line number Diff line Loading @@ -2548,6 +2548,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { final PooledConsumer c = PooledLambda.obtainConsumer( ActivityRecord::updatePictureInPictureMode, PooledLambda.__(ActivityRecord.class), targetStackBounds, forceUpdate); task.getStack().setBounds(targetStackBounds); task.forAllActivities(c); c.recycle(); } Loading Loading
core/java/android/app/IActivityTaskManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.os.StrictMode; import android.os.WorkSource; import android.service.voice.IVoiceInteractionSession; import android.view.IRecentsAnimationRunner; import android.view.ITaskOrganizer; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationAdapter; import android.view.WindowContainerTransaction; Loading Loading @@ -121,6 +122,9 @@ interface IActivityTaskManager { in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options, IBinder permissionToken, boolean ignoreTargetSecurity, int userId); void registerTaskOrganizer(in ITaskOrganizer organizer, int windowingMode); boolean isActivityStartAllowedOnDisplay(int displayId, in Intent intent, in String resolvedType, int userId); Loading
core/java/android/view/ITaskOrganizer.aidl 0 → 100644 +38 −0 Original line number Diff line number Diff line /* //device/java/android/android/view/ITaskOrganizer.aidl ** ** Copyright 2019, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ package android.view; import android.view.IWindowContainer; import android.view.SurfaceControl; import android.app.ActivityManager; /** * Interface for ActivityTaskManager/WindowManager to delegate control of tasks. * {@hide} */ oneway interface ITaskOrganizer { void taskAppeared(in IWindowContainer container, in ActivityManager.RunningTaskInfo taskInfo); void taskVanished(in IWindowContainer container); /** * Called upon completion of * ActivityTaskManagerService#applyTaskOrganizerTransaction */ void transactionReady(int id, in SurfaceControl.Transaction t); } No newline at end of file
core/java/android/view/WindowContainerTransaction.java +33 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,18 @@ public class WindowContainerTransaction implements Parcelable { return this; } /** * Notify activies within the hiearchy of a container that they have entered picture-in-picture * mode with the given bounds. */ public WindowContainerTransaction scheduleFinishEnterPip(IWindowContainer container, Rect bounds) { Change chg = getOrCreateChange(container.asBinder()); chg.mSchedulePipCallback = true; chg.mPinnedBounds = new Rect(bounds); return this; } public Map<IBinder, Change> getChanges() { return mChanges; } Loading Loading @@ -104,12 +116,20 @@ public class WindowContainerTransaction implements Parcelable { private @ActivityInfo.Config int mConfigSetMask = 0; private @WindowConfiguration.WindowConfig int mWindowSetMask = 0; private boolean mSchedulePipCallback = false; private Rect mPinnedBounds = null; public Change() {} protected Change(Parcel in) { mConfiguration.readFromParcel(in); mConfigSetMask = in.readInt(); mWindowSetMask = in.readInt(); mSchedulePipCallback = (in.readInt() != 0); if (mSchedulePipCallback ) { mPinnedBounds = new Rect(); mPinnedBounds.readFromParcel(in); } } public Configuration getConfiguration() { Loading @@ -126,6 +146,14 @@ public class WindowContainerTransaction implements Parcelable { return mWindowSetMask; } /** * Returns the bounds to be used for scheduling the enter pip callback * or null if no callback is to be scheduled. */ public Rect getEnterPipBounds() { return mPinnedBounds; } @Override public String toString() { final boolean changesBounds = Loading @@ -151,6 +179,11 @@ public class WindowContainerTransaction implements Parcelable { mConfiguration.writeToParcel(dest, flags); dest.writeInt(mConfigSetMask); dest.writeInt(mWindowSetMask); dest.writeInt(mSchedulePipCallback ? 1 : 0); if (mSchedulePipCallback ) { mPinnedBounds.writeToParcel(dest, flags); } } @Override Loading
services/core/java/com/android/server/wm/ActivityStack.java +47 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,7 @@ import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.ITaskOrganizer; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -803,6 +804,16 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, false /* creating */); windowingMode = getWindowingMode(); /* * Different windowing modes may be managed by different task organizers. If * getTaskOrganizer returns null, we still call transferToTaskOrganizer to * make sure we clear it. */ final ITaskOrganizer org = mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode); transferToTaskOrganizer(org); } /** Loading Loading @@ -1649,6 +1660,33 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn return topActivity != null && topActivity.mVisibleRequested; } /** * Indicate whether the first task in this stack is controlled by a TaskOrganizer. We aren't * expecting to use the TaskOrganizer in multiple task per stack scenarios so checking * the first one is ok. */ boolean isControlledByTaskOrganizer() { return getChildCount() > 0 && getTopMostTask().mTaskOrganizer != null; } private static void transferSingleTaskToOrganizer(Task tr, ITaskOrganizer organizer) { tr.setTaskOrganizer(organizer); } /** * Transfer control of the leashes and IWindowContainers to the given ITaskOrganizer. * This will (or shortly there-after) invoke the taskAppeared callbacks. * If the tasks had a previous TaskOrganizer, setTaskOrganizer will take care of * emitting the taskVanished callbacks. */ void transferToTaskOrganizer(ITaskOrganizer organizer) { final PooledConsumer c = PooledLambda.obtainConsumer( ActivityStack::transferSingleTaskToOrganizer, PooledLambda.__(Task.class), organizer); forAllTasks(c); c.recycle(); } /** * Returns true if the stack should be visible. * Loading Loading @@ -3577,6 +3615,15 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds, int animationDuration, boolean fromFullscreen) { if (!inPinnedWindowingMode()) return; /** * TODO(b/146594635): Remove all PIP animation code from WM once SysUI handles animation. * If this PIP Task is controlled by a TaskOrganizer, the animation occurs entirely * on the TaskOrganizer side, so we just hand over the leash without doing any animation. * We have to be careful to not schedule the enter-pip callback as the TaskOrganizer * needs to have flexibility to schedule that at an appropriate point in the animation. */ if (isControlledByTaskOrganizer()) return; if (toBounds == null /* toFullscreen */) { final Configuration parentConfig = getParent().getConfiguration(); final ActivityRecord top = topRunningNonOverlayTaskActivity(); Loading
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +1 −0 Original line number Diff line number Diff line Loading @@ -2548,6 +2548,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { final PooledConsumer c = PooledLambda.obtainConsumer( ActivityRecord::updatePictureInPictureMode, PooledLambda.__(ActivityRecord.class), targetStackBounds, forceUpdate); task.getStack().setBounds(targetStackBounds); task.forAllActivities(c); c.recycle(); } Loading