Migrate OneHanded to WM shell (4/n)

Move OneHanded related codes, res and tests to WM shell.

Some tests add ignored currently due to permission issue.
Add another bug to trace it.

Also fix animation issue caused by wrong logic.

Bug: 161980408
Fix: 168074363
Test: manual check one handed function
Test: atest WMShellUnitTests
Test: atest SystemUITests
Test: make ArcSystemUI; make ArcSystemUITests
Test: make CarSystemUI; make CarSystemUITests
Change-Id: Ib25661d010278202ffe15fd9c4962e76e6698c21
This commit is contained in:
Tony Huang
2020-09-07 15:46:28 +08:00
parent 8be878f942
commit 1ed148d3e7
41 changed files with 290 additions and 317 deletions

View File

@@ -105,6 +105,7 @@ android_library {
static_libs: [
"protolog-lib",
"WindowManager-Shell-proto",
"androidx.appcompat_appcompat",
],
manifest: "AndroidManifest.xml",
}

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -29,4 +29,7 @@
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
<!-- Allow one handed to enable round corner -->
<bool name="config_one_handed_enable_round_corner">true</bool>
</resources>

View File

@@ -62,4 +62,8 @@
<dimen name="docked_divider_handle_width">16dp</dimen>
<dimen name="docked_divider_handle_height">2dp</dimen>
<!-- One-Handed Mode -->
<!-- Threshold for dragging distance to enable one-handed mode -->
<dimen name="gestures_onehanded_drag_threshold">20dp</dimen>
</resources>

View File

@@ -88,4 +88,9 @@
<string name="accessibility_action_divider_top_30">Top 30%</string>
<!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] -->
<string name="accessibility_action_divider_bottom_full">Bottom full screen</string>
<!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
<string name="one_handed_tutorial_title">Using one-handed mode</string>
<!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
<string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string>
</resources>

View File

