Merge "Fix NPE of handling ACTION_MOVE in StatusBarTouchController and added unit test" into udc-dev am: 3dca7b3c6a
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/23300979 Change-Id: Ic563b3f997f85fc8a4736be07ed1eacf73e132e3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
+12
-9
@@ -30,6 +30,8 @@ import android.view.ViewConfiguration;
|
|||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.launcher3.AbstractFloatingView;
|
import com.android.launcher3.AbstractFloatingView;
|
||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
@@ -50,12 +52,13 @@ public class StatusBarTouchController implements TouchController {
|
|||||||
|
|
||||||
private final Launcher mLauncher;
|
private final Launcher mLauncher;
|
||||||
private final SystemUiProxy mSystemUiProxy;
|
private final SystemUiProxy mSystemUiProxy;
|
||||||
private final float mTouchSlop;
|
@VisibleForTesting final float mTouchSlop;
|
||||||
private int mLastAction;
|
private int mLastAction;
|
||||||
private final SparseArray<PointF> mDownEvents;
|
private final SparseArray<PointF> mDownEvents;
|
||||||
|
|
||||||
/* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/
|
/* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/
|
||||||
private boolean mCanIntercept;
|
@VisibleForTesting
|
||||||
|
boolean mCanIntercept;
|
||||||
|
|
||||||
public StatusBarTouchController(Launcher l) {
|
public StatusBarTouchController(Launcher l) {
|
||||||
mLauncher = l;
|
mLauncher = l;
|
||||||
@@ -82,9 +85,9 @@ public class StatusBarTouchController implements TouchController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||||
int action = ev.getActionMasked();
|
final int action = ev.getActionMasked();
|
||||||
int idx = ev.getActionIndex();
|
final int idx = ev.getActionIndex();
|
||||||
int pid = ev.getPointerId(idx);
|
final int pid = ev.getPointerId(idx);
|
||||||
if (action == ACTION_DOWN) {
|
if (action == ACTION_DOWN) {
|
||||||
mCanIntercept = canInterceptTouch(ev);
|
mCanIntercept = canInterceptTouch(ev);
|
||||||
if (!mCanIntercept) {
|
if (!mCanIntercept) {
|
||||||
@@ -92,14 +95,14 @@ public class StatusBarTouchController implements TouchController {
|
|||||||
}
|
}
|
||||||
mDownEvents.clear();
|
mDownEvents.clear();
|
||||||
mDownEvents.put(pid, new PointF(ev.getX(), ev.getY()));
|
mDownEvents.put(pid, new PointF(ev.getX(), ev.getY()));
|
||||||
} else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
|
} else if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
// Check!! should only set it only when threshold is not entered.
|
// Check!! should only set it only when threshold is not entered.
|
||||||
mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx)));
|
mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx)));
|
||||||
}
|
}
|
||||||
if (!mCanIntercept) {
|
if (!mCanIntercept) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (action == ACTION_MOVE) {
|
if (action == ACTION_MOVE && mDownEvents.contains(pid)) {
|
||||||
float dy = ev.getY(idx) - mDownEvents.get(pid).y;
|
float dy = ev.getY(idx) - mDownEvents.get(pid).y;
|
||||||
float dx = ev.getX(idx) - mDownEvents.get(pid).x;
|
float dx = ev.getX(idx) - mDownEvents.get(pid).x;
|
||||||
// Currently input dispatcher will not do touch transfer if there are more than
|
// Currently input dispatcher will not do touch transfer if there are more than
|
||||||
@@ -126,7 +129,6 @@ public class StatusBarTouchController implements TouchController {
|
|||||||
mLauncher.getStatsLogManager().logger()
|
mLauncher.getStatsLogManager().logger()
|
||||||
.log(LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN);
|
.log(LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN);
|
||||||
setWindowSlippery(false);
|
setWindowSlippery(false);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -140,7 +142,8 @@ public class StatusBarTouchController implements TouchController {
|
|||||||
* Touches can slide out of the window but they cannot necessarily slide
|
* Touches can slide out of the window but they cannot necessarily slide
|
||||||
* back in (unless the other window with touch focus permits it).
|
* back in (unless the other window with touch focus permits it).
|
||||||
*/
|
*/
|
||||||
private void setWindowSlippery(boolean enable) {
|
@VisibleForTesting
|
||||||
|
void setWindowSlippery(boolean enable) {
|
||||||
Window w = mLauncher.getWindow();
|
Window w = mLauncher.getWindow();
|
||||||
WindowManager.LayoutParams wlp = w.getAttributes();
|
WindowManager.LayoutParams wlp = w.getAttributes();
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
|||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 202 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.launcher3.uioverrides.touchcontrollers
|
||||||
|
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import androidx.test.runner.AndroidJUnit4
|
||||||
|
import com.android.launcher3.Launcher
|
||||||
|
import com.android.launcher3.ui.AbstractLauncherUiTest
|
||||||
|
import com.android.launcher3.ui.TaplTestsLauncher3
|
||||||
|
import junit.framework.Assert.assertEquals
|
||||||
|
import junit.framework.Assert.assertFalse
|
||||||
|
import junit.framework.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class StatusBarTouchControllerTest : AbstractLauncherUiTest() {
|
||||||
|
@Before
|
||||||
|
@Throws(Exception::class)
|
||||||
|
fun setup() {
|
||||||
|
TaplTestsLauncher3.initialize(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun interceptActionDown_canIntercept() {
|
||||||
|
executeOnLauncher { launcher: Launcher? ->
|
||||||
|
val underTest = StatusBarTouchController(launcher)
|
||||||
|
assertFalse(underTest.mCanIntercept)
|
||||||
|
val downEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||||
|
|
||||||
|
underTest.onControllerInterceptTouchEvent(downEvent)
|
||||||
|
|
||||||
|
assertTrue(underTest.mCanIntercept)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun interceptActionMove_handledAndSetSlippery() {
|
||||||
|
executeOnLauncher { launcher: Launcher ->
|
||||||
|
val underTest = StatusBarTouchController(launcher)
|
||||||
|
val downEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||||
|
underTest.onControllerInterceptTouchEvent(downEvent)
|
||||||
|
val w = launcher.window
|
||||||
|
assertEquals(0, w.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY)
|
||||||
|
val moveEvent =
|
||||||
|
MotionEvent.obtain(
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
MotionEvent.ACTION_MOVE,
|
||||||
|
underTest.mTouchSlop,
|
||||||
|
underTest.mTouchSlop + 10,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
val handled = underTest.onControllerInterceptTouchEvent(moveEvent)
|
||||||
|
|
||||||
|
assertTrue(handled)
|
||||||
|
assertEquals(
|
||||||
|
WindowManager.LayoutParams.FLAG_SLIPPERY,
|
||||||
|
w.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun interceptActionMove_not_handled() {
|
||||||
|
executeOnLauncher { launcher: Launcher? ->
|
||||||
|
val underTest = StatusBarTouchController(launcher)
|
||||||
|
val downEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||||
|
underTest.onControllerInterceptTouchEvent(downEvent)
|
||||||
|
val moveEvent =
|
||||||
|
MotionEvent.obtain(
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
MotionEvent.ACTION_MOVE,
|
||||||
|
underTest.mTouchSlop + 10,
|
||||||
|
underTest.mTouchSlop,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
val handled = underTest.onControllerInterceptTouchEvent(moveEvent)
|
||||||
|
|
||||||
|
assertFalse(handled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun interceptActionMoveAsFirstGestureEvent_notCrashedNorHandled() {
|
||||||
|
executeOnLauncher { launcher: Launcher? ->
|
||||||
|
val underTest = StatusBarTouchController(launcher)
|
||||||
|
underTest.mCanIntercept = true
|
||||||
|
val moveEvent = MotionEvent.obtain(2, 2, MotionEvent.ACTION_MOVE, 10f, 10f, 0)
|
||||||
|
|
||||||
|
val handled = underTest.onControllerInterceptTouchEvent(moveEvent)
|
||||||
|
|
||||||
|
assertFalse(handled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleActionUp_setNotSlippery() {
|
||||||
|
executeOnLauncher { launcher: Launcher ->
|
||||||
|
val underTest = StatusBarTouchController(launcher)
|
||||||
|
underTest.mCanIntercept = true
|
||||||
|
underTest.setWindowSlippery(true)
|
||||||
|
val moveEvent = MotionEvent.obtain(2, 2, MotionEvent.ACTION_UP, 10f, 10f, 0)
|
||||||
|
|
||||||
|
val handled = underTest.onControllerTouchEvent(moveEvent)
|
||||||
|
|
||||||
|
assertTrue(handled)
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
launcher.window.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleActionCancel_setNotSlippery() {
|
||||||
|
executeOnLauncher { launcher: Launcher ->
|
||||||
|
val underTest = StatusBarTouchController(launcher)
|
||||||
|
underTest.mCanIntercept = true
|
||||||
|
underTest.setWindowSlippery(true)
|
||||||
|
val moveEvent = MotionEvent.obtain(2, 2, MotionEvent.ACTION_CANCEL, 10f, 10f, 0)
|
||||||
|
|
||||||
|
val handled = underTest.onControllerTouchEvent(moveEvent)
|
||||||
|
|
||||||
|
assertTrue(handled)
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
launcher.window.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user