Merge "Synchronize SplitController" into tm-dev am: d4d0fee814
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18418602 Change-Id: Ie8fe385b3d2bfe862ed2ba8ecd228860cbab10f2 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -47,6 +47,7 @@ import android.util.SparseArray;
|
|||||||
import android.window.TaskFragmentInfo;
|
import android.window.TaskFragmentInfo;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
|
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -65,9 +66,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
private static final String TAG = "SplitController";
|
private static final String TAG = "SplitController";
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@GuardedBy("mLock")
|
||||||
final SplitPresenter mPresenter;
|
final SplitPresenter mPresenter;
|
||||||
|
|
||||||
// Currently applied split configuration.
|
// Currently applied split configuration.
|
||||||
|
@GuardedBy("mLock")
|
||||||
private final List<EmbeddingRule> mSplitRules = new ArrayList<>();
|
private final List<EmbeddingRule> mSplitRules = new ArrayList<>();
|
||||||
/**
|
/**
|
||||||
* Map from Task id to {@link TaskContainer} which contains all TaskFragment and split pair info
|
* Map from Task id to {@link TaskContainer} which contains all TaskFragment and split pair info
|
||||||
@@ -76,6 +79,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
* organizer.
|
* organizer.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@GuardedBy("mLock")
|
||||||
final SparseArray<TaskContainer> mTaskContainers = new SparseArray<>();
|
final SparseArray<TaskContainer> mTaskContainers = new SparseArray<>();
|
||||||
|
|
||||||
// Callback to Jetpack to notify about changes to split states.
|
// Callback to Jetpack to notify about changes to split states.
|
||||||
@@ -83,6 +87,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
private Consumer<List<SplitInfo>> mEmbeddingCallback;
|
private Consumer<List<SplitInfo>> mEmbeddingCallback;
|
||||||
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
|
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
public SplitController() {
|
public SplitController() {
|
||||||
final MainThreadExecutor executor = new MainThreadExecutor();
|
final MainThreadExecutor executor = new MainThreadExecutor();
|
||||||
@@ -100,180 +105,183 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
/** Updates the embedding rules applied to future activity launches. */
|
/** Updates the embedding rules applied to future activity launches. */
|
||||||
@Override
|
@Override
|
||||||
public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) {
|
public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) {
|
||||||
mSplitRules.clear();
|
synchronized (mLock) {
|
||||||
mSplitRules.addAll(rules);
|
mSplitRules.clear();
|
||||||
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
mSplitRules.addAll(rules);
|
||||||
updateAnimationOverride(mTaskContainers.valueAt(i));
|
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
||||||
|
updateAnimationOverride(mTaskContainers.valueAt(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<EmbeddingRule> getSplitRules() {
|
List<EmbeddingRule> getSplitRules() {
|
||||||
return mSplitRules;
|
return mSplitRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts an activity to side of the launchingActivity with the provided split config.
|
|
||||||
*/
|
|
||||||
public void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent intent,
|
|
||||||
@Nullable Bundle options, @NonNull SplitRule sideRule,
|
|
||||||
@Nullable Consumer<Exception> failureCallback, boolean isPlaceholder) {
|
|
||||||
try {
|
|
||||||
mPresenter.startActivityToSide(launchingActivity, intent, options, sideRule,
|
|
||||||
isPlaceholder);
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (failureCallback != null) {
|
|
||||||
failureCallback.accept(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the split organizer callback to notify about changes to active splits.
|
* Registers the split organizer callback to notify about changes to active splits.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setSplitInfoCallback(@NonNull Consumer<List<SplitInfo>> callback) {
|
public void setSplitInfoCallback(@NonNull Consumer<List<SplitInfo>> callback) {
|
||||||
mEmbeddingCallback = callback;
|
synchronized (mLock) {
|
||||||
updateCallbackIfNecessary();
|
mEmbeddingCallback = callback;
|
||||||
|
updateCallbackIfNecessary();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||||
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
synchronized (mLock) {
|
||||||
if (container == null) {
|
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
||||||
return;
|
if (container == null) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
container.setInfo(taskFragmentInfo);
|
container.setInfo(taskFragmentInfo);
|
||||||
if (container.isFinished()) {
|
if (container.isFinished()) {
|
||||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
|
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
|
||||||
|
}
|
||||||
|
updateCallbackIfNecessary();
|
||||||
}
|
}
|
||||||
updateCallbackIfNecessary();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||||
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
synchronized (mLock) {
|
||||||
if (container == null) {
|
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
||||||
return;
|
if (container == null) {
|
||||||
}
|
return;
|
||||||
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
final boolean wasInPip = isInPictureInPicture(container);
|
|
||||||
container.setInfo(taskFragmentInfo);
|
|
||||||
final boolean isInPip = isInPictureInPicture(container);
|
|
||||||
// Check if there are no running activities - consider the container empty if there are no
|
|
||||||
// non-finishing activities left.
|
|
||||||
if (!taskFragmentInfo.hasRunningActivity()) {
|
|
||||||
if (taskFragmentInfo.isTaskFragmentClearedForPip()) {
|
|
||||||
// Do not finish the dependents if the last activity is reparented to PiP.
|
|
||||||
// Instead, the original split should be cleanup, and the dependent may be expanded
|
|
||||||
// to fullscreen.
|
|
||||||
cleanupForEnterPip(wct, container);
|
|
||||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct);
|
|
||||||
} else if (taskFragmentInfo.isTaskClearedForReuse()) {
|
|
||||||
// Do not finish the dependents if this TaskFragment was cleared due to launching
|
|
||||||
// activity in the Task.
|
|
||||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct);
|
|
||||||
} else if (!container.isWaitingActivityAppear()) {
|
|
||||||
// Do not finish the container before the expected activity appear until timeout.
|
|
||||||
mPresenter.cleanupContainer(container, true /* shouldFinishDependent */, wct);
|
|
||||||
}
|
}
|
||||||
} else if (wasInPip && isInPip) {
|
|
||||||
// No update until exit PIP.
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
return;
|
final boolean wasInPip = isInPictureInPicture(container);
|
||||||
} else if (isInPip) {
|
container.setInfo(taskFragmentInfo);
|
||||||
// Enter PIP.
|
final boolean isInPip = isInPictureInPicture(container);
|
||||||
// All overrides will be cleanup.
|
// Check if there are no running activities - consider the container empty if there are
|
||||||
container.setLastRequestedBounds(null /* bounds */);
|
// no non-finishing activities left.
|
||||||
container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
|
if (!taskFragmentInfo.hasRunningActivity()) {
|
||||||
cleanupForEnterPip(wct, container);
|
if (taskFragmentInfo.isTaskFragmentClearedForPip()) {
|
||||||
} else if (wasInPip) {
|
// Do not finish the dependents if the last activity is reparented to PiP.
|
||||||
// Exit PIP.
|
// Instead, the original split should be cleanup, and the dependent may be
|
||||||
// Updates the presentation of the container. Expand or launch placeholder if needed.
|
// expanded to fullscreen.
|
||||||
updateContainer(wct, container);
|
cleanupForEnterPip(wct, container);
|
||||||
|
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct);
|
||||||
|
} else if (taskFragmentInfo.isTaskClearedForReuse()) {
|
||||||
|
// Do not finish the dependents if this TaskFragment was cleared due to
|
||||||
|
// launching activity in the Task.
|
||||||
|
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct);
|
||||||
|
} else if (!container.isWaitingActivityAppear()) {
|
||||||
|
// Do not finish the container before the expected activity appear until
|
||||||
|
// timeout.
|
||||||
|
mPresenter.cleanupContainer(container, true /* shouldFinishDependent */, wct);
|
||||||
|
}
|
||||||
|
} else if (wasInPip && isInPip) {
|
||||||
|
// No update until exit PIP.
|
||||||
|
return;
|
||||||
|
} else if (isInPip) {
|
||||||
|
// Enter PIP.
|
||||||
|
// All overrides will be cleanup.
|
||||||
|
container.setLastRequestedBounds(null /* bounds */);
|
||||||
|
container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
|
||||||
|
cleanupForEnterPip(wct, container);
|
||||||
|
} else if (wasInPip) {
|
||||||
|
// Exit PIP.
|
||||||
|
// Updates the presentation of the container. Expand or launch placeholder if
|
||||||
|
// needed.
|
||||||
|
updateContainer(wct, container);
|
||||||
|
}
|
||||||
|
mPresenter.applyTransaction(wct);
|
||||||
|
updateCallbackIfNecessary();
|
||||||
}
|
}
|
||||||
mPresenter.applyTransaction(wct);
|
|
||||||
updateCallbackIfNecessary();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||||
final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
synchronized (mLock) {
|
||||||
if (container != null) {
|
final TaskFragmentContainer container = getContainer(
|
||||||
// Cleanup if the TaskFragment vanished is not requested by the organizer.
|
taskFragmentInfo.getFragmentToken());
|
||||||
removeContainer(container);
|
if (container != null) {
|
||||||
// Make sure the top container is updated.
|
// Cleanup if the TaskFragment vanished is not requested by the organizer.
|
||||||
final TaskFragmentContainer newTopContainer = getTopActiveContainer(
|
removeContainer(container);
|
||||||
container.getTaskId());
|
// Make sure the top container is updated.
|
||||||
if (newTopContainer != null) {
|
final TaskFragmentContainer newTopContainer = getTopActiveContainer(
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
container.getTaskId());
|
||||||
updateContainer(wct, newTopContainer);
|
if (newTopContainer != null) {
|
||||||
mPresenter.applyTransaction(wct);
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
updateContainer(wct, newTopContainer);
|
||||||
|
mPresenter.applyTransaction(wct);
|
||||||
|
}
|
||||||
|
updateCallbackIfNecessary();
|
||||||
}
|
}
|
||||||
updateCallbackIfNecessary();
|
cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
|
||||||
}
|
}
|
||||||
cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
|
public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
|
||||||
@NonNull Configuration parentConfig) {
|
@NonNull Configuration parentConfig) {
|
||||||
final TaskFragmentContainer container = getContainer(fragmentToken);
|
synchronized (mLock) {
|
||||||
if (container != null) {
|
final TaskFragmentContainer container = getContainer(fragmentToken);
|
||||||
onTaskConfigurationChanged(container.getTaskId(), parentConfig);
|
if (container != null) {
|
||||||
if (isInPictureInPicture(parentConfig)) {
|
onTaskConfigurationChanged(container.getTaskId(), parentConfig);
|
||||||
// No need to update presentation in PIP until the Task exit PIP.
|
if (isInPictureInPicture(parentConfig)) {
|
||||||
return;
|
// No need to update presentation in PIP until the Task exit PIP.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mPresenter.updateContainer(container);
|
||||||
|
updateCallbackIfNecessary();
|
||||||
}
|
}
|
||||||
mPresenter.updateContainer(container);
|
|
||||||
updateCallbackIfNecessary();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityReparentToTask(int taskId, @NonNull Intent activityIntent,
|
public void onActivityReparentToTask(int taskId, @NonNull Intent activityIntent,
|
||||||
@NonNull IBinder activityToken) {
|
@NonNull IBinder activityToken) {
|
||||||
// If the activity belongs to the current app process, we treat it as a new activity launch.
|
synchronized (mLock) {
|
||||||
final Activity activity = getActivity(activityToken);
|
// If the activity belongs to the current app process, we treat it as a new activity
|
||||||
if (activity != null) {
|
// launch.
|
||||||
// We don't allow split as primary for new launch because we currently only support
|
final Activity activity = getActivity(activityToken);
|
||||||
// launching to top. We allow split as primary for activity reparent because the
|
if (activity != null) {
|
||||||
// activity may be split as primary before it is reparented out. In that case, we want
|
// We don't allow split as primary for new launch because we currently only support
|
||||||
// to show it as primary again when it is reparented back.
|
// launching to top. We allow split as primary for activity reparent because the
|
||||||
if (!resolveActivityToContainer(activity, true /* isOnReparent */)) {
|
// activity may be split as primary before it is reparented out. In that case, we
|
||||||
|
// want to show it as primary again when it is reparented back.
|
||||||
|
if (!resolveActivityToContainer(activity, true /* isOnReparent */)) {
|
||||||
|
// When there is no embedding rule matched, try to place it in the top container
|
||||||
|
// like a normal launch.
|
||||||
|
placeActivityInTopContainer(activity);
|
||||||
|
}
|
||||||
|
updateCallbackIfNecessary();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TaskContainer taskContainer = getTaskContainer(taskId);
|
||||||
|
if (taskContainer == null || taskContainer.isInPictureInPicture()) {
|
||||||
|
// We don't embed activity when it is in PIP.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the activity belongs to a different app process, we treat it as starting new
|
||||||
|
// intent, since both actions might result in a new activity that should appear in an
|
||||||
|
// organized TaskFragment.
|
||||||
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
TaskFragmentContainer targetContainer = resolveStartActivityIntent(wct, taskId,
|
||||||
|
activityIntent, null /* launchingActivity */);
|
||||||
|
if (targetContainer == null) {
|
||||||
// When there is no embedding rule matched, try to place it in the top container
|
// When there is no embedding rule matched, try to place it in the top container
|
||||||
// like a normal launch.
|
// like a normal launch.
|
||||||
placeActivityInTopContainer(activity);
|
targetContainer = taskContainer.getTopTaskFragmentContainer();
|
||||||
}
|
}
|
||||||
updateCallbackIfNecessary();
|
if (targetContainer == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
wct.reparentActivityToTaskFragment(targetContainer.getTaskFragmentToken(),
|
||||||
|
activityToken);
|
||||||
|
mPresenter.applyTransaction(wct);
|
||||||
|
// Because the activity does not belong to the organizer process, we wait until
|
||||||
|
// onTaskFragmentAppeared to trigger updateCallbackIfNecessary().
|
||||||
}
|
}
|
||||||
|
|
||||||
final TaskContainer taskContainer = getTaskContainer(taskId);
|
|
||||||
if (taskContainer == null || taskContainer.isInPictureInPicture()) {
|
|
||||||
// We don't embed activity when it is in PIP.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the activity belongs to a different app process, we treat it as starting new intent,
|
|
||||||
// since both actions might result in a new activity that should appear in an organized
|
|
||||||
// TaskFragment.
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
TaskFragmentContainer targetContainer = resolveStartActivityIntent(wct, taskId,
|
|
||||||
activityIntent, null /* launchingActivity */);
|
|
||||||
if (targetContainer == null) {
|
|
||||||
// When there is no embedding rule matched, try to place it in the top container like a
|
|
||||||
// normal launch.
|
|
||||||
targetContainer = taskContainer.getTopTaskFragmentContainer();
|
|
||||||
}
|
|
||||||
if (targetContainer == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wct.reparentActivityToTaskFragment(targetContainer.getTaskFragmentToken(), activityToken);
|
|
||||||
mPresenter.applyTransaction(wct);
|
|
||||||
// Because the activity does not belong to the organizer process, we wait until
|
|
||||||
// onTaskFragmentAppeared to trigger updateCallbackIfNecessary().
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called on receiving {@link #onTaskFragmentVanished(TaskFragmentInfo)} for cleanup. */
|
/** Called on receiving {@link #onTaskFragmentVanished(TaskFragmentInfo)} for cleanup. */
|
||||||
@@ -480,6 +488,22 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
mPresenter.applyTransaction(wct);
|
mPresenter.applyTransaction(wct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts an activity to side of the launchingActivity with the provided split config.
|
||||||
|
*/
|
||||||
|
private void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent intent,
|
||||||
|
@Nullable Bundle options, @NonNull SplitRule sideRule,
|
||||||
|
@Nullable Consumer<Exception> failureCallback, boolean isPlaceholder) {
|
||||||
|
try {
|
||||||
|
mPresenter.startActivityToSide(launchingActivity, intent, options, sideRule,
|
||||||
|
isPlaceholder);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (failureCallback != null) {
|
||||||
|
failureCallback.accept(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands the given activity by either expanding the TaskFragment it is currently in or putting
|
* Expands the given activity by either expanding the TaskFragment it is currently in or putting
|
||||||
* it into a new expanded TaskFragment.
|
* it into a new expanded TaskFragment.
|
||||||
@@ -1382,25 +1406,28 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) {
|
public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
final IBinder activityToken = activity.getActivityToken();
|
synchronized (mLock) {
|
||||||
final IBinder initialTaskFragmentToken = getInitialTaskFragmentToken(activity);
|
final IBinder activityToken = activity.getActivityToken();
|
||||||
// If the activity is not embedded, then it will not have an initial task fragment token
|
final IBinder initialTaskFragmentToken = getInitialTaskFragmentToken(activity);
|
||||||
// so no further action is needed.
|
// If the activity is not embedded, then it will not have an initial task fragment
|
||||||
if (initialTaskFragmentToken == null) {
|
// token so no further action is needed.
|
||||||
return;
|
if (initialTaskFragmentToken == null) {
|
||||||
}
|
return;
|
||||||
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
}
|
||||||
final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
|
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
||||||
.mContainers;
|
final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
|
||||||
for (int j = containers.size() - 1; j >= 0; j--) {
|
.mContainers;
|
||||||
final TaskFragmentContainer container = containers.get(j);
|
for (int j = containers.size() - 1; j >= 0; j--) {
|
||||||
if (!container.hasActivity(activityToken)
|
final TaskFragmentContainer container = containers.get(j);
|
||||||
&& container.getTaskFragmentToken().equals(initialTaskFragmentToken)) {
|
if (!container.hasActivity(activityToken)
|
||||||
// The onTaskFragmentInfoChanged callback containing this activity has not
|
&& container.getTaskFragmentToken()
|
||||||
// reached the client yet, so add the activity to the pending appeared
|
.equals(initialTaskFragmentToken)) {
|
||||||
// activities.
|
// The onTaskFragmentInfoChanged callback containing this activity has
|
||||||
container.addPendingAppearedActivity(activity);
|
// not reached the client yet, so add the activity to the pending
|
||||||
return;
|
// appeared activities.
|
||||||
|
container.addPendingAppearedActivity(activity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1412,17 +1439,23 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
// first. In case of a configured placeholder activity we want to make sure
|
// first. In case of a configured placeholder activity we want to make sure
|
||||||
// that we don't launch it if an activity itself already requested something to be
|
// that we don't launch it if an activity itself already requested something to be
|
||||||
// launched to side.
|
// launched to side.
|
||||||
SplitController.this.onActivityCreated(activity);
|
synchronized (mLock) {
|
||||||
|
SplitController.this.onActivityCreated(activity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityConfigurationChanged(Activity activity) {
|
public void onActivityConfigurationChanged(Activity activity) {
|
||||||
SplitController.this.onActivityConfigurationChanged(activity);
|
synchronized (mLock) {
|
||||||
|
SplitController.this.onActivityConfigurationChanged(activity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityPostDestroyed(Activity activity) {
|
public void onActivityPostDestroyed(Activity activity) {
|
||||||
SplitController.this.onActivityDestroyed(activity);
|
synchronized (mLock) {
|
||||||
|
SplitController.this.onActivityDestroyed(activity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1457,16 +1490,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
return super.onStartActivity(who, intent, options);
|
return super.onStartActivity(who, intent, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int taskId = getTaskId(launchingActivity);
|
synchronized (mLock) {
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final int taskId = getTaskId(launchingActivity);
|
||||||
final TaskFragmentContainer launchedInTaskFragment = resolveStartActivityIntent(wct,
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
taskId, intent, launchingActivity);
|
final TaskFragmentContainer launchedInTaskFragment = resolveStartActivityIntent(wct,
|
||||||
if (launchedInTaskFragment != null) {
|
taskId, intent, launchingActivity);
|
||||||
mPresenter.applyTransaction(wct);
|
if (launchedInTaskFragment != null) {
|
||||||
// Amend the request to let the WM know that the activity should be placed in the
|
mPresenter.applyTransaction(wct);
|
||||||
// dedicated container.
|
// Amend the request to let the WM know that the activity should be placed in
|
||||||
options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
|
// the dedicated container.
|
||||||
launchedInTaskFragment.getTaskFragmentToken());
|
options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
|
||||||
|
launchedInTaskFragment.getTaskFragmentToken());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onStartActivity(who, intent, options);
|
return super.onStartActivity(who, intent, options);
|
||||||
@@ -1479,7 +1514,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isActivityEmbedded(@NonNull Activity activity) {
|
public boolean isActivityEmbedded(@NonNull Activity activity) {
|
||||||
return mPresenter.isActivityEmbedded(activity.getActivityToken());
|
synchronized (mLock) {
|
||||||
|
return mPresenter.isActivityEmbedded(activity.getActivityToken());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user