Adding finish signal to GestureNavContract.
Also fixing also-closing behavior for FloatingSurfaceView for Android S
Bug: 228260232
Test: Verified manually on device
Change-Id: I83f6417a756c1459533294d681e83abba6ea58aa
diff --git a/src/com/android/launcher3/GestureNavContract.java b/src/com/android/launcher3/GestureNavContract.java
index 2a7e629..c782dca 100644
--- a/src/com/android/launcher3/GestureNavContract.java
+++ b/src/com/android/launcher3/GestureNavContract.java
@@ -18,20 +18,30 @@
import static android.content.Intent.EXTRA_COMPONENT_NAME;
import static android.content.Intent.EXTRA_USER;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE;
+
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
+import android.os.Messenger;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.SurfaceControl;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.views.ActivityContext;
+
+import java.lang.ref.WeakReference;
+
/**
* Class to encapsulate the handshake protocol between Launcher and gestureNav.
*/
@@ -43,6 +53,7 @@
public static final String EXTRA_ICON_POSITION = "gesture_nav_contract_icon_position";
public static final String EXTRA_ICON_SURFACE = "gesture_nav_contract_surface_control";
public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
+ public static final String EXTRA_ON_FINISH_CALLBACK = "gesture_nav_contract_finish_callback";
public final ComponentName componentName;
public final UserHandle user;
@@ -59,10 +70,15 @@
* Sends the position information to the receiver
*/
@TargetApi(Build.VERSION_CODES.R)
- public void sendEndPosition(RectF position, @Nullable SurfaceControl surfaceControl) {
+ public void sendEndPosition(RectF position, ActivityContext context,
+ @Nullable SurfaceControl surfaceControl) {
Bundle result = new Bundle();
result.putParcelable(EXTRA_ICON_POSITION, position);
result.putParcelable(EXTRA_ICON_SURFACE, surfaceControl);
+ if (sMessageReceiver == null) {
+ sMessageReceiver = new StaticMessageReceiver();
+ }
+ result.putParcelable(EXTRA_ON_FINISH_CALLBACK, sMessageReceiver.setCurrentContext(context));
Message callback = Message.obtain();
callback.copyFrom(mCallback);
@@ -98,4 +114,42 @@
}
return null;
}
+
+ /**
+ * Message used for receiving gesture nav contract information. We use a static messenger to
+ * avoid leaking too make binders in case the receiving launcher does not handle the contract
+ * properly.
+ */
+ private static StaticMessageReceiver sMessageReceiver = null;
+
+ private static class StaticMessageReceiver implements Handler.Callback {
+
+ private static final int MSG_CLOSE_LAST_TARGET = 0;
+
+ private final Messenger mMessenger =
+ new Messenger(new Handler(Looper.getMainLooper(), this));
+
+ private WeakReference<ActivityContext> mLastTarget = new WeakReference<>(null);
+
+ public Message setCurrentContext(ActivityContext context) {
+ mLastTarget = new WeakReference<>(context);
+
+ Message msg = Message.obtain();
+ msg.replyTo = mMessenger;
+ msg.what = MSG_CLOSE_LAST_TARGET;
+ return msg;
+ }
+
+ @Override
+ public boolean handleMessage(@NonNull Message message) {
+ if (message.what == MSG_CLOSE_LAST_TARGET) {
+ ActivityContext lastContext = mLastTarget.get();
+ if (lastContext != null) {
+ AbstractFloatingView.closeOpenViews(lastContext, false, TYPE_ICON_SURFACE);
+ }
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1cead11..2636d55 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -604,7 +604,13 @@
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
- AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
+ // Starting with Android S, onEnterAnimationComplete is sent immediately
+ // causing the surface to get removed before the animation completed (b/175345344).
+ // Instead we rely on next user touch event to remove the view and optionally a callback
+ // from system from Android T onwards.
+ if (!Utilities.ATLEAST_S) {
+ AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
+ }
}
@Override
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index 19c28b4..bfb75f0 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -62,7 +62,6 @@
private final SurfaceView mSurfaceView;
-
private View mIcon;
private GestureNavContract mContract;
@@ -103,7 +102,13 @@
private void removeViewFromParent() {
mPicture.beginRecording(1, 1);
mPicture.endRecording();
- mLauncher.getDragLayer().removeView(this);
+ mLauncher.getDragLayer().removeViewInLayout(this);
+ }
+
+ private void removeViewImmediate() {
+ // Cancel any pending remove
+ Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(mRemoveViewRunnable);
+ removeViewFromParent();
}
/**
@@ -115,9 +120,7 @@
view.mContract = contract;
view.mIsOpen = true;
- // Cancel any pending remove
- Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(view.mRemoveViewRunnable);
- view.removeViewFromParent();
+ view.removeViewImmediate();
launcher.getDragLayer().addView(view);
}
@@ -129,6 +132,7 @@
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
close(false);
+ removeViewImmediate();
return false;
}
@@ -197,7 +201,7 @@
private void sendIconInfo() {
if (mContract != null && !mIconPosition.isEmpty()) {
- mContract.sendEndPosition(mIconPosition, mSurfaceView.getSurfaceControl());
+ mContract.sendEndPosition(mIconPosition, mLauncher, mSurfaceView.getSurfaceControl());
}
}