blob: b50267633b5289862287cd9519027c94f89715cb [file] [log] [blame]
/*
* Copyright (C) 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 com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import android.graphics.Rect;
import android.util.ArraySet;
import android.view.RemoteAnimationTarget;
import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
/**
* Wrapper around {@link com.android.systemui.shared.system.RecentsAnimationListener} which
* delegates callbacks to multiple listeners on the main thread
*/
public class RecentsAnimationCallbacks implements
com.android.systemui.shared.system.RecentsAnimationListener {
private final Set<RecentsAnimationListener> mListeners = new ArraySet<>();
private final SystemUiProxy mSystemUiProxy;
private final boolean mAllowMinimizeSplitScreen;
// TODO(141886704): Remove these references when they are no longer needed
private RecentsAnimationController mController;
private boolean mCancelled;
public RecentsAnimationCallbacks(SystemUiProxy systemUiProxy,
boolean allowMinimizeSplitScreen) {
mSystemUiProxy = systemUiProxy;
mAllowMinimizeSplitScreen = allowMinimizeSplitScreen;
}
@UiThread
public void addListener(RecentsAnimationListener listener) {
Preconditions.assertUIThread();
mListeners.add(listener);
}
@UiThread
public void removeListener(RecentsAnimationListener listener) {
Preconditions.assertUIThread();
mListeners.remove(listener);
}
@UiThread
public void removeAllListeners() {
Preconditions.assertUIThread();
mListeners.clear();
}
public void notifyAnimationCanceled() {
mCancelled = true;
onAnimationCanceled(new HashMap<>());
}
// Called only in Q platform
@BinderThread
@Deprecated
public final void onAnimationStart(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] appTargets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
onAnimationStart(controller, appTargets, new RemoteAnimationTargetCompat[0],
homeContentInsets, minimizedHomeBounds);
}
// Called only in R+ platform
@BinderThread
public final void onAnimationStart(RecentsAnimationControllerCompat animationController,
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
Rect homeContentInsets, Rect minimizedHomeBounds) {
// Convert appTargets to type RemoteAnimationTarget for all apps except Home app
RemoteAnimationTarget[] nonHomeApps = Arrays.stream(appTargets)
.filter(remoteAnimationTarget ->
remoteAnimationTarget.activityType != ACTIVITY_TYPE_HOME)
.map(RemoteAnimationTargetCompat::unwrap)
.toArray(RemoteAnimationTarget[]::new);
RemoteAnimationTarget[] nonAppTargets =
mSystemUiProxy.onGoingToRecentsLegacy(mCancelled, nonHomeApps);
RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets),
homeContentInsets, minimizedHomeBounds);
mController = new RecentsAnimationController(animationController,
mAllowMinimizeSplitScreen, this::onAnimationFinished);
if (mCancelled) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
mController::finishAnimationToApp);
} else {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(mController, targets);
}
});
}
}
@BinderThread
@Override
public final void onAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled(thumbnailDatas);
}
});
}
@BinderThread
@Override
public void onTasksAppeared(RemoteAnimationTargetCompat[] apps) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (RecentsAnimationListener listener : getListeners()) {
listener.onTasksAppeared(apps);
}
});
}
private final void onAnimationFinished(RecentsAnimationController controller) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationFinished(controller);
}
});
}
private RecentsAnimationListener[] getListeners() {
return mListeners.toArray(new RecentsAnimationListener[mListeners.size()]);
}
/**
* Listener for the recents animation callbacks.
*/
public interface RecentsAnimationListener {
default void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {}
/**
* Callback from the system when the recents animation is canceled. {@param thumbnailData}
* is passed back for rendering screenshot to replace live tile.
*/
default void onRecentsAnimationCanceled(
@NonNull HashMap<Integer, ThumbnailData> thumbnailDatas) {}
/**
* Callback made whenever the recents animation is finished.
*/
default void onRecentsAnimationFinished(@NonNull RecentsAnimationController controller) {}
/**
* Callback made when a task started from the recents is ready for an app transition.
*/
default void onTasksAppeared(@NonNull RemoteAnimationTargetCompat[] appearedTaskTarget) {}
}
}