Fix bug with resize frame in Launcher3.

Also updated the tests to check that the resize frame is shown.

Bug: 192655785
Test: AddWidgetTest, AddConfigWidgetTest, manual
Change-Id: Id348f39cec1bebc8ec9ea9f3068f4bda2159eac4
This commit is contained in:
Yogisha Dixit 2021-10-14 13:06:40 +01:00
parent 20c05fbd4c
commit 7b1d25b251
6 changed files with 116 additions and 62 deletions

View File

@ -215,7 +215,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
dl.addView(frame);
frame.mIsOpen = true;
frame.snapToWidget(false);
frame.post(() -> frame.snapToWidget(false));
}
private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,

View File

@ -1391,22 +1391,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
final LauncherAppWidgetHostView launcherHostView = (LauncherAppWidgetHostView) hostView;
CellLayout cellLayout = getCellLayout(launcherInfo.container, launcherInfo.screenId);
if (mStateManager.getState() == NORMAL) {
// Show resize frame once the widget layout is drawn.
View.OnLayoutChangeListener onLayoutChangeListener =
new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight,
int oldBottom) {
AppWidgetResizeFrame.showForWidget(launcherHostView, cellLayout);
launcherHostView.removeOnLayoutChangeListener(this);
}
};
launcherHostView.addOnLayoutChangeListener(onLayoutChangeListener);
// There is a small chance that the layout was already drawn before the layout
// change listener was registered, which means that the resize frame wouldn't be
// shown. Directly call requestLayout to force a layout change.
launcherHostView.requestLayout();
} else {
mStateManager.addStateListener(new StateManager.StateListener<LauncherState>() {
@Override

View File

@ -15,28 +15,24 @@
*/
package com.android.launcher3.ui.widget;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.view.View;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.testcomponent.WidgetConfigActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait.Condition;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@ -92,48 +88,26 @@ public class AddConfigWidgetTest extends AbstractLauncherUiTest {
// Drag widget to homescreen
WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor();
WidgetResizeFrame resizeFrame =
widgets.getWidget(mWidgetInfo.getLabel(mTargetContext.getPackageManager()))
.dragToWorkspace(true, false);
.dragConfigWidgetToWorkspace(acceptConfig);
// Widget id for which the config activity was opened
mWidgetId = monitor.getWidgetId();
// Verify that the widget id is valid and bound
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
setResult(acceptConfig);
if (acceptConfig) {
// TODO(b/192655785) Assert widget resize frame is shown and then dismiss it.
Wait.atMost("", new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
assertNotNull("Widget resize frame not shown after widget added", resizeFrame);
resizeFrame.dismiss();
final Widget widget =
mLauncher.getWorkspace().tryGetWidget(mWidgetInfo.label, DEFAULT_UI_TIMEOUT);
assertNotNull("Widget not found on the workspace", widget);
} else {
// Verify that the widget id is deleted.
Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null,
DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
}
}
private void setResult(boolean success) {
getInstrumentation().getTargetContext().sendBroadcast(
WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
success ? "clickOK" : "clickCancel"));
}
/**
* Condition for searching widget id
*/
private class WidgetSearchCondition implements Condition, ItemOperator {
@Override
public boolean isTrue() throws Throwable {
return mMainThreadExecutor.submit(mActivityMonitor.itemExists(this)).get();
}
@Override
public boolean evaluate(ItemInfo info, View view) {
return info instanceof LauncherAppWidgetInfo &&
((LauncherAppWidgetInfo) info).providerName.getClassName().equals(
mWidgetInfo.provider.getClassName()) &&
((LauncherAppWidgetInfo) info).appWidgetId == mWidgetId;
final Widget widget =
mLauncher.getWorkspace().tryGetWidget(mWidgetInfo.label, DEFAULT_UI_TIMEOUT);
assertNull("Widget unexpectedly found on the workspace", widget);
}
}

View File

@ -25,6 +25,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ShellCommandRule;
@ -53,19 +54,20 @@ public class AddWidgetTest extends AbstractLauncherUiTest {
final LauncherAppWidgetProviderInfo widgetInfo =
TestViewHelpers.findWidgetProvider(this, false /* hasConfigureScreen */);
mLauncher.
WidgetResizeFrame resizeFrame = mLauncher.
getWorkspace().
openAllWidgets().
getWidget(widgetInfo.getLabel(mTargetContext.getPackageManager())).
dragToWorkspace(false, false);
// Dismiss widget resize frame.
mDevice.pressHome();
dragWidgetToWorkspace();
assertTrue(mActivityMonitor.itemExists(
(info, view) -> info instanceof LauncherAppWidgetInfo &&
((LauncherAppWidgetInfo) info).providerName.getClassName().equals(
widgetInfo.provider.getClassName())).call());
assertNotNull("Widget resize frame not shown after widget add", resizeFrame);
resizeFrame.dismiss();
final Widget widget = mLauncher.getWorkspace().tryGetWidget(widgetInfo.label,
DEFAULT_UI_TIMEOUT);
assertNotNull("Widget not found on the workspace", widget);

View File

@ -16,7 +16,12 @@
package com.android.launcher3.tapl;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import com.android.launcher3.testing.TestProtocol;
@ -51,4 +56,55 @@ public final class Widget extends Launchable {
protected String launchableType() {
return "widget";
}
/**
* Drags a non-configurable widget from the widgets container to the workspace and returns the
* resize frame that is shown after the widget is added.
*/
@NonNull
public WidgetResizeFrame dragWidgetToWorkspace() {
return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false);
}
/**
* Drags a configurable widget from the widgets container to the workspace, either accepts or
* cancels the configuration based on {@code acceptsConfig}, and returns the resize frame that
* is shown if the widget is added.
*/
@Nullable
public WidgetResizeFrame dragConfigWidgetToWorkspace(boolean acceptsConfig) {
return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig);
}
/**
* Drags a widget from the widgets container to the workspace and returns the resize frame that
* is shown after the widget is added.
*
* <p> If {@code configurable} is true, then either accepts or cancels the configuration based
* on {@code acceptsConfig}.
*/
@Nullable
private WidgetResizeFrame dragWidgetToWorkspace(
boolean configurable, boolean acceptsConfig) {
dragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */ false);
if (configurable) {
// Configure the widget.
BySelector selector = By.text(acceptsConfig ? "OK" : "Cancel");
mLauncher.getDevice()
.wait(Until.findObject(selector), LauncherInstrumentation.WAIT_TIME_MS)
.click();
// If the widget configuration was cancelled, then the widget wasn't added to the home
// screen. In that case, we cannot return a resize frame.
if (!acceptsConfig) {
return null;
}
}
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get widget resize frame")) {
return new WidgetResizeFrame(mLauncher);
}
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2021 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.tapl;
/** The resize frame that is shown for a widget on the workspace. */
public class WidgetResizeFrame {
private final LauncherInstrumentation mLauncher;
WidgetResizeFrame(LauncherInstrumentation launcher) {
mLauncher = launcher;
launcher.waitForLauncherObject("widget_resize_frame");
}
/** Dismisses the resize frame. */
public void dismiss() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to dismiss widget resize frame")) {
// Dismiss the resize frame by pressing the home button.
mLauncher.getDevice().pressHome();
}
}
}