Adding support for multiple overlay callbacks

Bug: 193244407
Test: Presubmit
Change-Id: Ic345972056752238e7e46226533fd8f33d664213
This commit is contained in:
Sunny Goyal
2022-11-02 18:58:49 -07:00
parent ef24d5954c
commit 82379187ea
6 changed files with 71 additions and 161 deletions

View File

@@ -219,6 +219,8 @@ public class QuickstepLauncher extends Launcher {
mEnableWidgetDepth = ENABLE_WIDGET_PICKER_DEPTH.get()
&& SystemProperties.getBoolean("ro.launcher.depth.widget", true);
getWorkspace().addOverlayCallback(progress ->
onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX));
}
@Override
@@ -594,17 +596,6 @@ public class QuickstepLauncher extends Launcher {
recentsView.finishRecentsAnimation(true /* toRecents */, null);
}
/**
* {@code LauncherOverlayCallbacks} scroll amount.
* Indicates transition progress to -1 screen.
* @param progress From 0 to 1.
*/
@Override
public void onScrollChanged(float progress) {
super.onScrollChanged(progress);
onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX);
}
@Override
public void onAllAppsTransition(float progress) {
super.onAllAppsTransition(progress);

View File

@@ -53,6 +53,8 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_EXIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONSTOP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RECONFIGURED;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
@@ -183,7 +185,6 @@ import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.AllAppsSwipeController;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.ActivityResultInfo;
import com.android.launcher3.util.ActivityTracker;
@@ -222,7 +223,6 @@ import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.shared.LauncherExterns;
import com.android.systemui.plugins.shared.LauncherOverlayManager;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -242,7 +242,7 @@ import java.util.stream.Stream;
*/
public class Launcher extends StatefulActivity<LauncherState>
implements LauncherExterns, Callbacks, InvariantDeviceProfile.OnIDPChangeListener,
PluginListener<LauncherOverlayPlugin>, LauncherOverlayCallbacks {
PluginListener<LauncherOverlayPlugin> {
public static final String TAG = "Launcher";
public static final ActivityTracker<Launcher> ACTIVITY_TRACKER = new ActivityTracker<>();
@@ -696,17 +696,9 @@ public class Launcher extends StatefulActivity<LauncherState>
*/
@Override
public void setLauncherOverlay(LauncherOverlay overlay) {
if (overlay != null) {
overlay.setOverlayCallbacks(this);
}
mWorkspace.setLauncherOverlay(overlay);
}
@Override
public void runOnOverlayHidden(Runnable runnable) {
getWorkspace().runOnOverlayHidden(runnable);
}
public boolean setLauncherCallbacks(LauncherCallbacks callbacks) {
mLauncherCallbacks = callbacks;
return true;
@@ -1213,18 +1205,6 @@ public class Launcher extends StatefulActivity<LauncherState>
mAppWidgetHolder.setActivityResumed(false);
}
/**
* {@code LauncherOverlayCallbacks} scroll amount.
* Indicates transition progress to -1 screen.
* @param progress From 0 to 1.
*/
@Override
public void onScrollChanged(float progress) {
if (mWorkspace != null) {
mWorkspace.onOverlayScrollChanged(progress);
}
}
/**
* Restores the previous state, if it exists.
*
@@ -2895,7 +2875,16 @@ public class Launcher extends StatefulActivity<LauncherState>
/**
* Informs us that the overlay (-1 screen, typically), has either become visible or invisible.
*/
public void onOverlayVisibilityChanged(boolean visible) {}
public void onOverlayVisibilityChanged(boolean visible) {
getStatsLogManager().logger()
.withSrcState(LAUNCHER_STATE_HOME)
.withDstState(LAUNCHER_STATE_HOME)
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
.setWorkspace(WorkspaceContainer.newBuilder()
.setPageIndex(visible ? 0 : -1))
.build())
.log(visible ? LAUNCHER_SWIPELEFT : LAUNCHER_SWIPERIGHT);
}
/**
* Informs us that the page transition has ended, so that we can react to the newly selected

View File

@@ -26,7 +26,6 @@ import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT;
@@ -58,7 +57,6 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.Toast;
@@ -119,6 +117,7 @@ import com.android.launcher3.widget.WidgetManagerHelper;
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
import com.android.launcher3.widget.util.WidgetSizes;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
import java.util.ArrayList;
import java.util.Iterator;
@@ -136,7 +135,7 @@ import java.util.stream.Collectors;
public class Workspace<T extends View & PageIndicator> extends PagedView<T>
implements DropTarget, DragSource, View.OnTouchListener,
DragController.DragListener, Insettable, StateHandler<LauncherState>,
WorkspaceLayoutManager, LauncherBindableItemsContainer {
WorkspaceLayoutManager, LauncherBindableItemsContainer, LauncherOverlayCallbacks {
/** The value that {@link #mTransitionProgress} must be greater than for
* {@link #transitionStateShouldAllowDrop()} to return true. */
@@ -254,14 +253,12 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
// State related to Launcher Overlay
private OverlayEdgeEffect mOverlayEdgeEffect;
boolean mOverlayShown = false;
private Runnable mOnOverlayHiddenCallback;
private boolean mOverlayShown = false;
private float mOverlayProgress; // 1 -> overlay completely visible, 0 -> home visible
private final List<LauncherOverlayCallbacks> mOverlayCallbacks = new ArrayList<>();
private boolean mForceDrawAdjacentPages = false;
// Total over scrollX in the overlay direction.
private float mOverlayTranslation;
// Handles workspace state transitions
private final WorkspaceStateTransitionAnimation mStateTransitionAnimation;
@@ -1151,9 +1148,15 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
}
public void setLauncherOverlay(LauncherOverlay overlay) {
mOverlayEdgeEffect = overlay == null ? null : new OverlayEdgeEffect(getContext(), overlay);
EdgeEffectCompat newEffect = overlay == null
? new EdgeEffectCompat(getContext()) : mOverlayEdgeEffect;
final EdgeEffectCompat newEffect;
if (overlay == null) {
newEffect = new EdgeEffectCompat(getContext());
mOverlayEdgeEffect = null;
} else {
newEffect = mOverlayEdgeEffect = new OverlayEdgeEffect(getContext(), overlay);
overlay.setOverlayCallbacks(this);
}
if (mIsRtl) {
mEdgeGlowRight = newEffect;
} else {
@@ -1203,132 +1206,46 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
@Override
protected boolean shouldFlingForVelocity(int velocityX) {
// When the overlay is moving, the fling or settle transition is controlled by the overlay.
return Float.compare(Math.abs(mOverlayTranslation), 0) == 0 &&
super.shouldFlingForVelocity(velocityX);
return Float.compare(Math.abs(mOverlayProgress), 0) == 0
&& super.shouldFlingForVelocity(velocityX);
}
/**
* The overlay scroll is being controlled locally, just update our overlay effect
*/
@Override
public void onOverlayScrollChanged(float scroll) {
if (Float.compare(scroll, 1f) == 0) {
mOverlayProgress = Utilities.boundToRange(scroll, 0, 1);
if (Float.compare(mOverlayProgress, 1f) == 0) {
if (!mOverlayShown) {
mLauncher.getStatsLogManager().logger()
.withSrcState(LAUNCHER_STATE_HOME)
.withDstState(LAUNCHER_STATE_HOME)
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
.setWorkspace(
LauncherAtom.WorkspaceContainer.newBuilder()
.setPageIndex(0))
.build())
.log(LAUNCHER_SWIPELEFT);
mOverlayShown = true;
mLauncher.onOverlayVisibilityChanged(true);
}
mOverlayShown = true;
// Let the Launcher activity know that the overlay is now visible.
mLauncher.onOverlayVisibilityChanged(mOverlayShown);
// Not announcing the overlay page for accessibility since it announces itself.
} else if (Float.compare(scroll, 0f) == 0) {
} else if (Float.compare(mOverlayProgress, 0f) == 0) {
if (mOverlayShown) {
// TODO: this is logged unnecessarily on home gesture.
mLauncher.getStatsLogManager().logger()
.withSrcState(LAUNCHER_STATE_HOME)
.withDstState(LAUNCHER_STATE_HOME)
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
.setWorkspace(
LauncherAtom.WorkspaceContainer.newBuilder()
.setPageIndex(-1))
.build())
.log(LAUNCHER_SWIPERIGHT);
} else if (Float.compare(mOverlayTranslation, 0f) != 0) {
// When arriving to 0 overscroll from non-zero overscroll, announce page for
// accessibility since default announcements were disabled while in overscroll
// state.
// Not doing this if mOverlayShown because in that case the accessibility service
// will announce the launcher window description upon regaining focus after
// switching from the overlay screen.
announcePageForAccessibility();
mOverlayShown = false;
mLauncher.onOverlayVisibilityChanged(false);
}
mOverlayShown = false;
// Let the Launcher activity know that the overlay is no longer visible.
mLauncher.onOverlayVisibilityChanged(mOverlayShown);
tryRunOverlayCallback();
}
float offset = 0f;
scroll = Math.max(scroll - offset, 0);
scroll = Math.min(1, scroll / (1 - offset));
float alpha = 1 - Interpolators.DEACCEL_3.getInterpolation(scroll);
float transX = mLauncher.getDragLayer().getMeasuredWidth() * scroll;
if (mIsRtl) {
transX = -transX;
int count = mOverlayCallbacks.size();
for (int i = 0; i < count; i++) {
mOverlayCallbacks.get(i).onOverlayScrollChanged(mOverlayProgress);
}
mOverlayTranslation = transX;
// TODO(adamcohen): figure out a final effect here. We may need to recommend
// different effects based on device performance. On at least one relatively high-end
// device I've tried, translating the launcher causes things to get quite laggy.
mLauncher.getDragLayer().setTranslationX(transX);
mLauncher.getDragLayer().getAlphaProperty(ALPHA_INDEX_OVERLAY).setValue(alpha);
}
/**
* @return false if the callback is still pending
* Adds a callback for receiving overlay progress
*/
private boolean tryRunOverlayCallback() {
if (mOnOverlayHiddenCallback == null) {
// Return true as no callback is pending. This is used by OnWindowFocusChangeListener
// to remove itself if multiple focus handles were added.
return true;
}
if (mOverlayShown || !hasWindowFocus()) {
return false;
}
mOnOverlayHiddenCallback.run();
mOnOverlayHiddenCallback = null;
return true;
public void addOverlayCallback(LauncherOverlayCallbacks callback) {
mOverlayCallbacks.add(callback);
callback.onOverlayScrollChanged(mOverlayProgress);
}
/**
* Runs the given callback when the minus one overlay is hidden. Specifically, it is run
* when launcher's window has focus and the overlay is no longer being shown. If a callback
* is already present, the new callback will chain off it so both are run.
*
* @return Whether the callback was deferred.
* Removes a previously added overlay progress callback
*/
public boolean runOnOverlayHidden(Runnable callback) {
if (mOnOverlayHiddenCallback == null) {
mOnOverlayHiddenCallback = callback;
} else {
// Chain the new callback onto the previous callback(s).
Runnable oldCallback = mOnOverlayHiddenCallback;
mOnOverlayHiddenCallback = () -> {
oldCallback.run();
callback.run();
};
}
if (!tryRunOverlayCallback()) {
ViewTreeObserver observer = getViewTreeObserver();
if (observer != null && observer.isAlive()) {
observer.addOnWindowFocusChangeListener(
new ViewTreeObserver.OnWindowFocusChangeListener() {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (tryRunOverlayCallback() && observer.isAlive()) {
observer.removeOnWindowFocusChangeListener(this);
}
}});
}
return true;
}
return false;
public void removeOverlayCallback(LauncherOverlayCallbacks callback) {
mOverlayCallbacks.remove(callback);
}
@Override
@@ -3470,7 +3387,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
protected boolean canAnnouncePageDescription() {
// Disable announcements while overscrolling potentially to overlay screen because if we end
// up on the overlay screen, it will take care of announcing itself.
return Float.compare(mOverlayTranslation, 0f) == 0;
return Float.compare(mOverlayProgress, 0f) == 0;
}
@Override

View File

@@ -47,7 +47,9 @@ import com.android.launcher3.DropTargetBar;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringProperty;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
@@ -56,13 +58,14 @@ import com.android.launcher3.graphics.Scrim;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
import java.util.ArrayList;
/**
* A ViewGroup that coordinates dragging across its descendants
*/
public class DragLayer extends BaseDragLayer<Launcher> {
public class DragLayer extends BaseDragLayer<Launcher> implements LauncherOverlayCallbacks {
public static final int ALPHA_INDEX_OVERLAY = 0;
private static final int ALPHA_CHANNEL_COUNT = 1;
@@ -70,6 +73,8 @@ public class DragLayer extends BaseDragLayer<Launcher> {
public static final int ANIMATION_END_DISAPPEAR = 0;
public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
private final boolean mIsRtl;
private DragController mDragController;
// Variables relating to animation of views after drop
@@ -100,6 +105,7 @@ public class DragLayer extends BaseDragLayer<Launcher> {
setChildrenDrawingOrderEnabled(true);
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
mIsRtl = Utilities.isRtl(getResources());
}
/**
@@ -109,6 +115,7 @@ public class DragLayer extends BaseDragLayer<Launcher> {
mDragController = dragController;
recreateControllers();
mWorkspaceDragScrim = new Scrim(this);
workspace.addOverlayCallback(this);
}
@Override
@@ -476,4 +483,16 @@ public class DragLayer extends BaseDragLayer<Launcher> {
controller.onOneHandedModeStateChanged(activated);
}
}
@Override
public void onOverlayScrollChanged(float progress) {
float alpha = 1 - Interpolators.DEACCEL_3.getInterpolation(progress);
float transX = getMeasuredWidth() * progress;
if (mIsRtl) {
transX = -transX;
}
setTranslationX(transX);
getAlphaProperty(ALPHA_INDEX_OVERLAY).setValue(alpha);
}
}

View File

@@ -40,10 +40,4 @@ public interface LauncherExterns {
* Sets the overlay on the target activity
*/
void setLauncherOverlay(LauncherOverlay overlay);
/**
* Executes the command, next time the overlay is hidden
*/
void runOnOverlayHidden(Runnable runnable);
}

View File

@@ -93,6 +93,6 @@ public interface LauncherOverlayManager extends Application.ActivityLifecycleCal
interface LauncherOverlayCallbacks {
void onScrollChanged(float progress);
void onOverlayScrollChanged(float progress);
}
}