Loading services/core/java/com/android/server/am/LaunchingActivityPositioner.java→services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java +11 −9 Original line number Diff line number Diff line Loading @@ -19,23 +19,25 @@ package com.android.server.am; import android.app.ActivityOptions; import android.content.pm.ActivityInfo; import android.graphics.Rect; import com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner; import com.android.server.am.LaunchParamsController.LaunchParams; import com.android.server.am.LaunchParamsController.LaunchParamsModifier; /** * An implementation of {@link LaunchingBoundsPositioner}, which applies the launch bounds specified * An implementation of {@link LaunchParamsModifier}, which applies the launch bounds specified * inside {@link ActivityOptions#getLaunchBounds()}. */ public class LaunchingActivityPositioner implements LaunchingBoundsPositioner { public class ActivityLaunchParamsModifier implements LaunchParamsModifier { private final ActivityStackSupervisor mSupervisor; LaunchingActivityPositioner(ActivityStackSupervisor activityStackSupervisor) { ActivityLaunchParamsModifier(ActivityStackSupervisor activityStackSupervisor) { mSupervisor = activityStackSupervisor; } @Override public int onCalculateBounds(TaskRecord task, ActivityInfo.WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, Rect current, Rect result) { public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, LaunchParams currentParams, LaunchParams outParams) { // We only care about figuring out bounds for activities. if (activity == null) { return RESULT_SKIP; Loading @@ -54,7 +56,7 @@ public class LaunchingActivityPositioner implements LaunchingBoundsPositioner { return RESULT_SKIP; } result.set(bounds); outParams.mBounds.set(bounds); // When this is the most explicit position specification so we should not allow further // modification of the position. Loading services/core/java/com/android/server/am/ActivityStack.java +1 −1 Original line number Diff line number Diff line Loading @@ -5052,7 +5052,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai addTask(task, toTop, "createTaskRecord"); final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController() .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY); if (!mStackSupervisor.getLaunchingBoundsController() if (!mStackSupervisor.getLaunchParamsController() .layoutTask(task, info.windowLayout, activity, source, options) && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) { task.updateOverrideConfiguration(getOverrideBounds()); Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +5 −5 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D WindowManagerService mWindowManager; DisplayManager mDisplayManager; private LaunchingBoundsController mLaunchingBoundsController; private LaunchParamsController mLaunchParamsController; /** * Maps the task identifier that activities are currently being started in to the userId of the Loading Loading @@ -593,8 +593,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mHandler.getLooper()); mKeyguardController = new KeyguardController(mService, this); mLaunchingBoundsController = new LaunchingBoundsController(); mLaunchingBoundsController.registerDefaultPositioners(this); mLaunchParamsController = new LaunchParamsController(mService); mLaunchParamsController.registerDefaultModifiers(this); } Loading Loading @@ -2220,8 +2220,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D || mService.mSupportsFreeformWindowManagement; } LaunchingBoundsController getLaunchingBoundsController() { return mLaunchingBoundsController; LaunchParamsController getLaunchParamsController() { return mLaunchParamsController; } protected <T extends ActivityStack> T getStack(int stackId) { Loading services/core/java/com/android/server/am/ActivityStarter.java +22 −10 Original line number Diff line number Diff line Loading @@ -96,7 +96,6 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; Loading @@ -109,6 +108,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch; import com.android.server.am.LaunchParamsController.LaunchParams; import com.android.server.pm.InstantAppResolver; import java.io.PrintWriter; Loading Loading @@ -144,7 +144,7 @@ class ActivityStarter { private boolean mLaunchTaskBehind; private int mLaunchFlags; private Rect mLaunchBounds = new Rect(); private LaunchParams mLaunchParams = new LaunchParams(); private ActivityRecord mNotTop; private boolean mDoResume; Loading Loading @@ -419,7 +419,7 @@ class ActivityStarter { mLaunchFlags = starter.mLaunchFlags; mLaunchMode = starter.mLaunchMode; mLaunchBounds.set(starter.mLaunchBounds); mLaunchParams.set(starter.mLaunchParams); mNotTop = starter.mNotTop; mDoResume = starter.mDoResume; Loading Loading @@ -1154,6 +1154,18 @@ class ActivityStarter { preferredLaunchDisplayId = mOptions.getLaunchDisplayId(); } // windowing mode and preferred launch display values from {@link LaunchParams} take // priority over those specified in {@link ActivityOptions}. if (!mLaunchParams.isEmpty()) { if (mLaunchParams.hasPreferredDisplay()) { preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId; } if (mLaunchParams.hasWindowingMode()) { preferredWindowingMode = mLaunchParams.mWindowingMode; } } if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and Loading Loading @@ -1378,7 +1390,7 @@ class ActivityStarter { mLaunchFlags = 0; mLaunchMode = INVALID_LAUNCH_MODE; mLaunchBounds.setEmpty(); mLaunchParams.reset(); mNotTop = null; mDoResume = false; Loading Loading @@ -1425,10 +1437,10 @@ class ActivityStarter { mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options); mLaunchBounds.setEmpty(); mLaunchParams.reset(); mSupervisor.getLaunchingBoundsController().calculateBounds(inTask, null /*layout*/, r, sourceRecord, options, mLaunchBounds); mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord, options, mLaunchParams); mLaunchMode = r.launchMode; Loading Loading @@ -1938,7 +1950,7 @@ class ActivityStarter { mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord, mOptions); addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); updateBounds(mStartActivity.getTask(), mLaunchBounds); updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds); if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity + " in new task " + mStartActivity.getTask()); Loading Loading @@ -2102,7 +2114,7 @@ class ActivityStarter { return START_TASK_TO_FRONT; } if (!mLaunchBounds.isEmpty()) { if (!mLaunchParams.mBounds.isEmpty()) { // TODO: Shouldn't we already know what stack to use by the time we get here? ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP); if (stack != mInTask.getStack()) { Loading @@ -2111,7 +2123,7 @@ class ActivityStarter { mTargetStack = mInTask.getStack(); } updateBounds(mInTask, mLaunchBounds); updateBounds(mInTask, mLaunchParams.mBounds); } mTargetStack.moveTaskToFrontLocked( Loading services/core/java/com/android/server/am/LaunchParamsController.java 0 → 100644 +256 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 com.android.server.am; import android.annotation.IntDef; import android.app.ActivityOptions; import android.content.pm.ActivityInfo.WindowLayout; import android.graphics.Rect; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE; import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP; /** * {@link LaunchParamsController} calculates the {@link LaunchParams} by coordinating between * registered {@link LaunchParamsModifier}s. */ class LaunchParamsController { private final ActivityManagerService mService; private final List<LaunchParamsModifier> mModifiers = new ArrayList<>(); // Temporary {@link LaunchParams} for internal calculations. This is kept separate from // {@code mTmpCurrent} and {@code mTmpResult} to prevent clobbering values. private final LaunchParams mTmpParams = new LaunchParams(); private final LaunchParams mTmpCurrent = new LaunchParams(); private final LaunchParams mTmpResult = new LaunchParams(); LaunchParamsController(ActivityManagerService service) { mService = service; } /** * Creates a {@link LaunchParamsController} with default registered * {@link LaunchParamsModifier}s. */ void registerDefaultModifiers(ActivityStackSupervisor supervisor) { // {@link TaskLaunchParamsModifier} handles window layout preferences. registerModifier(new TaskLaunchParamsModifier()); // {@link ActivityLaunchParamsModifier} is the most specific modifier and thus should be // registered last (applied first) out of the defaults. registerModifier(new ActivityLaunchParamsModifier(supervisor)); } /** * Returns the {@link LaunchParams} calculated by the registered modifiers * @param task The {@link TaskRecord} currently being positioned. * @param layout The specified {@link WindowLayout}. * @param activity The {@link ActivityRecord} currently being positioned. * @param source The {@link ActivityRecord} from which activity was started from. * @param options The {@link ActivityOptions} specified for the activity. * @param result The resulting params. */ void calculate(TaskRecord task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, LaunchParams result) { result.reset(); // We start at the last registered {@link LaunchParamsModifier} as this represents // The modifier closest to the product level. Moving back through the list moves closer to // the platform logic. for (int i = mModifiers.size() - 1; i >= 0; --i) { mTmpCurrent.set(result); mTmpResult.reset(); final LaunchParamsModifier modifier = mModifiers.get(i); switch(modifier.onCalculate(task, layout, activity, source, options, mTmpCurrent, mTmpResult)) { case RESULT_SKIP: // Do not apply any results when we are told to skip continue; case RESULT_DONE: // Set result and return immediately. result.set(mTmpResult); return; case RESULT_CONTINUE: // Set result and continue result.set(mTmpResult); break; } } } /** * A convenience method for laying out a task. * @return {@code true} if bounds were set on the task. {@code false} otherwise. */ boolean layoutTask(TaskRecord task, WindowLayout layout) { return layoutTask(task, layout, null /*activity*/, null /*source*/, null /*options*/); } boolean layoutTask(TaskRecord task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options) { calculate(task, layout, activity, source, options, mTmpParams); // No changes, return. if (mTmpParams.isEmpty()) { return false; } mService.mWindowManager.deferSurfaceLayout(); try { if (mTmpParams.hasPreferredDisplay() && mTmpParams.mPreferredDisplayId != task.getStack().getDisplay().mDisplayId) { mService.moveStackToDisplay(task.getStackId(), mTmpParams.mPreferredDisplayId); } if (mTmpParams.hasWindowingMode() && mTmpParams.mWindowingMode != task.getStack().getWindowingMode()) { task.getStack().setWindowingMode(mTmpParams.mWindowingMode); } if (!mTmpParams.mBounds.isEmpty()) { task.updateOverrideConfiguration(mTmpParams.mBounds); return true; } else { return false; } } finally { mService.mWindowManager.continueSurfaceLayout(); } } /** * Adds a modifier to participate in future bounds calculation. Note that the last registered * {@link LaunchParamsModifier} will be the first to calculate the bounds. */ void registerModifier(LaunchParamsModifier modifier) { if (mModifiers.contains(modifier)) { return; } mModifiers.add(modifier); } /** * A container for holding launch related fields. */ static class LaunchParams { /** The bounds within the parent container. */ final Rect mBounds = new Rect(); /** The id of the display the {@link TaskRecord} would prefer to be on. */ int mPreferredDisplayId; /** The windowing mode to be in. */ int mWindowingMode; /** Sets values back to default. {@link #isEmpty} will return {@code true} once called. */ void reset() { mBounds.setEmpty(); mPreferredDisplayId = INVALID_DISPLAY; mWindowingMode = WINDOWING_MODE_UNDEFINED; } /** Copies the values set on the passed in {@link LaunchParams}. */ void set(LaunchParams params) { mBounds.set(params.mBounds); mPreferredDisplayId = params.mPreferredDisplayId; mWindowingMode = params.mWindowingMode; } /** Returns {@code true} if no values have been explicitly set. */ boolean isEmpty() { return mBounds.isEmpty() && mPreferredDisplayId == INVALID_DISPLAY && mWindowingMode == WINDOWING_MODE_UNDEFINED; } boolean hasWindowingMode() { return mWindowingMode != WINDOWING_MODE_UNDEFINED; } boolean hasPreferredDisplay() { return mPreferredDisplayId != INVALID_DISPLAY; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LaunchParams that = (LaunchParams) o; if (mPreferredDisplayId != that.mPreferredDisplayId) return false; if (mWindowingMode != that.mWindowingMode) return false; return mBounds != null ? mBounds.equals(that.mBounds) : that.mBounds == null; } @Override public int hashCode() { int result = mBounds != null ? mBounds.hashCode() : 0; result = 31 * result + mPreferredDisplayId; result = 31 * result + mWindowingMode; return result; } } /** * An interface implemented by those wanting to participate in bounds calculation. */ interface LaunchParamsModifier { @Retention(RetentionPolicy.SOURCE) @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE}) @interface Result {} // Returned when the modifier does not want to influence the bounds calculation int RESULT_SKIP = 0; // Returned when the modifier has changed the bounds and would like its results to be the // final bounds applied. int RESULT_DONE = 1; // Returned when the modifier has changed the bounds but is okay with other modifiers // influencing the bounds. int RESULT_CONTINUE = 2; /** * Called when asked to calculate {@link LaunchParams}. * @param task The {@link TaskRecord} currently being positioned. * @param layout The specified {@link WindowLayout}. * @param activity The {@link ActivityRecord} currently being positioned. * @param source The {@link ActivityRecord} activity was started from. * @param options The {@link ActivityOptions} specified for the activity. * @param currentParams The current {@link LaunchParams}. This can differ from the initial * params as it represents the modified params up to this point. * @param outParams The resulting {@link LaunchParams} after all calculations. * @return A {@link Result} representing the result of the * {@link LaunchParams} calculation. */ @Result int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, LaunchParams currentParams, LaunchParams outParams); } } Loading
services/core/java/com/android/server/am/LaunchingActivityPositioner.java→services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java +11 −9 Original line number Diff line number Diff line Loading @@ -19,23 +19,25 @@ package com.android.server.am; import android.app.ActivityOptions; import android.content.pm.ActivityInfo; import android.graphics.Rect; import com.android.server.am.LaunchingBoundsController.LaunchingBoundsPositioner; import com.android.server.am.LaunchParamsController.LaunchParams; import com.android.server.am.LaunchParamsController.LaunchParamsModifier; /** * An implementation of {@link LaunchingBoundsPositioner}, which applies the launch bounds specified * An implementation of {@link LaunchParamsModifier}, which applies the launch bounds specified * inside {@link ActivityOptions#getLaunchBounds()}. */ public class LaunchingActivityPositioner implements LaunchingBoundsPositioner { public class ActivityLaunchParamsModifier implements LaunchParamsModifier { private final ActivityStackSupervisor mSupervisor; LaunchingActivityPositioner(ActivityStackSupervisor activityStackSupervisor) { ActivityLaunchParamsModifier(ActivityStackSupervisor activityStackSupervisor) { mSupervisor = activityStackSupervisor; } @Override public int onCalculateBounds(TaskRecord task, ActivityInfo.WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, Rect current, Rect result) { public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, LaunchParams currentParams, LaunchParams outParams) { // We only care about figuring out bounds for activities. if (activity == null) { return RESULT_SKIP; Loading @@ -54,7 +56,7 @@ public class LaunchingActivityPositioner implements LaunchingBoundsPositioner { return RESULT_SKIP; } result.set(bounds); outParams.mBounds.set(bounds); // When this is the most explicit position specification so we should not allow further // modification of the position. Loading
services/core/java/com/android/server/am/ActivityStack.java +1 −1 Original line number Diff line number Diff line Loading @@ -5052,7 +5052,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai addTask(task, toTop, "createTaskRecord"); final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController() .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY); if (!mStackSupervisor.getLaunchingBoundsController() if (!mStackSupervisor.getLaunchParamsController() .layoutTask(task, info.windowLayout, activity, source, options) && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) { task.updateOverrideConfiguration(getOverrideBounds()); Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +5 −5 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D WindowManagerService mWindowManager; DisplayManager mDisplayManager; private LaunchingBoundsController mLaunchingBoundsController; private LaunchParamsController mLaunchParamsController; /** * Maps the task identifier that activities are currently being started in to the userId of the Loading Loading @@ -593,8 +593,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mHandler.getLooper()); mKeyguardController = new KeyguardController(mService, this); mLaunchingBoundsController = new LaunchingBoundsController(); mLaunchingBoundsController.registerDefaultPositioners(this); mLaunchParamsController = new LaunchParamsController(mService); mLaunchParamsController.registerDefaultModifiers(this); } Loading Loading @@ -2220,8 +2220,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D || mService.mSupportsFreeformWindowManagement; } LaunchingBoundsController getLaunchingBoundsController() { return mLaunchingBoundsController; LaunchParamsController getLaunchParamsController() { return mLaunchParamsController; } protected <T extends ActivityStack> T getStack(int stackId) { Loading
services/core/java/com/android/server/am/ActivityStarter.java +22 −10 Original line number Diff line number Diff line Loading @@ -96,7 +96,6 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; Loading @@ -109,6 +108,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch; import com.android.server.am.LaunchParamsController.LaunchParams; import com.android.server.pm.InstantAppResolver; import java.io.PrintWriter; Loading Loading @@ -144,7 +144,7 @@ class ActivityStarter { private boolean mLaunchTaskBehind; private int mLaunchFlags; private Rect mLaunchBounds = new Rect(); private LaunchParams mLaunchParams = new LaunchParams(); private ActivityRecord mNotTop; private boolean mDoResume; Loading Loading @@ -419,7 +419,7 @@ class ActivityStarter { mLaunchFlags = starter.mLaunchFlags; mLaunchMode = starter.mLaunchMode; mLaunchBounds.set(starter.mLaunchBounds); mLaunchParams.set(starter.mLaunchParams); mNotTop = starter.mNotTop; mDoResume = starter.mDoResume; Loading Loading @@ -1154,6 +1154,18 @@ class ActivityStarter { preferredLaunchDisplayId = mOptions.getLaunchDisplayId(); } // windowing mode and preferred launch display values from {@link LaunchParams} take // priority over those specified in {@link ActivityOptions}. if (!mLaunchParams.isEmpty()) { if (mLaunchParams.hasPreferredDisplay()) { preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId; } if (mLaunchParams.hasWindowingMode()) { preferredWindowingMode = mLaunchParams.mWindowingMode; } } if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and Loading Loading @@ -1378,7 +1390,7 @@ class ActivityStarter { mLaunchFlags = 0; mLaunchMode = INVALID_LAUNCH_MODE; mLaunchBounds.setEmpty(); mLaunchParams.reset(); mNotTop = null; mDoResume = false; Loading Loading @@ -1425,10 +1437,10 @@ class ActivityStarter { mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options); mLaunchBounds.setEmpty(); mLaunchParams.reset(); mSupervisor.getLaunchingBoundsController().calculateBounds(inTask, null /*layout*/, r, sourceRecord, options, mLaunchBounds); mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord, options, mLaunchParams); mLaunchMode = r.launchMode; Loading Loading @@ -1938,7 +1950,7 @@ class ActivityStarter { mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord, mOptions); addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); updateBounds(mStartActivity.getTask(), mLaunchBounds); updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds); if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity + " in new task " + mStartActivity.getTask()); Loading Loading @@ -2102,7 +2114,7 @@ class ActivityStarter { return START_TASK_TO_FRONT; } if (!mLaunchBounds.isEmpty()) { if (!mLaunchParams.mBounds.isEmpty()) { // TODO: Shouldn't we already know what stack to use by the time we get here? ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP); if (stack != mInTask.getStack()) { Loading @@ -2111,7 +2123,7 @@ class ActivityStarter { mTargetStack = mInTask.getStack(); } updateBounds(mInTask, mLaunchBounds); updateBounds(mInTask, mLaunchParams.mBounds); } mTargetStack.moveTaskToFrontLocked( Loading
services/core/java/com/android/server/am/LaunchParamsController.java 0 → 100644 +256 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 com.android.server.am; import android.annotation.IntDef; import android.app.ActivityOptions; import android.content.pm.ActivityInfo.WindowLayout; import android.graphics.Rect; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE; import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP; /** * {@link LaunchParamsController} calculates the {@link LaunchParams} by coordinating between * registered {@link LaunchParamsModifier}s. */ class LaunchParamsController { private final ActivityManagerService mService; private final List<LaunchParamsModifier> mModifiers = new ArrayList<>(); // Temporary {@link LaunchParams} for internal calculations. This is kept separate from // {@code mTmpCurrent} and {@code mTmpResult} to prevent clobbering values. private final LaunchParams mTmpParams = new LaunchParams(); private final LaunchParams mTmpCurrent = new LaunchParams(); private final LaunchParams mTmpResult = new LaunchParams(); LaunchParamsController(ActivityManagerService service) { mService = service; } /** * Creates a {@link LaunchParamsController} with default registered * {@link LaunchParamsModifier}s. */ void registerDefaultModifiers(ActivityStackSupervisor supervisor) { // {@link TaskLaunchParamsModifier} handles window layout preferences. registerModifier(new TaskLaunchParamsModifier()); // {@link ActivityLaunchParamsModifier} is the most specific modifier and thus should be // registered last (applied first) out of the defaults. registerModifier(new ActivityLaunchParamsModifier(supervisor)); } /** * Returns the {@link LaunchParams} calculated by the registered modifiers * @param task The {@link TaskRecord} currently being positioned. * @param layout The specified {@link WindowLayout}. * @param activity The {@link ActivityRecord} currently being positioned. * @param source The {@link ActivityRecord} from which activity was started from. * @param options The {@link ActivityOptions} specified for the activity. * @param result The resulting params. */ void calculate(TaskRecord task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, LaunchParams result) { result.reset(); // We start at the last registered {@link LaunchParamsModifier} as this represents // The modifier closest to the product level. Moving back through the list moves closer to // the platform logic. for (int i = mModifiers.size() - 1; i >= 0; --i) { mTmpCurrent.set(result); mTmpResult.reset(); final LaunchParamsModifier modifier = mModifiers.get(i); switch(modifier.onCalculate(task, layout, activity, source, options, mTmpCurrent, mTmpResult)) { case RESULT_SKIP: // Do not apply any results when we are told to skip continue; case RESULT_DONE: // Set result and return immediately. result.set(mTmpResult); return; case RESULT_CONTINUE: // Set result and continue result.set(mTmpResult); break; } } } /** * A convenience method for laying out a task. * @return {@code true} if bounds were set on the task. {@code false} otherwise. */ boolean layoutTask(TaskRecord task, WindowLayout layout) { return layoutTask(task, layout, null /*activity*/, null /*source*/, null /*options*/); } boolean layoutTask(TaskRecord task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options) { calculate(task, layout, activity, source, options, mTmpParams); // No changes, return. if (mTmpParams.isEmpty()) { return false; } mService.mWindowManager.deferSurfaceLayout(); try { if (mTmpParams.hasPreferredDisplay() && mTmpParams.mPreferredDisplayId != task.getStack().getDisplay().mDisplayId) { mService.moveStackToDisplay(task.getStackId(), mTmpParams.mPreferredDisplayId); } if (mTmpParams.hasWindowingMode() && mTmpParams.mWindowingMode != task.getStack().getWindowingMode()) { task.getStack().setWindowingMode(mTmpParams.mWindowingMode); } if (!mTmpParams.mBounds.isEmpty()) { task.updateOverrideConfiguration(mTmpParams.mBounds); return true; } else { return false; } } finally { mService.mWindowManager.continueSurfaceLayout(); } } /** * Adds a modifier to participate in future bounds calculation. Note that the last registered * {@link LaunchParamsModifier} will be the first to calculate the bounds. */ void registerModifier(LaunchParamsModifier modifier) { if (mModifiers.contains(modifier)) { return; } mModifiers.add(modifier); } /** * A container for holding launch related fields. */ static class LaunchParams { /** The bounds within the parent container. */ final Rect mBounds = new Rect(); /** The id of the display the {@link TaskRecord} would prefer to be on. */ int mPreferredDisplayId; /** The windowing mode to be in. */ int mWindowingMode; /** Sets values back to default. {@link #isEmpty} will return {@code true} once called. */ void reset() { mBounds.setEmpty(); mPreferredDisplayId = INVALID_DISPLAY; mWindowingMode = WINDOWING_MODE_UNDEFINED; } /** Copies the values set on the passed in {@link LaunchParams}. */ void set(LaunchParams params) { mBounds.set(params.mBounds); mPreferredDisplayId = params.mPreferredDisplayId; mWindowingMode = params.mWindowingMode; } /** Returns {@code true} if no values have been explicitly set. */ boolean isEmpty() { return mBounds.isEmpty() && mPreferredDisplayId == INVALID_DISPLAY && mWindowingMode == WINDOWING_MODE_UNDEFINED; } boolean hasWindowingMode() { return mWindowingMode != WINDOWING_MODE_UNDEFINED; } boolean hasPreferredDisplay() { return mPreferredDisplayId != INVALID_DISPLAY; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LaunchParams that = (LaunchParams) o; if (mPreferredDisplayId != that.mPreferredDisplayId) return false; if (mWindowingMode != that.mWindowingMode) return false; return mBounds != null ? mBounds.equals(that.mBounds) : that.mBounds == null; } @Override public int hashCode() { int result = mBounds != null ? mBounds.hashCode() : 0; result = 31 * result + mPreferredDisplayId; result = 31 * result + mWindowingMode; return result; } } /** * An interface implemented by those wanting to participate in bounds calculation. */ interface LaunchParamsModifier { @Retention(RetentionPolicy.SOURCE) @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE}) @interface Result {} // Returned when the modifier does not want to influence the bounds calculation int RESULT_SKIP = 0; // Returned when the modifier has changed the bounds and would like its results to be the // final bounds applied. int RESULT_DONE = 1; // Returned when the modifier has changed the bounds but is okay with other modifiers // influencing the bounds. int RESULT_CONTINUE = 2; /** * Called when asked to calculate {@link LaunchParams}. * @param task The {@link TaskRecord} currently being positioned. * @param layout The specified {@link WindowLayout}. * @param activity The {@link ActivityRecord} currently being positioned. * @param source The {@link ActivityRecord} activity was started from. * @param options The {@link ActivityOptions} specified for the activity. * @param currentParams The current {@link LaunchParams}. This can differ from the initial * params as it represents the modified params up to this point. * @param outParams The resulting {@link LaunchParams} after all calculations. * @return A {@link Result} representing the result of the * {@link LaunchParams} calculation. */ @Result int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, LaunchParams currentParams, LaunchParams outParams); } }