blob: 7ef4d19283ed1d5918e696daf34eeb46405c393f [file] [log] [blame]
/*
* Copyright (C) 2021 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.quickstep;
import android.content.Context;
import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* Glues together the necessary components to animate a remote target using a
* {@link TaskViewSimulator}
*/
public class RemoteTargetGluer {
private static final String TAG = "RemoteTargetGluer";
private RemoteTargetHandle[] mRemoteTargetHandles;
private SplitConfigurationOptions.StagedSplitBounds mStagedSplitBounds;
/**
* Use this constructor if remote targets are split-screen independent
*/
public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy,
RemoteAnimationTargets targets) {
mRemoteTargetHandles = createHandles(context, sizingStrategy, targets.apps.length);
}
/**
* Use this constructor if you want the number of handles created to match the number of active
* running tasks
*/
public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
.getRunningSplitTaskIds();
mRemoteTargetHandles = createHandles(context, sizingStrategy, splitIds.length == 2 ? 2 : 1);
}
private RemoteTargetHandle[] createHandles(Context context,
BaseActivityInterface sizingStrategy, int numHandles) {
RemoteTargetHandle[] handles = new RemoteTargetHandle[numHandles];
for (int i = 0; i < numHandles; i++) {
TaskViewSimulator tvs = new TaskViewSimulator(context, sizingStrategy);
TransformParams transformParams = new TransformParams();
handles[i] = new RemoteTargetHandle(tvs, transformParams);
}
return handles;
}
/**
* Pairs together {@link TaskViewSimulator}s and {@link TransformParams} into a
* {@link RemoteTargetHandle}
* Assigns only the apps associated with {@param targets} into their own TaskViewSimulators.
* Length of targets.apps should match that of {@link #mRemoteTargetHandles}.
*
* If split screen may be active when this is called, you might want to use
* {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)}
*/
public RemoteTargetHandle[] assignTargets(RemoteAnimationTargets targets) {
for (int i = 0; i < mRemoteTargetHandles.length; i++) {
RemoteAnimationTargetCompat primaryTaskTarget = targets.apps[i];
mRemoteTargetHandles[i].mTransformParams.setTargetSet(
createRemoteAnimationTargetsForTarget(primaryTaskTarget, targets));
mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
}
return mRemoteTargetHandles;
}
/**
* Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this matches the
* apps in targets.apps to that of the split screened tasks. If split screen is active, then
* {@link #mRemoteTargetHandles} index 0 will be the left/top task, index one right/bottom
*/
public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
.getRunningSplitTaskIds();
if (splitIds.length == 0 && mRemoteTargetHandles.length > 1) {
// There's a chance that between the creation of this class and assigning targets,
// LauncherSplitScreenListener may have received callback that removes split
mRemoteTargetHandles = new RemoteTargetHandle[]{mRemoteTargetHandles[0]};
Log.w(TAG, "splitTaskIds changed between creation and assignment");
}
RemoteAnimationTargetCompat primaryTaskTarget;
RemoteAnimationTargetCompat secondaryTaskTarget;
if (mRemoteTargetHandles.length == 1) {
// If we're not in split screen, the splitIds count doesn't really matter since we
// should always hit this case. Right now there's no use case for multiple app targets
// without being in split screen
primaryTaskTarget = targets.apps[0];
mRemoteTargetHandles[0].mTransformParams.setTargetSet(targets);
mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget, null);
} else {
// split screen
primaryTaskTarget = targets.findTask(splitIds[0]);
secondaryTaskTarget = targets.findTask(splitIds[1]);
mStagedSplitBounds = new SplitConfigurationOptions.StagedSplitBounds(
primaryTaskTarget.screenSpaceBounds,
secondaryTaskTarget.screenSpaceBounds);
mRemoteTargetHandles[0].mTransformParams.setTargetSet(
createRemoteAnimationTargetsForTarget(primaryTaskTarget, targets));
mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget,
mStagedSplitBounds);
mRemoteTargetHandles[1].mTransformParams.setTargetSet(
createRemoteAnimationTargetsForTarget(secondaryTaskTarget, targets));
mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(secondaryTaskTarget,
mStagedSplitBounds);
}
return mRemoteTargetHandles;
}
private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
RemoteAnimationTargetCompat target,
RemoteAnimationTargets targets) {
return new RemoteAnimationTargets(new RemoteAnimationTargetCompat[]{target},
targets.wallpapers, targets.nonApps, targets.targetMode);
}
public RemoteTargetHandle[] getRemoteTargetHandles() {
return mRemoteTargetHandles;
}
public SplitConfigurationOptions.StagedSplitBounds getStagedSplitBounds() {
return mStagedSplitBounds;
}
/**
* Container to keep together all the associated objects whose properties need to be updated to
* animate a single remote app target
*/
public static class RemoteTargetHandle {
private final TaskViewSimulator mTaskViewSimulator;
private final TransformParams mTransformParams;
@Nullable
private AnimatorControllerWithResistance mPlaybackController;
public RemoteTargetHandle(TaskViewSimulator taskViewSimulator,
TransformParams transformParams) {
mTransformParams = transformParams;
mTaskViewSimulator = taskViewSimulator;
}
public TaskViewSimulator getTaskViewSimulator() {
return mTaskViewSimulator;
}
public TransformParams getTransformParams() {
return mTransformParams;
}
@Nullable
public AnimatorControllerWithResistance getPlaybackController() {
return mPlaybackController;
}
public void setPlaybackController(
@Nullable AnimatorControllerWithResistance playbackController) {
mPlaybackController = playbackController;
}
}
}