Merge "Migrating widgets tests off TAPL" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
e38be8df37
@@ -63,7 +63,6 @@ filegroup {
|
||||
"src/com/android/launcher3/dragging/TaplDragTest.java",
|
||||
"src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java",
|
||||
"src/com/android/launcher3/ui/TaplTestsLauncher3Test.java",
|
||||
"src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java",
|
||||
"src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -21,11 +21,8 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Process;
|
||||
import android.system.OsConstants;
|
||||
import android.util.Log;
|
||||
@@ -53,7 +50,6 @@ import org.junit.rules.TestRule;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
@@ -216,38 +212,6 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher>
|
||||
}, mLauncher, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast receiver which blocks until the result is received.
|
||||
*/
|
||||
public class BlockingBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private Intent mIntent;
|
||||
|
||||
public BlockingBroadcastReceiver(String action) {
|
||||
mTargetContext.registerReceiver(this, new IntentFilter(action),
|
||||
Context.RECEIVER_EXPORTED/*UNAUDITED*/);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
mIntent = intent;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
public Intent blockingGetIntent() throws InterruptedException {
|
||||
assertTrue("Timed Out", latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS));
|
||||
mTargetContext.unregisterReceiver(this);
|
||||
return mIntent;
|
||||
}
|
||||
|
||||
public Intent blockingGetExtraIntent() throws InterruptedException {
|
||||
Intent intent = blockingGetIntent();
|
||||
return intent == null ? null : (Intent) intent.getParcelableExtra(
|
||||
Intent.EXTRA_INTENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static void startAppFast(String packageName) {
|
||||
startIntent(
|
||||
getInstrumentation().getContext().getPackageManager().getLaunchIntentForPackage(
|
||||
|
||||
+66
-51
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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
|
||||
* 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
|
||||
* 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.
|
||||
* 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.ui.widget;
|
||||
|
||||
@@ -24,23 +24,34 @@ import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Process;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.celllayout.FavoriteItemsTransaction;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.testcomponent.WidgetConfigActivity;
|
||||
import com.android.launcher3.ui.AbstractLauncherUiTest;
|
||||
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
|
||||
import com.android.launcher3.ui.TestViewHelpers;
|
||||
import com.android.launcher3.util.BaseLauncherActivityTest;
|
||||
import com.android.launcher3.util.BlockingBroadcastReceiver;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.Wait;
|
||||
import com.android.launcher3.util.rule.ShellCommandRule;
|
||||
import com.android.launcher3.views.OptionsPopupView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.PendingAddWidgetInfo;
|
||||
import com.android.launcher3.widget.WidgetCell;
|
||||
import com.android.launcher3.widget.picker.WidgetsFullSheet;
|
||||
import com.android.launcher3.widget.picker.WidgetsListAdapter;
|
||||
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -52,7 +63,7 @@ import org.junit.runner.RunWith;
|
||||
*/
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
public class AddConfigWidgetTest extends BaseLauncherActivityTest<Launcher> {
|
||||
|
||||
@Rule
|
||||
public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
|
||||
@@ -62,12 +73,10 @@ public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
|
||||
private int mWidgetId;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mWidgetInfo = TestViewHelpers.findWidgetProvider(true /* hasConfigureScreen */);
|
||||
mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
|
||||
mAppWidgetManager = AppWidgetManager.getInstance(targetContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,80 +91,86 @@ public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
runTest(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param acceptConfig accept the config activity
|
||||
*/
|
||||
private void runTest(boolean acceptConfig) throws Throwable {
|
||||
commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
|
||||
new FavoriteItemsTransaction(targetContext()).commit();
|
||||
loadLauncherSync();
|
||||
|
||||
// Drag widget to homescreen
|
||||
// Add widget to homescreen
|
||||
WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor();
|
||||
mLauncher.getWorkspace()
|
||||
.openAllWidgets()
|
||||
.getWidget(mWidgetInfo.getLabel())
|
||||
.dragToWorkspace(true, false);
|
||||
executeOnLauncher(OptionsPopupView::openWidgets);
|
||||
uiDevice.waitForIdle();
|
||||
|
||||
// Select the widget header
|
||||
Context testContext = getInstrumentation().getContext();
|
||||
String packageName = testContext.getPackageName();
|
||||
executeOnLauncher(l -> {
|
||||
WidgetsRecyclerView wrv = WidgetsFullSheet.getWidgetsView(l);
|
||||
WidgetsListAdapter adapter = (WidgetsListAdapter) wrv.getAdapter();
|
||||
int pos = adapter.getItems().indexOf(
|
||||
adapter.getItems().stream()
|
||||
.filter(entry -> packageName.equals(entry.mPkgItem.packageName))
|
||||
.findFirst()
|
||||
.get());
|
||||
wrv.getLayoutManager().scrollToPosition(pos);
|
||||
adapter.onHeaderClicked(true, new PackageUserKey(packageName, Process.myUserHandle()));
|
||||
});
|
||||
uiDevice.waitForIdle();
|
||||
|
||||
View widgetView = getOnceNotNull("Widget not found", l -> searchView(l.getDragLayer(), v ->
|
||||
v instanceof WidgetCell
|
||||
&& v.getTag() instanceof PendingAddWidgetInfo pawi
|
||||
&& mWidgetInfo.provider.equals(pawi.componentName)));
|
||||
addToWorkspace(widgetView);
|
||||
|
||||
// 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);
|
||||
|
||||
setResultAndWaitForAnimation(acceptConfig);
|
||||
if (acceptConfig) {
|
||||
Wait.atMost("", new WidgetSearchCondition(), mLauncher);
|
||||
getOnceNotNull("Widget was not added", l -> {
|
||||
// Close the resize frame before searching for widget
|
||||
AbstractFloatingView.closeAllOpenViews(l);
|
||||
return l.getWorkspace().getFirstMatch(new WidgetSearchCondition());
|
||||
});
|
||||
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
|
||||
} else {
|
||||
// Verify that the widget id is deleted.
|
||||
Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null,
|
||||
mLauncher);
|
||||
Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setResult(boolean success) {
|
||||
private void setResult(boolean success) {
|
||||
getInstrumentation().getTargetContext().sendBroadcast(
|
||||
WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
|
||||
success ? "clickOK" : "clickCancel"));
|
||||
}
|
||||
|
||||
private void setResultAndWaitForAnimation(boolean success) {
|
||||
if (mLauncher.isLauncher3()) {
|
||||
setResult(success);
|
||||
} else {
|
||||
mLauncher.executeAndWaitForWallpaperAnimation(
|
||||
() -> setResult(success),
|
||||
"setting widget coinfig result");
|
||||
}
|
||||
uiDevice.waitForIdle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition for searching widget id
|
||||
*/
|
||||
private class WidgetSearchCondition implements Wait.Condition, ItemOperator {
|
||||
|
||||
@Override
|
||||
public boolean isTrue() throws Throwable {
|
||||
return mMainThreadExecutor.submit(() -> {
|
||||
Launcher l = Launcher.ACTIVITY_TRACKER.getCreatedContext();
|
||||
return l != null && l.getWorkspace().getFirstMatch(this) != null;
|
||||
}).get();
|
||||
}
|
||||
private class WidgetSearchCondition implements ItemOperator {
|
||||
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View view) {
|
||||
return info instanceof LauncherAppWidgetInfo
|
||||
&& ((LauncherAppWidgetInfo) info).providerName.getClassName().equals(
|
||||
mWidgetInfo.provider.getClassName())
|
||||
&& ((LauncherAppWidgetInfo) info).appWidgetId == mWidgetId;
|
||||
return info instanceof LauncherAppWidgetInfo lawi
|
||||
&& lawi.providerName.equals(mWidgetInfo.provider)
|
||||
&& lawi.appWidgetId == mWidgetId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast receiver for receiving widget config activity status.
|
||||
*/
|
||||
private class WidgetConfigStartupMonitor extends BlockingBroadcastReceiver {
|
||||
private static class WidgetConfigStartupMonitor extends BlockingBroadcastReceiver {
|
||||
|
||||
public WidgetConfigStartupMonitor() {
|
||||
WidgetConfigStartupMonitor() {
|
||||
super(WidgetConfigActivity.class.getName());
|
||||
}
|
||||
|
||||
+52
-43
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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
|
||||
* 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
|
||||
* 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.
|
||||
* 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.ui.widget;
|
||||
|
||||
@@ -22,12 +22,12 @@ import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_PROVID
|
||||
import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
|
||||
import static com.android.launcher3.provider.LauncherDbUtils.itemIdMatch;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.TestUtil.getOnUiThread;
|
||||
import static com.android.launcher3.util.Wait.atMost;
|
||||
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
@@ -36,6 +36,7 @@ import android.content.pm.PackageInstaller.SessionParams;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
@@ -49,13 +50,12 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.celllayout.FavoriteItemsTransaction;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
import com.android.launcher3.tapl.Widget;
|
||||
import com.android.launcher3.tapl.Workspace;
|
||||
import com.android.launcher3.ui.AbstractLauncherUiTest;
|
||||
import com.android.launcher3.ui.TestViewHelpers;
|
||||
import com.android.launcher3.util.TestUtil;
|
||||
import com.android.launcher3.util.BaseLauncherActivityTest;
|
||||
import com.android.launcher3.util.rule.ShellCommandRule;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.PendingAppWidgetHostView;
|
||||
import com.android.launcher3.widget.WidgetManagerHelper;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -67,6 +67,7 @@ import org.junit.runner.RunWith;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Tests for bind widget flow.
|
||||
@@ -75,7 +76,7 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
public class BindWidgetTest extends BaseLauncherActivityTest<Launcher> {
|
||||
|
||||
@Rule
|
||||
public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
|
||||
@@ -87,11 +88,9 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
|
||||
private LauncherModel mModel;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mModel = LauncherAppState.getInstance(mTargetContext).getModel();
|
||||
mModel = LauncherAppState.getInstance(targetContext()).getModel();
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -101,7 +100,7 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
}
|
||||
|
||||
if (mSessionId > -1) {
|
||||
mTargetContext.getPackageManager().getPackageInstaller().abandonSession(mSessionId);
|
||||
targetContext().getPackageManager().getPackageInstaller().abandonSession(mSessionId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,13 +121,12 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
LauncherAppWidgetProviderInfo info = addWidgetToScreen(false, false,
|
||||
item -> item.appWidgetId = -33);
|
||||
|
||||
final Workspace workspace = mLauncher.getWorkspace();
|
||||
// Item deleted from db
|
||||
mCursor = queryItem();
|
||||
assertEquals(0, mCursor.getCount());
|
||||
|
||||
// The view does not exist
|
||||
assertTrue("Widget exists", workspace.tryGetWidget(info.label, 0) == null);
|
||||
verifyItemEventuallyNull("Widget exists", widgetProvider(info));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,18 +152,19 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
// Widget has a valid Id now.
|
||||
assertEquals(0, mCursor.getInt(mCursor.getColumnIndex(LauncherSettings.Favorites.RESTORED))
|
||||
& FLAG_ID_NOT_VALID);
|
||||
assertNotNull(AppWidgetManager.getInstance(mTargetContext)
|
||||
assertNotNull(AppWidgetManager.getInstance(targetContext())
|
||||
.getAppWidgetInfo(mCursor.getInt(mCursor.getColumnIndex(
|
||||
LauncherSettings.Favorites.APPWIDGET_ID))));
|
||||
|
||||
// send OPTION_APPWIDGET_RESTORE_COMPLETED
|
||||
int appWidgetId = mCursor.getInt(
|
||||
mCursor.getColumnIndex(LauncherSettings.Favorites.APPWIDGET_ID));
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mTargetContext);
|
||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(targetContext());
|
||||
|
||||
Bundle b = new Bundle();
|
||||
b.putBoolean(WidgetManagerHelper.WIDGET_OPTION_RESTORE_COMPLETED, true);
|
||||
RemoteViews remoteViews = new RemoteViews(mTargetPackage, R.layout.appwidget_not_ready);
|
||||
RemoteViews remoteViews = new RemoteViews(
|
||||
targetContext().getPackageName(), R.layout.appwidget_not_ready);
|
||||
appWidgetManager.updateAppWidgetOptions(appWidgetId, b);
|
||||
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
|
||||
|
||||
@@ -175,15 +174,14 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
WidgetManagerHelper.WIDGET_OPTION_RESTORE_COMPLETED));
|
||||
executeOnLauncher(l -> l.getAppWidgetHolder().startListening());
|
||||
verifyWidgetPresent(info);
|
||||
assertNull(mLauncher.getWorkspace().tryGetPendingWidget(100));
|
||||
verifyItemEventuallyNull("Pending widget exists", pendingWidgetProvider());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPendingWidget_notRestored_removed() {
|
||||
addPendingItemToScreen(getInvalidWidgetInfo(), FLAG_ID_NOT_VALID | FLAG_PROVIDER_NOT_READY);
|
||||
|
||||
assertTrue("Pending widget exists",
|
||||
mLauncher.getWorkspace().tryGetPendingWidget(0) == null);
|
||||
verifyItemEventuallyNull("Pending widget exists", pendingWidgetProvider());
|
||||
// Item deleted from db
|
||||
mCursor = queryItem();
|
||||
assertEquals(0, mCursor.getCount());
|
||||
@@ -216,7 +214,7 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
// Create an active installer session
|
||||
SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
|
||||
params.setAppPackageName(item.providerName.getPackageName());
|
||||
PackageInstaller installer = mTargetContext.getPackageManager().getPackageInstaller();
|
||||
PackageInstaller installer = targetContext().getPackageManager().getPackageInstaller();
|
||||
mSessionId = installer.createSession(params);
|
||||
|
||||
addPendingItemToScreen(item, FLAG_ID_NOT_VALID | FLAG_PROVIDER_NOT_READY);
|
||||
@@ -234,36 +232,47 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
}
|
||||
|
||||
private void verifyWidgetPresent(LauncherAppWidgetProviderInfo info) {
|
||||
final Widget widget = mLauncher.getWorkspace().tryGetWidget(info.label,
|
||||
TestUtil.DEFAULT_UI_TIMEOUT);
|
||||
assertTrue("Widget is not present",
|
||||
widget != null);
|
||||
getOnceNotNull("Widget is not present", widgetProvider(info));
|
||||
}
|
||||
|
||||
private void verifyPendingWidgetPresent() {
|
||||
final Widget widget = mLauncher.getWorkspace().tryGetPendingWidget(
|
||||
TestUtil.DEFAULT_UI_TIMEOUT);
|
||||
assertTrue("Pending widget is not present",
|
||||
widget != null);
|
||||
getOnceNotNull("Widget is not present", pendingWidgetProvider());
|
||||
}
|
||||
|
||||
private Function<Launcher, Object> pendingWidgetProvider() {
|
||||
return l -> l.getWorkspace().getFirstMatch(
|
||||
(item, view) -> view instanceof PendingAppWidgetHostView);
|
||||
}
|
||||
|
||||
private Function<Launcher, Object> widgetProvider(LauncherAppWidgetProviderInfo info) {
|
||||
return l -> l.getWorkspace().getFirstMatch((item, view) ->
|
||||
view instanceof LauncherAppWidgetHostView
|
||||
&& TextUtils.equals(info.label, view.getContentDescription()));
|
||||
}
|
||||
|
||||
private void verifyItemEventuallyNull(String message, Function<Launcher, Object> provider) {
|
||||
atMost(message, () -> getFromLauncher(provider) == null);
|
||||
}
|
||||
|
||||
private void addPendingItemToScreen(LauncherAppWidgetInfo item, int restoreStatus) {
|
||||
item.restoreStatus = restoreStatus;
|
||||
item.screenId = FIRST_SCREEN_ID;
|
||||
commitTransactionAndLoadHome(
|
||||
new FavoriteItemsTransaction(mTargetContext).addItem(() -> item));
|
||||
new FavoriteItemsTransaction(targetContext()).addItem(() -> item).commit();
|
||||
loadLauncherSync();
|
||||
}
|
||||
|
||||
private LauncherAppWidgetProviderInfo addWidgetToScreen(boolean hasConfigureScreen,
|
||||
boolean bindWidget, Consumer<LauncherAppWidgetInfo> itemOverride) {
|
||||
LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(hasConfigureScreen);
|
||||
commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext)
|
||||
new FavoriteItemsTransaction(targetContext())
|
||||
.addItem(() -> {
|
||||
LauncherAppWidgetInfo item = createWidgetInfo(info, mTargetContext, bindWidget);
|
||||
LauncherAppWidgetInfo item =
|
||||
createWidgetInfo(info, targetContext(), bindWidget);
|
||||
item.screenId = FIRST_SCREEN_ID;
|
||||
itemOverride.accept(item);
|
||||
return item;
|
||||
}));
|
||||
}).commit();
|
||||
loadLauncherSync();
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -277,13 +286,13 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
|
||||
|
||||
Set<String> activePackage = getOnUiThread(() -> {
|
||||
Set<String> packages = new HashSet<>();
|
||||
InstallSessionHelper.INSTANCE.get(mTargetContext).getActiveSessions()
|
||||
InstallSessionHelper.INSTANCE.get(targetContext()).getActiveSessions()
|
||||
.keySet().forEach(packageUserKey -> packages.add(packageUserKey.mPackageName));
|
||||
return packages;
|
||||
});
|
||||
while (true) {
|
||||
try {
|
||||
mTargetContext.getPackageManager().getPackageInfo(
|
||||
targetContext().getPackageManager().getPackageInfo(
|
||||
pkg, PackageManager.GET_UNINSTALLED_PACKAGES);
|
||||
} catch (Exception e) {
|
||||
if (!activePackage.contains(pkg)) {
|
||||
+54
-64
@@ -1,34 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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
|
||||
* 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
|
||||
* 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.
|
||||
* 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.ui.widget;
|
||||
|
||||
import static android.app.PendingIntent.FLAG_MUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_ONE_SHOT;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
import androidx.test.uiautomator.By;
|
||||
import androidx.test.uiautomator.BySelector;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
@@ -37,14 +44,13 @@ import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.tapl.AddToHomeScreenPrompt;
|
||||
import com.android.launcher3.testcomponent.AppWidgetNoConfig;
|
||||
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
|
||||
import com.android.launcher3.testcomponent.RequestPinItemActivity;
|
||||
import com.android.launcher3.ui.AbstractLauncherUiTest;
|
||||
import com.android.launcher3.util.BaseLauncherActivityTest;
|
||||
import com.android.launcher3.util.BlockingBroadcastReceiver;
|
||||
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.TestUtil;
|
||||
import com.android.launcher3.util.rule.ShellCommandRule;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -53,25 +59,27 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Test to verify pin item request flow.
|
||||
*/
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
|
||||
public class RequestPinItemTest extends BaseLauncherActivityTest<Launcher> {
|
||||
|
||||
@Rule
|
||||
public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
|
||||
|
||||
@Rule
|
||||
public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
|
||||
|
||||
private String mCallbackAction;
|
||||
private String mShortcutId;
|
||||
private int mAppWidgetId;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mCallbackAction = UUID.randomUUID().toString();
|
||||
mShortcutId = UUID.randomUUID().toString();
|
||||
}
|
||||
@@ -81,9 +89,9 @@ public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
|
||||
|
||||
@Test
|
||||
public void testPinWidgetNoConfig() throws Throwable {
|
||||
runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo &&
|
||||
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
|
||||
((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo
|
||||
&& ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId
|
||||
&& ((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
.equals(AppWidgetNoConfig.class.getName()));
|
||||
}
|
||||
|
||||
@@ -94,18 +102,18 @@ public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
|
||||
RequestPinItemActivity.class, "setRemoteViewColor").putExtra(
|
||||
RequestPinItemActivity.EXTRA_PARAM + "0", Color.RED);
|
||||
|
||||
runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo &&
|
||||
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
|
||||
((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo
|
||||
&& ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId
|
||||
&& ((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
.equals(AppWidgetNoConfig.class.getName()), command);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPinWidgetWithConfig() throws Throwable {
|
||||
runTest("pinWidgetWithConfig", true,
|
||||
(info, view) -> info instanceof LauncherAppWidgetInfo &&
|
||||
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
|
||||
((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
(info, view) -> info instanceof LauncherAppWidgetInfo
|
||||
&& ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId
|
||||
&& ((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
.equals(AppWidgetWithConfig.class.getName()));
|
||||
}
|
||||
|
||||
@@ -119,47 +127,48 @@ public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
|
||||
runTest("pinShortcut", false, new ItemOperator() {
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View view) {
|
||||
return info instanceof WorkspaceItemInfo &&
|
||||
info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
|
||||
ShortcutKey.fromItemInfo(info).getId().equals(mShortcutId);
|
||||
return info instanceof WorkspaceItemInfo
|
||||
&& info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
&& ShortcutKey.fromItemInfo(info).getId().equals(mShortcutId);
|
||||
}
|
||||
}, command);
|
||||
}
|
||||
|
||||
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
|
||||
Intent... commandIntents) throws Throwable {
|
||||
commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
|
||||
new FavoriteItemsTransaction(targetContext()).commit();
|
||||
loadLauncherSync();
|
||||
|
||||
// Open Pin item activity
|
||||
BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver(
|
||||
RequestPinItemActivity.class.getName());
|
||||
mLauncher.
|
||||
getWorkspace().
|
||||
switchToAllApps().
|
||||
getAppIcon("Test Pin Item").
|
||||
launch(getAppPackageName());
|
||||
Context testContext = getInstrumentation().getContext();
|
||||
startAppFast(
|
||||
testContext.getPackageName(),
|
||||
new Intent(testContext, RequestPinItemActivity.class));
|
||||
assertNotNull(openMonitor.blockingGetExtraIntent());
|
||||
|
||||
// Set callback
|
||||
PendingIntent callback = PendingIntent.getBroadcast(mTargetContext, 0,
|
||||
new Intent(mCallbackAction).setPackage(mTargetContext.getPackageName()),
|
||||
PendingIntent callback = PendingIntent.getBroadcast(targetContext(), 0,
|
||||
new Intent(mCallbackAction).setPackage(targetContext().getPackageName()),
|
||||
FLAG_ONE_SHOT | FLAG_MUTABLE);
|
||||
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
|
||||
targetContext().sendBroadcast(RequestPinItemActivity.getCommandIntent(
|
||||
RequestPinItemActivity.class, "setCallback").putExtra(
|
||||
RequestPinItemActivity.EXTRA_PARAM + "0", callback));
|
||||
|
||||
for (Intent command : commandIntents) {
|
||||
mTargetContext.sendBroadcast(command);
|
||||
targetContext().sendBroadcast(command);
|
||||
}
|
||||
|
||||
// call the requested method to start the flow
|
||||
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
|
||||
targetContext().sendBroadcast(RequestPinItemActivity.getCommandIntent(
|
||||
RequestPinItemActivity.class, activityMethod));
|
||||
final AddToHomeScreenPrompt addToHomeScreenPrompt = mLauncher.getAddToHomeScreenPrompt();
|
||||
|
||||
// Accept confirmation:
|
||||
BlockingBroadcastReceiver resultReceiver = new BlockingBroadcastReceiver(mCallbackAction);
|
||||
addToHomeScreenPrompt.addAutomatically();
|
||||
BySelector selector = By.text(Pattern.compile("^Add to home screen$", CASE_INSENSITIVE))
|
||||
.pkg(targetContext().getPackageName());
|
||||
uiDevice.wait(device -> device.findObject(selector), TestUtil.DEFAULT_UI_TIMEOUT).click();
|
||||
Intent result = resultReceiver.blockingGetIntent();
|
||||
assertNotNull(result);
|
||||
mAppWidgetId = result.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
|
||||
@@ -167,28 +176,9 @@ public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
|
||||
assertNotSame(-1, mAppWidgetId);
|
||||
}
|
||||
|
||||
// Go back to home
|
||||
mLauncher.goHome();
|
||||
Wait.atMost("", new ItemSearchCondition(itemMatcher), mLauncher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition for for an item
|
||||
*/
|
||||
private class ItemSearchCondition implements Condition {
|
||||
|
||||
private final ItemOperator mOp;
|
||||
|
||||
ItemSearchCondition(ItemOperator op) {
|
||||
mOp = op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrue() throws Throwable {
|
||||
return mMainThreadExecutor.submit(() -> {
|
||||
Launcher l = Launcher.ACTIVITY_TRACKER.getCreatedContext();
|
||||
return l != null && l.getWorkspace().getFirstMatch(mOp) != null;
|
||||
}).get();
|
||||
}
|
||||
// Reload activity, so that the activity is focused
|
||||
closeCurrentActivity();
|
||||
loadLauncherSync();
|
||||
getOnceNotNull("", l -> l.getWorkspace().getFirstMatch(itemMatcher));
|
||||
}
|
||||
}
|
||||
+17
-20
@@ -22,24 +22,30 @@ import static org.junit.Assert.assertTrue;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.MediumTest;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.tapl.Widgets;
|
||||
import com.android.launcher3.ui.AbstractLauncherUiTest;
|
||||
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
|
||||
import com.android.launcher3.util.BaseLauncherActivityTest;
|
||||
import com.android.launcher3.util.rule.ScreenRecordRule;
|
||||
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
|
||||
import com.android.launcher3.views.OptionsPopupView;
|
||||
import com.android.launcher3.widget.picker.WidgetsFullSheet;
|
||||
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* This test run in both Out of process (Oop) and in-process (Ipc).
|
||||
* Make sure the basic interactions with the WidgetPicker works.
|
||||
*/
|
||||
@MediumTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TaplWidgetPickerTest extends AbstractLauncherUiTest<Launcher> {
|
||||
public class WidgetPickerTest extends BaseLauncherActivityTest<Launcher> {
|
||||
|
||||
@Rule
|
||||
public TestRule screenRecordRule = new ScreenRecordRule();
|
||||
|
||||
private WidgetsRecyclerView getWidgetsView(Launcher launcher) {
|
||||
return WidgetsFullSheet.getWidgetsView(launcher);
|
||||
@@ -56,30 +62,21 @@ public class TaplWidgetPickerTest extends AbstractLauncherUiTest<Launcher> {
|
||||
@ScreenRecord
|
||||
@PortraitLandscape
|
||||
public void testWidgets() {
|
||||
mLauncher.goHome();
|
||||
loadLauncherSync();
|
||||
// Test opening widgets.
|
||||
executeOnLauncher(launcher ->
|
||||
assertTrue("Widgets is initially opened", getWidgetsView(launcher) == null));
|
||||
Widgets widgets = mLauncher.getWorkspace().openAllWidgets();
|
||||
assertNotNull("openAllWidgets() returned null", widgets);
|
||||
widgets = mLauncher.getAllWidgets();
|
||||
assertNotNull("openAllWidgets() returned null",
|
||||
getFromLauncher(OptionsPopupView::openWidgets));
|
||||
WidgetsRecyclerView widgets = getFromLauncher(this::getWidgetsView);
|
||||
assertNotNull("getAllWidgets() returned null", widgets);
|
||||
executeOnLauncher(launcher ->
|
||||
assertTrue("Widgets is not shown", getWidgetsView(launcher).isShown()));
|
||||
executeOnLauncher(launcher -> assertTrue("Widgets is not shown", widgets.isShown()));
|
||||
executeOnLauncher(launcher -> assertEquals("Widgets is scrolled upon opening",
|
||||
0, getWidgetsScroll(launcher)));
|
||||
|
||||
// Test flinging widgets.
|
||||
widgets.flingForward();
|
||||
Integer flingForwardY = getFromLauncher(launcher -> getWidgetsScroll(launcher));
|
||||
executeOnLauncher(launcher -> assertTrue("Flinging forward didn't scroll widgets",
|
||||
flingForwardY > 0));
|
||||
executeOnLauncher(AbstractFloatingView::closeAllOpenViews);
|
||||
uiDevice.waitForIdle();
|
||||
|
||||
widgets.flingBackward();
|
||||
executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets",
|
||||
getWidgetsScroll(launcher) < flingForwardY));
|
||||
|
||||
mLauncher.goHome();
|
||||
waitForLauncherCondition("Widgets were not closed",
|
||||
launcher -> getWidgetsView(launcher) == null);
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.launcher3.ui.workspace;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_ACTION_POPUP;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
|
||||
@@ -29,11 +27,9 @@ import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
@@ -49,9 +45,6 @@ import com.android.launcher3.util.TestUtil;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* Tests for theme icon support in Launcher
|
||||
*
|
||||
@@ -137,27 +130,10 @@ public class ThemeIconsTest extends BaseLauncherActivityTest<Launcher> {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Find the app icon
|
||||
Queue<View> viewQueue = new ArrayDeque<>();
|
||||
viewQueue.add(parent);
|
||||
BubbleTextView icon = null;
|
||||
while (!viewQueue.isEmpty()) {
|
||||
View view = viewQueue.poll();
|
||||
if (view instanceof ViewGroup) {
|
||||
parent = (ViewGroup) view;
|
||||
for (int i = parent.getChildCount() - 1; i >= 0; i--) {
|
||||
viewQueue.add(parent.getChildAt(i));
|
||||
}
|
||||
} else if (view instanceof BubbleTextView btv) {
|
||||
if (btv.getContentDescription() != null
|
||||
&& title.equals(btv.getContentDescription().toString())) {
|
||||
icon = btv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
return (BubbleTextView) searchView(parent, v ->
|
||||
v instanceof BubbleTextView btv
|
||||
&& btv.getContentDescription() != null
|
||||
&& title.equals(btv.getContentDescription().toString()));
|
||||
}
|
||||
|
||||
private BubbleTextView verifyIconTheme(String title, ViewGroup parent, boolean isThemed) {
|
||||
@@ -193,11 +169,4 @@ public class ThemeIconsTest extends BaseLauncherActivityTest<Launcher> {
|
||||
rv.getLayoutManager().scrollToPosition(pos);
|
||||
});
|
||||
}
|
||||
|
||||
private void addToWorkspace(View btv) {
|
||||
TestUtil.runOnExecutorSync(MAIN_EXECUTOR, () ->
|
||||
btv.getAccessibilityDelegate().performAccessibilityAction(
|
||||
btv, com.android.launcher3.R.id.action_add_to_workspace, null));
|
||||
UiDevice.getInstance(getInstrumentation()).waitForIdle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ import android.view.InputDevice
|
||||
import android.view.KeyCharacterMap
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import androidx.lifecycle.Lifecycle.State.RESUMED
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.core.app.ActivityScenario.ActivityAction
|
||||
@@ -30,11 +33,13 @@ import androidx.test.uiautomator.UiDevice
|
||||
import com.android.launcher3.Launcher
|
||||
import com.android.launcher3.LauncherAppState
|
||||
import com.android.launcher3.LauncherState
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST
|
||||
import com.android.launcher3.tapl.TestHelpers
|
||||
import com.android.launcher3.util.ModelTestExtensions.loadModelSync
|
||||
import com.android.launcher3.util.Wait.atMost
|
||||
import java.util.function.Function
|
||||
import java.util.function.Predicate
|
||||
import java.util.function.Supplier
|
||||
import org.junit.After
|
||||
|
||||
@@ -56,6 +61,8 @@ open class BaseLauncherActivityTest<LAUNCHER_TYPE : Launcher> {
|
||||
)
|
||||
.also { currentScenario = it }
|
||||
|
||||
@JvmField val uiDevice = UiDevice.getInstance(getInstrumentation())
|
||||
|
||||
@After
|
||||
fun closeCurrentActivity() {
|
||||
currentScenario?.close()
|
||||
@@ -136,18 +143,43 @@ open class BaseLauncherActivityTest<LAUNCHER_TYPE : Launcher> {
|
||||
event.recycle()
|
||||
}
|
||||
|
||||
fun startAppFast(packageName: String) {
|
||||
val intent = targetContext().packageManager.getLaunchIntentForPackage(packageName)!!
|
||||
@JvmOverloads
|
||||
fun startAppFast(
|
||||
packageName: String,
|
||||
intent: Intent = targetContext().packageManager.getLaunchIntentForPackage(packageName)!!,
|
||||
) {
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
targetContext().startActivity(intent)
|
||||
UiDevice.getInstance(getInstrumentation()).waitForIdle()
|
||||
uiDevice.waitForIdle()
|
||||
}
|
||||
|
||||
fun freezeAllApps() = executeOnLauncher {
|
||||
it.appsView.appsStore.enableDeferUpdates(DEFER_UPDATES_TEST)
|
||||
}
|
||||
|
||||
fun executeShellCommand(cmd: String) =
|
||||
UiDevice.getInstance(getInstrumentation()).executeShellCommand(cmd)
|
||||
fun executeShellCommand(cmd: String) = uiDevice.executeShellCommand(cmd)
|
||||
|
||||
fun addToWorkspace(view: View) {
|
||||
TestUtil.runOnExecutorSync(Executors.MAIN_EXECUTOR) {
|
||||
view.accessibilityDelegate.performAccessibilityAction(
|
||||
view,
|
||||
R.id.action_add_to_workspace,
|
||||
null,
|
||||
)
|
||||
}
|
||||
UiDevice.getInstance(getInstrumentation()).waitForIdle()
|
||||
}
|
||||
|
||||
fun ViewGroup.searchView(filter: Predicate<View>): View? {
|
||||
if (filter.test(this)) return this
|
||||
for (child in children) {
|
||||
if (filter.test(child)) return child
|
||||
if (child is ViewGroup)
|
||||
child.searchView(filter)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.util
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Parcelable
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.TimeUnit.SECONDS
|
||||
|
||||
private const val DEFAULT_BROADCAST_TIMEOUT_SECS: Long = 10
|
||||
|
||||
/** Broadcast receiver which blocks until the result is received. */
|
||||
open class BlockingBroadcastReceiver(action: String) : BroadcastReceiver() {
|
||||
|
||||
val value = CompletableFuture<Intent>()
|
||||
|
||||
init {
|
||||
getInstrumentation()
|
||||
.targetContext
|
||||
.registerReceiver(this, IntentFilter(action), Context.RECEIVER_EXPORTED)
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
value.complete(intent)
|
||||
}
|
||||
|
||||
@Throws(InterruptedException::class)
|
||||
fun blockingGetIntent(): Intent =
|
||||
value.get(DEFAULT_BROADCAST_TIMEOUT_SECS, SECONDS).also {
|
||||
getInstrumentation().targetContext.unregisterReceiver(this)
|
||||
}
|
||||
|
||||
@Throws(InterruptedException::class)
|
||||
fun blockingGetExtraIntent(): Intent? =
|
||||
blockingGetIntent().getParcelableExtra<Parcelable>(Intent.EXTRA_INTENT) as Intent?
|
||||
}
|
||||
Reference in New Issue
Block a user