@@ -14,11 +14,11 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import androidx.annotation.NonNull;
import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import java.io.PrintWriter;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.view.SurfaceControl;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.animation.Animator;
import android.animation.ValueAnimator;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -35,9 +35,9 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import java.io.PrintWriter;
@@ -390,7 +390,7 @@ public class OneHandedController implements OneHanded {
}
}
@androidx.annotation.VisibleForTesting
@VisibleForTesting
private void setEnabledGesturalOverlay(boolean enabled) {
try {
mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
import android.content.Context;
import android.graphics.Point;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEvent;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -38,7 +38,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.R;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
@@ -210,7 +210,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
displaySize.y);
mInputMonitor = InputManager.getInstance().monitorGestureInput(
"onehanded-gesture-offset", DEFAULT_DISPLAY);
mInputEventReceiver = new SysUiInputEventReceiver(
mInputEventReceiver = new EventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper());
}
}
@@ -227,8 +227,8 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
mRotation = toRotation;
}
private class SysUiInputEventReceiver extends InputEventReceiver {
SysUiInputEventReceiver(InputChannel channel, Looper looper) {
private class EventReceiver extends InputEventReceiver {
EventReceiver(InputChannel channel, Looper looper) {
super(channel, looper);
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.annotation.IntDef;
import android.content.ContentResolver;
@@ -22,8 +22,6 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.provider.Settings;
import com.android.systemui.dagger.SysUISingleton;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -31,7 +29,6 @@ import java.lang.annotation.RetentionPolicy;
/**
* APIs for querying or updating one handed settings .
*/
@SysUISingleton
public final class OneHandedSettingsUtil {
private static final String TAG = "OneHandedSettingsUtil";

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.view.SurfaceControl;
import com.android.systemui.R;
import com.android.wm.shell.R;
/**
* Abstracts the common operations on {@link SurfaceControl.Transaction} for OneHanded transition.

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.os.Handler;
import android.os.HandlerThread;

View File

@@ -14,9 +14,9 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import android.os.Handler;
import android.os.Looper;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -127,7 +127,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback {
if (mIsEnabled) {
mInputMonitor = InputManager.getInstance().monitorGestureInput(
"onehanded-touch", DEFAULT_DISPLAY);
mInputEventReceiver = new SysUiInputEventReceiver(
mInputEventReceiver = new EventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper());
}
}
@@ -150,8 +150,8 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback {
pw.println(mLastUpdatedBounds);
}
private class SysUiInputEventReceiver extends InputEventReceiver {
SysUiInputEventReceiver(InputChannel channel, Looper looper) {
private class EventReceiver extends InputEventReceiver {
EventReceiver(InputChannel channel, Looper looper) {
super(channel, looper);
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.graphics.Rect;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import android.content.ContentResolver;
import android.content.Context;
@@ -33,7 +33,7 @@ import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.android.systemui.R;
import com.android.wm.shell.R;
import java.io.PrintWriter;
@@ -79,7 +79,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
mTargetViewContainer.setClipChildren(false);
mTutorialAreaHeight = Math.round(mDisplaySize.y
* (SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f));
mTutorialView = LayoutInflater.from(context).inflate(R.xml.one_handed_tutorial, null);
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
mTargetViewContainer.addView(mTutorialView);
mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)

View File

@@ -25,6 +25,7 @@ android_test {
"androidx.test.ext.junit",
"mockito-target-extended-minus-junit4",
"truth-prebuilt",
"testables",
],
libs: [
"android.test.mock",

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static org.junit.Assert.assertNotNull;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static com.google.common.truth.Truth.assertThat;
@@ -112,10 +112,21 @@ public class OneHandedControllerTest extends OneHandedTestCase {
}
@Test
public void testRegisterTransitionCallback() {
verify(mMockDisplayAreaOrganizer, atLeastOnce()).registerTransitionCallback(any());
public void testRegisterTransitionCallbackAfterInit() {
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTouchHandler);
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockGestureHandler);
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTutorialHandler);
}
@Test
public void testRegisterTransitionCallback() {
OneHandedTransitionCallback callback = new OneHandedTransitionCallback() {};
mOneHandedController.registerTransitionCallback(callback);
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(callback);
}
@Test
public void testStopOneHanded_shouldRemoveTimer() {
mOneHandedController.stopOneHanded();
@@ -139,7 +150,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
}
@Ignore("b/161980408, fix it after migration finished")
@Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateTapAppToExit() {
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -148,7 +159,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
verify(mOneHandedController).setTaskChangeToExit(true);
}
@Ignore("b/161980408, fix it after migration finished")
@Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -157,7 +168,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
verify(mOneHandedController).setOneHandedEnabled(true);
}
@Ignore("b/161980408, fix it after migration finished")
@Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateTimeout() {
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -168,7 +179,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
}
@Ignore("b/161980408, fix it after migration finished")
@Ignore("b/167943723, refactor it and fix it")
@Test
public void tesSettingsObserver_updateSwipeToNotification() {
Settings.Secure.putInt(mContext.getContentResolver(),

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static org.junit.Assert.assertEquals;
@@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
@@ -34,7 +33,7 @@ import java.util.Collection;
@RunWith(Parameterized.class)
@SmallTest
public class OneHandedEventsTest extends SysuiTestCase {
public class OneHandedEventsTest extends OneHandedTestCase {
private UiEventLoggerFake mUiEventLogger;

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2020 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.wm.shell.onehanded;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedGestureHandlerTest extends OneHandedTestCase {
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
@Mock
DisplayController mMockDisplayController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
}
@Test
public void testSetGestureEventListener() {
OneHandedGestureHandler.OneHandedGestureEventCallback callback =
new OneHandedGestureHandler.OneHandedGestureEventCallback() {
@Override
public void onStart() {}
@Override
public void onStop() {}
};
mGestureHandler.setGestureEventListener(callback);
assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
}
@Ignore("b/167943723, refactor it and fix it")
@Test
public void testReceiveNewConfig_whenThreeButtonModeEnabled() {
mGestureHandler.onOneHandedEnabled(true);
mGestureHandler.onThreeButtonModeEnabled(true);
assertThat(mGestureHandler.mInputMonitor).isNotNull();
assertThat(mGestureHandler.mInputEventReceiver).isNotNull();
}
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
mGestureHandler.onOneHandedEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
}
@Test
public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
mGestureHandler.onOneHandedEnabled(true);
mGestureHandler.onThreeButtonModeEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
}
}

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
import static com.google.common.truth.Truth.assertThat;
@@ -59,24 +59,24 @@ public class OneHandedSettingsUtilTest extends OneHandedTestCase {
@Test
public void testRegisterSecureKeyObserver() {
final Uri result = OneHandedSettingsUtil.registerSettingsKeyObserver(
Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver);
Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver);
assertThat(result).isNotNull();
OneHandedSettingsUtil.registerSettingsKeyObserver(
Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver);
Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver);
}
@Test
public void testUnregisterSecureKeyObserver() {
OneHandedSettingsUtil.registerSettingsKeyObserver(
Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver);
Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver);
OneHandedSettingsUtil.unregisterSettingsKeyObserver(mContentResolver, mContentObserver);
assertThat(mOnChanged).isFalse();
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ONE_HANDED_MODE_ENABLED, 0);
Settings.Secure.TAPS_APP_TO_EXIT, 0);
assertThat(mOnChanged).isFalse();
}

View File

@@ -14,17 +14,21 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static com.android.systemui.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.SystemProperties;
import android.provider.Settings;
import com.android.systemui.SysuiTestCase;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
@@ -32,14 +36,26 @@ import org.junit.Before;
/**
* Base class that does One Handed specific setup.
*/
public abstract class OneHandedTestCase extends SysuiTestCase {
public abstract class OneHandedTestCase {
static boolean sOrigEnabled;
static boolean sOrigTapsAppToExitEnabled;
static int sOrigTimeout;
static boolean sOrigSwipeToNotification;
protected Context mContext;
@Before
public void setupSettings() {
final Context testContext =
InstrumentationRegistry.getInstrumentation().getTargetContext();
final DisplayManager dm = testContext.getSystemService(DisplayManager.class);
mContext = testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY));
InstrumentationRegistry
.getInstrumentation()
.getUiAutomation()
.adoptShellPermissionIdentity();
sOrigEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
getContext().getContentResolver());
sOrigTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
@@ -74,6 +90,15 @@ public abstract class OneHandedTestCase extends SysuiTestCase {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
sOrigSwipeToNotification ? 1 : 0);
InstrumentationRegistry
.getInstrumentation()
.getUiAutomation()
.dropShellPermissionIdentity();
}
protected Context getContext() {
return mContext;
}
}

View File

@@ -14,13 +14,13 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
import static com.android.systemui.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
import static com.android.wm.shell.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG;
import static com.google.common.truth.Truth.assertThat;

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2020 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.wm.shell.onehanded;
import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedTouchHandlerTest extends OneHandedTestCase {
OneHandedTouchHandler mTouchHandler;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
}
@Test
public void testRegisterTouchEventListener() {
OneHandedTouchHandler.OneHandedTouchEventCallback callback = () -> {
};
mTouchHandler.registerTouchEventListener(callback);
assertThat(mTouchHandler.mTouchEventCallback).isEqualTo(callback);
}
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
mTouchHandler.onOneHandedEnabled(false);
assertThat(mTouchHandler.mInputMonitor).isNull();
assertThat(mTouchHandler.mInputEventReceiver).isNull();
}
@Ignore("b/167943723, refactor it and fix it")
@Test
public void testOneHandedEnabled_monitorInputChannel() {
mTouchHandler.onOneHandedEnabled(true);
assertThat(mTouchHandler.mInputMonitor).isNotNull();
assertThat(mTouchHandler.mInputEventReceiver).isNotNull();
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.onehanded;
package com.android.wm.shell.onehanded;
import static org.mockito.Mockito.verify;
@@ -29,13 +29,13 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
@Mock
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
@@ -48,8 +48,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),

View File

@@ -560,9 +560,6 @@
<!-- If the config font scale is >= this value, potentially adjust the number of columns-->
<item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
<!-- Allow one handed to enable round corner -->
<bool name="config_one_handed_enable_round_corner">true</bool>
<!-- Show a separate icon for low and high volume on the volume dialog -->
<bool name="config_showLowMediaVolumeIcon">false</bool>
</resources>

View File

@@ -1366,8 +1366,4 @@
<dimen name="config_rounded_mask_size">@*android:dimen/rounded_corner_radius</dimen>
<dimen name="config_rounded_mask_size_top">@*android:dimen/rounded_corner_radius_top</dimen>
<dimen name="config_rounded_mask_size_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
<!-- One-Handed Mode -->
<!-- Threshold for dragging distance to enable one-handed mode -->
<dimen name="gestures_onehanded_drag_threshold">20dp</dimen>
</resources>

View File

@@ -2799,9 +2799,4 @@
<string name="udfps_hbm_enable_command" translatable="false"></string>
<!-- Device-specific payload for disabling the high-brightness mode -->
<string name="udfps_hbm_disable_command" translatable="false"></string>
<!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
<string name="one_handed_tutorial_title">Using one-handed mode</string>
<!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
<string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string>
</resources>

View File

@@ -75,8 +75,6 @@ import com.android.systemui.navigationbar.NavigationBar;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.onehanded.OneHandedEvents;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipAnimationController;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -93,6 +91,8 @@ import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEvents;
import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;

View File

@@ -38,10 +38,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.onehanded.OneHandedEvents;
import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -51,6 +47,10 @@ import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEvents;
import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.splitscreen.SplitScreen;
@@ -248,10 +248,9 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis,
int backDisposition, boolean showImeSwitcher) {
if (displayId != DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) == 0) {
return;
if (displayId == DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) != 0) {
oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
}
oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
}
});

View File

@@ -24,7 +24,6 @@ import android.view.IWindowManager;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipUiEventLogger;
@@ -36,6 +35,7 @@ import com.android.wm.shell.animation.FlingAnimationUtils;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.splitscreen.SplitScreen;
import dagger.BindsOptionalOf;

View File

@@ -24,8 +24,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.onehanded.OneHandedController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
@@ -40,6 +38,8 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;

View File

@@ -1,121 +0,0 @@
/*
* Copyright (C) 2020 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.systemui.onehanded;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedGestureHandlerTest extends OneHandedTestCase {
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = Mockito.spy(
new OneHandedGestureHandler(mContext, mMockDisplayController));
mOneHandedController = new OneHandedController(
getContext(),
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
mGestureHandler);
mOneHandedController.setThreeButtonModeEnabled(true);
}
@Test
public void testOneHandedManager_registerForDisplayAreaOrganizer() {
verify(mMockDisplayAreaOrganizer, atLeastOnce())
.registerTransitionCallback(mGestureHandler);
}
@Test
public void testOneHandedManager_setGestureEventListener() {
OneHandedGestureHandler.OneHandedGestureEventCallback callback =
new OneHandedGestureHandler.OneHandedGestureEventCallback() {
@Override
public void onStart() {}
@Override
public void onStop() {}
};
mOneHandedController.registerGestureCallback(callback);
verify(mGestureHandler).setGestureEventListener(callback);
assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
}
@Test
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
// 1st called at init
verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
}
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
mOneHandedController.setOneHandedEnabled(false);
mOneHandedController.setSwipeToNotificationEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
}
@Test
public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
// 1st called at init
verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
mGestureHandler.onThreeButtonModeEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) 2020 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.systemui.onehanded;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedTouchHandlerTest extends OneHandedTestCase {
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
mGestureHandler);
}
@Test
public void testOneHandedManager_registerForDisplayAreaOrganizer() {
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTouchHandler);
}
@Test
public void testOneHandedManager_registerTouchEventListener() {
verify(mTouchHandler).registerTouchEventListener(any());
assertThat(mTouchHandler.mTouchEventCallback).isNotNull();
}
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
mOneHandedController.setOneHandedEnabled(false);
assertThat(mTouchHandler.mInputMonitor).isNull();
assertThat(mTouchHandler.mInputEventReceiver).isNull();
}
@Test
public void testOneHandedEnabled_monitorInputChannel() {
mOneHandedController.setOneHandedEnabled(true);
assertThat(mTouchHandler.mInputMonitor).isNotNull();
assertThat(mTouchHandler.mInputEventReceiver).isNotNull();
}
@Test
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
// Called at init
verify(mTouchHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// Called by setOneHandedEnabled()
verify(mTouchHandler, atLeast(2)).onOneHandedEnabled(true);
}
}

View File

@@ -30,15 +30,15 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.onehanded.OneHandedGestureHandler;
import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedGestureHandler;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;