Merge "Collapse bubbles when drag and drop is initiated" into tm-dev am: ef1cc8850f am: 4437048f1a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17715693
Change-Id: I0407669dd09567eb74318522d1ec8faa66dab63f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 5ef2413..806c395 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -96,6 +96,7 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
@@ -214,6 +215,8 @@
/** One handed mode controller to register transition listener. */
private Optional<OneHandedController> mOneHandedOptional;
+ /** Drag and drop controller to register listener for onDragStarted. */
+ private DragAndDropController mDragAndDropController;
/**
* Creates an instance of the BubbleController.
@@ -230,6 +233,7 @@
ShellTaskOrganizer organizer,
DisplayController displayController,
Optional<OneHandedController> oneHandedOptional,
+ DragAndDropController dragAndDropController,
ShellExecutor mainExecutor,
Handler mainHandler,
TaskViewTransitions taskViewTransitions,
@@ -241,8 +245,8 @@
new BubbleDataRepository(context, launcherApps, mainExecutor),
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
logger, taskStackListener, organizer, positioner, displayController,
- oneHandedOptional, mainExecutor, mainHandler, taskViewTransitions,
- syncQueue);
+ oneHandedOptional, dragAndDropController, mainExecutor, mainHandler,
+ taskViewTransitions, syncQueue);
}
/**
@@ -264,6 +268,7 @@
BubblePositioner positioner,
DisplayController displayController,
Optional<OneHandedController> oneHandedOptional,
+ DragAndDropController dragAndDropController,
ShellExecutor mainExecutor,
Handler mainHandler,
TaskViewTransitions taskViewTransitions,
@@ -293,6 +298,7 @@
mDisplayController = displayController;
mTaskViewTransitions = taskViewTransitions;
mOneHandedOptional = oneHandedOptional;
+ mDragAndDropController = dragAndDropController;
mSyncQueue = syncQueue;
}
@@ -433,6 +439,7 @@
});
mOneHandedOptional.ifPresent(this::registerOneHandedState);
+ mDragAndDropController.addListener(this::collapseStack);
}
@VisibleForTesting
@@ -884,7 +891,6 @@
return mBubbleData.isExpanded();
}
- @VisibleForTesting
public void collapseStack() {
mBubbleData.setExpanded(false /* expanded */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 4fa5a10..a3fdffa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -42,6 +42,7 @@
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.fullscreen.FullscreenUnfoldController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
@@ -110,6 +111,7 @@
ShellTaskOrganizer organizer,
DisplayController displayController,
@DynamicOverride Optional<OneHandedController> oneHandedOptional,
+ DragAndDropController dragAndDropController,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler,
TaskViewTransitions taskViewTransitions,
@@ -118,7 +120,7 @@
floatingContentCoordinator, statusBarService, windowManager,
windowManagerShellWrapper, launcherApps, taskStackListener,
uiEventLogger, organizer, displayController, oneHandedOptional,
- mainExecutor, mainHandler, taskViewTransitions, syncQueue);
+ dragAndDropController, mainExecutor, mainHandler, taskViewTransitions, syncQueue);
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 11ecc91..95de2dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -35,9 +35,6 @@
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.content.ClipDescription;
import android.content.Context;
import android.content.res.Configuration;
@@ -52,17 +49,19 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
-import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
+import java.util.ArrayList;
import java.util.Optional;
/**
@@ -80,10 +79,19 @@
private SplitScreenController mSplitScreen;
private ShellExecutor mMainExecutor;
private DragAndDropImpl mImpl;
+ private ArrayList<DragAndDropListener> mListeners = new ArrayList<>();
private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>();
private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ /**
+ * Listener called during drag events, currently just onDragStarted.
+ */
+ public interface DragAndDropListener {
+ /** Called when a drag has started. */
+ void onDragStarted();
+ }
+
public DragAndDropController(Context context, DisplayController displayController,
UiEventLogger uiEventLogger, IconProvider iconProvider, ShellExecutor mainExecutor) {
mContext = context;
@@ -103,6 +111,22 @@
mDisplayController.addDisplayWindowListener(this);
}
+ /** Adds a listener to be notified of drag and drop events. */
+ public void addListener(DragAndDropListener listener) {
+ mListeners.add(listener);
+ }
+
+ /** Removes a drag and drop listener. */
+ public void removeListener(DragAndDropListener listener) {
+ mListeners.remove(listener);
+ }
+
+ private void notifyListeners() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onDragStarted();
+ }
+ }
+
@Override
public void onDisplayAdded(int displayId) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display added: %d", displayId);
@@ -137,13 +161,19 @@
new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
try {
wm.addView(rootView, layoutParams);
- mDisplayDropTargets.put(displayId,
- new PerDisplay(displayId, context, wm, rootView, dragLayout));
+ addDisplayDropTarget(displayId, context, wm, rootView, dragLayout);
} catch (WindowManager.InvalidDisplayException e) {
Slog.w(TAG, "Unable to add view for display id: " + displayId);
}
}
+ @VisibleForTesting
+ void addDisplayDropTarget(int displayId, Context context, WindowManager wm,
+ FrameLayout rootView, DragLayout dragLayout) {
+ mDisplayDropTargets.put(displayId,
+ new PerDisplay(displayId, context, wm, rootView, dragLayout));
+ }
+
@Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display changed: %d", displayId);
@@ -206,6 +236,7 @@
pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId),
event.getClipData(), loggerSessionId);
setDropTargetWindowVisibility(pd, View.VISIBLE);
+ notifyListeners();
break;
case ACTION_DRAG_ENTERED:
pd.dragLayout.show();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index 9f74520..aaeebef 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -16,15 +16,28 @@
package com.android.wm.shell.draganddrop;
+import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DragEvent.ACTION_DRAG_STARTED;
+
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.Context;
+import android.content.Intent;
import android.os.RemoteException;
import android.view.Display;
import android.view.DragEvent;
import android.view.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -33,6 +46,7 @@
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import org.junit.Before;
import org.junit.Test;
@@ -40,6 +54,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
/**
* Tests for the drag and drop controller.
*/
@@ -56,6 +72,9 @@
@Mock
private UiEventLogger mUiEventLogger;
+ @Mock
+ private DragAndDropController.DragAndDropListener mDragAndDropListener;
+
private DragAndDropController mController;
@Before
@@ -63,6 +82,7 @@
MockitoAnnotations.initMocks(this);
mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger,
mock(IconProvider.class), mock(ShellExecutor.class));
+ mController.initialize(Optional.of(mock(SplitScreenController.class)));
}
@Test
@@ -77,4 +97,45 @@
mController.onDisplayAdded(nonDefaultDisplayId);
assertFalse(mController.onDrag(dragLayout, mock(DragEvent.class)));
}
+
+ @Test
+ public void testListenerOnDragStarted() {
+ final View dragLayout = mock(View.class);
+ final Display display = mock(Display.class);
+ doReturn(display).when(dragLayout).getDisplay();
+ doReturn(DEFAULT_DISPLAY).when(display).getDisplayId();
+
+ final ClipData clipData = createClipData();
+ final DragEvent event = mock(DragEvent.class);
+ doReturn(ACTION_DRAG_STARTED).when(event).getAction();
+ doReturn(clipData).when(event).getClipData();
+ doReturn(clipData.getDescription()).when(event).getClipDescription();
+
+ mController.addListener(mDragAndDropListener);
+
+ // Ensure there's a target so that onDrag will execute
+ mController.addDisplayDropTarget(0, mContext, mock(WindowManager.class),
+ mock(FrameLayout.class), mock(DragLayout.class));
+
+ // Verify the listener is called on a valid drag action.
+ mController.onDrag(dragLayout, event);
+ verify(mDragAndDropListener, times(1)).onDragStarted();
+
+ // Verify the listener isn't called after removal.
+ reset(mDragAndDropListener);
+ mController.removeListener(mDragAndDropListener);
+ mController.onDrag(dragLayout, event);
+ verify(mDragAndDropListener, never()).onDragStarted();
+ }
+
+ private ClipData createClipData() {
+ ClipDescription clipDescription = new ClipDescription(MIMETYPE_APPLICATION_SHORTCUT,
+ new String[] { MIMETYPE_APPLICATION_SHORTCUT });
+ Intent i = new Intent();
+ i.putExtra(Intent.EXTRA_PACKAGE_NAME, "pkg");
+ i.putExtra(Intent.EXTRA_SHORTCUT_ID, "shortcutId");
+ i.putExtra(Intent.EXTRA_USER, android.os.Process.myUserHandle());
+ ClipData.Item item = new ClipData.Item(i);
+ return new ClipData(clipDescription, item);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index ca67bd2..193879e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -133,6 +133,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.google.common.collect.ImmutableList;
@@ -367,6 +368,7 @@
mPositioner,
mock(DisplayController.class),
mOneHandedOptional,
+ mock(DragAndDropController.class),
syncExecutor,
mock(Handler.class),
mTaskViewTransitions,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index ce7924a..02d8691 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -116,6 +116,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import org.junit.Before;
@@ -332,6 +333,7 @@
mPositioner,
mock(DisplayController.class),
mOneHandedOptional,
+ mock(DragAndDropController.class),
syncExecutor,
mock(Handler.class),
mTaskViewTransitions,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index 83f5987..9646edf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -35,6 +35,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import java.util.Optional;
@@ -59,6 +60,7 @@
BubblePositioner positioner,
DisplayController displayController,
Optional<OneHandedController> oneHandedOptional,
+ DragAndDropController dragAndDropController,
ShellExecutor shellMainExecutor,
Handler shellMainHandler,
TaskViewTransitions taskViewTransitions,
@@ -66,8 +68,8 @@
super(context, data, Runnable::run, floatingContentCoordinator, dataRepository,
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
bubbleLogger, taskStackListener, shellTaskOrganizer, positioner, displayController,
- oneHandedOptional, shellMainExecutor, shellMainHandler, taskViewTransitions,
- syncQueue);
+ oneHandedOptional, dragAndDropController, shellMainExecutor, shellMainHandler,
+ taskViewTransitions, syncQueue);
setInflateSynchronously(true);
initialize();
}