1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 package com.android.launcher3.ui.widget; 17 18 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 19 20 import static com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertNotSame; 25 26 import android.appwidget.AppWidgetManager; 27 import android.content.Intent; 28 import android.view.View; 29 30 import androidx.test.filters.LargeTest; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import com.android.launcher3.Launcher; 34 import com.android.launcher3.celllayout.FavoriteItemsTransaction; 35 import com.android.launcher3.model.data.ItemInfo; 36 import com.android.launcher3.model.data.LauncherAppWidgetInfo; 37 import com.android.launcher3.testcomponent.WidgetConfigActivity; 38 import com.android.launcher3.ui.AbstractLauncherUiTest; 39 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape; 40 import com.android.launcher3.ui.TestViewHelpers; 41 import com.android.launcher3.util.Wait; 42 import com.android.launcher3.util.rule.ShellCommandRule; 43 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; 44 45 import org.junit.Before; 46 import org.junit.Rule; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 50 /** 51 * Test to verify widget configuration is properly shown. 52 */ 53 @LargeTest 54 @RunWith(AndroidJUnit4.class) 55 public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest<Launcher> { 56 57 @Rule 58 public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind(); 59 60 private LauncherAppWidgetProviderInfo mWidgetInfo; 61 private AppWidgetManager mAppWidgetManager; 62 63 private int mWidgetId; 64 65 @Override 66 @Before setUp()67 public void setUp() throws Exception { 68 super.setUp(); 69 mWidgetInfo = TestViewHelpers.findWidgetProvider(true /* hasConfigureScreen */); 70 mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext); 71 } 72 73 @Test 74 @PortraitLandscape testWidgetConfig()75 public void testWidgetConfig() throws Throwable { 76 runTest(true); 77 } 78 79 @Test 80 @PortraitLandscape testConfigCancelled()81 public void testConfigCancelled() throws Throwable { 82 runTest(false); 83 } 84 85 86 /** 87 * @param acceptConfig accept the config activity 88 */ runTest(boolean acceptConfig)89 private void runTest(boolean acceptConfig) throws Throwable { 90 commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext)); 91 92 // Drag widget to homescreen 93 WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor(); 94 mLauncher.getWorkspace() 95 .openAllWidgets() 96 .getWidget(mWidgetInfo.getLabel(mTargetContext.getPackageManager())) 97 .dragToWorkspace(true, false); 98 // Widget id for which the config activity was opened 99 mWidgetId = monitor.getWidgetId(); 100 101 // Verify that the widget id is valid and bound 102 assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); 103 104 setResultAndWaitForAnimation(acceptConfig); 105 if (acceptConfig) { 106 Wait.atMost("", new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT, mLauncher); 107 assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); 108 } else { 109 // Verify that the widget id is deleted. 110 Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null, 111 DEFAULT_ACTIVITY_TIMEOUT, mLauncher); 112 } 113 } 114 setResult(boolean success)115 private static void setResult(boolean success) { 116 getInstrumentation().getTargetContext().sendBroadcast( 117 WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class, 118 success ? "clickOK" : "clickCancel")); 119 } 120 setResultAndWaitForAnimation(boolean success)121 private void setResultAndWaitForAnimation(boolean success) { 122 if (mLauncher.isLauncher3()) { 123 setResult(success); 124 } else { 125 mLauncher.executeAndWaitForWallpaperAnimation( 126 () -> setResult(success), 127 "setting widget coinfig result"); 128 } 129 } 130 131 /** 132 * Condition for searching widget id 133 */ 134 private class WidgetSearchCondition implements Wait.Condition, ItemOperator { 135 136 @Override isTrue()137 public boolean isTrue() throws Throwable { 138 return mMainThreadExecutor.submit(() -> { 139 Launcher l = Launcher.ACTIVITY_TRACKER.getCreatedActivity(); 140 return l != null && l.getWorkspace().getFirstMatch(this) != null; 141 }).get(); 142 } 143 144 @Override evaluate(ItemInfo info, View view)145 public boolean evaluate(ItemInfo info, View view) { 146 return info instanceof LauncherAppWidgetInfo 147 && ((LauncherAppWidgetInfo) info).providerName.getClassName().equals( 148 mWidgetInfo.provider.getClassName()) 149 && ((LauncherAppWidgetInfo) info).appWidgetId == mWidgetId; 150 } 151 } 152 153 /** 154 * Broadcast receiver for receiving widget config activity status. 155 */ 156 private class WidgetConfigStartupMonitor extends BlockingBroadcastReceiver { 157 WidgetConfigStartupMonitor()158 public WidgetConfigStartupMonitor() { 159 super(WidgetConfigActivity.class.getName()); 160 } 161 getWidgetId()162 public int getWidgetId() throws InterruptedException { 163 Intent intent = blockingGetExtraIntent(); 164 assertNotNull("Null EXTRA_INTENT", intent); 165 assertEquals("Intent action is not ACTION_APPWIDGET_CONFIGURE", 166 AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, intent.getAction()); 167 int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 168 LauncherAppWidgetInfo.NO_ID); 169 assertNotSame("Widget id is NO_ID", widgetId, LauncherAppWidgetInfo.NO_ID); 170 return widgetId; 171 } 172 } 173 } 174