Loading src/com/android/launcher3/AppWidgetResizeFrame.java +1 −1 Original line number Diff line number Diff line Loading @@ -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, Loading src/com/android/launcher3/Launcher.java +1 −16 Original line number Diff line number Diff line Loading @@ -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 Loading tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java +15 −41 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); } 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")); } assertNotNull("Widget resize frame not shown after widget added", resizeFrame); resizeFrame.dismiss(); /** * 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); assertNotNull("Widget not found on the workspace", widget); } else { final Widget widget = mLauncher.getWorkspace().tryGetWidget(mWidgetInfo.label, DEFAULT_UI_TIMEOUT); assertNull("Widget unexpectedly found on the workspace", widget); } } Loading tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java +6 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading tests/tapl/com/android/launcher3/tapl/Widget.java +56 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } } Loading
src/com/android/launcher3/AppWidgetResizeFrame.java +1 −1 Original line number Diff line number Diff line Loading @@ -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, Loading
src/com/android/launcher3/Launcher.java +1 −16 Original line number Diff line number Diff line Loading @@ -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 Loading
tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java +15 −41 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); } 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")); } assertNotNull("Widget resize frame not shown after widget added", resizeFrame); resizeFrame.dismiss(); /** * 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); assertNotNull("Widget not found on the workspace", widget); } else { final Widget widget = mLauncher.getWorkspace().tryGetWidget(mWidgetInfo.label, DEFAULT_UI_TIMEOUT); assertNull("Widget unexpectedly found on the workspace", widget); } } Loading
tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java +6 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
tests/tapl/com/android/launcher3/tapl/Widget.java +56 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } }