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 android.appwidget.AppWidgetManager; 19 import android.content.Intent; 20 import android.support.test.filters.LargeTest; 21 import android.support.test.runner.AndroidJUnit4; 22 import android.support.test.uiautomator.By; 23 import android.support.test.uiautomator.UiObject2; 24 import android.view.View; 25 26 import com.android.launcher3.ItemInfo; 27 import com.android.launcher3.LauncherAppWidgetInfo; 28 import com.android.launcher3.LauncherAppWidgetProviderInfo; 29 import com.android.launcher3.Workspace; 30 import com.android.launcher3.testcomponent.WidgetConfigActivity; 31 import com.android.launcher3.ui.AbstractLauncherUiTest; 32 import com.android.launcher3.util.Condition; 33 import com.android.launcher3.util.Wait; 34 import com.android.launcher3.util.rule.LauncherActivityRule; 35 import com.android.launcher3.util.rule.ShellCommandRule; 36 import com.android.launcher3.widget.WidgetCell; 37 38 import org.junit.Before; 39 import org.junit.Rule; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import static org.junit.Assert.assertEquals; 44 import static org.junit.Assert.assertNotNull; 45 import static org.junit.Assert.assertNotSame; 46 import static org.junit.Assert.assertTrue; 47 48 /** 49 * Test to verify widget configuration is properly shown. 50 */ 51 @LargeTest 52 @RunWith(AndroidJUnit4.class) 53 public class AddConfigWidgetTest extends AbstractLauncherUiTest { 54 55 @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); 56 @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind(); 57 58 private LauncherAppWidgetProviderInfo mWidgetInfo; 59 private AppWidgetManager mAppWidgetManager; 60 61 private int mWidgetId; 62 63 @Override 64 @Before setUp()65 public void setUp() throws Exception { 66 super.setUp(); 67 mWidgetInfo = findWidgetProvider(true /* hasConfigureScreen */); 68 mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext); 69 } 70 71 @Test testWidgetConfig()72 public void testWidgetConfig() throws Throwable { 73 runTest(false, true); 74 } 75 76 @Test testWidgetConfig_rotate()77 public void testWidgetConfig_rotate() throws Throwable { 78 runTest(true, true); 79 } 80 81 @Test testConfigCancelled()82 public void testConfigCancelled() throws Throwable { 83 runTest(false, false); 84 } 85 86 @Test testConfigCancelled_rotate()87 public void testConfigCancelled_rotate() throws Throwable { 88 runTest(true, false); 89 } 90 91 /** 92 * @param rotateConfig should the config screen be rotated 93 * @param acceptConfig accept the config activity 94 */ runTest(boolean rotateConfig, boolean acceptConfig)95 private void runTest(boolean rotateConfig, boolean acceptConfig) throws Throwable { 96 lockRotation(true); 97 98 clearHomescreen(); 99 mActivityMonitor.startLauncher(); 100 101 // Open widget tray and wait for load complete. 102 final UiObject2 widgetContainer = openWidgetsTray(); 103 assertTrue(Wait.atMost(Condition.minChildCount(widgetContainer, 2), DEFAULT_UI_TIMEOUT)); 104 105 // Drag widget to homescreen 106 WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor(); 107 UiObject2 widget = scrollAndFind(widgetContainer, By.clazz(WidgetCell.class) 108 .hasDescendant(By.text(mWidgetInfo.getLabel(mTargetContext.getPackageManager())))); 109 dragToWorkspace(widget, false); 110 // Widget id for which the config activity was opened 111 mWidgetId = monitor.getWidgetId(); 112 113 if (rotateConfig) { 114 // Rotate the screen and verify that the config activity is recreated 115 monitor = new WidgetConfigStartupMonitor(); 116 lockRotation(false); 117 assertEquals(mWidgetId, monitor.getWidgetId()); 118 } 119 120 // Verify that the widget id is valid and bound 121 assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); 122 123 setResult(acceptConfig); 124 if (acceptConfig) { 125 assertTrue(Wait.atMost(new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT)); 126 assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); 127 } else { 128 // Verify that the widget id is deleted. 129 assertTrue(Wait.atMost(new Condition() { 130 @Override 131 public boolean isTrue() throws Throwable { 132 return mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null; 133 } 134 }, DEFAULT_ACTIVITY_TIMEOUT)); 135 } 136 } 137 setResult(boolean success)138 private void setResult(boolean success) { 139 140 getInstrumentation().getTargetContext().sendBroadcast( 141 WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class, 142 success ? "clickOK" : "clickCancel")); 143 } 144 145 /** 146 * Condition for searching widget id 147 */ 148 private class WidgetSearchCondition extends Condition 149 implements Workspace.ItemOperator { 150 151 @Override isTrue()152 public boolean isTrue() throws Throwable { 153 return mMainThreadExecutor.submit(mActivityMonitor.itemExists(this)).get(); 154 } 155 156 @Override evaluate(ItemInfo info, View view)157 public boolean evaluate(ItemInfo info, View view) { 158 return info instanceof LauncherAppWidgetInfo && 159 ((LauncherAppWidgetInfo) info).providerName.equals(mWidgetInfo.provider) && 160 ((LauncherAppWidgetInfo) info).appWidgetId == mWidgetId; 161 } 162 } 163 164 /** 165 * Broadcast receiver for receiving widget config activity status. 166 */ 167 private class WidgetConfigStartupMonitor extends BlockingBroadcastReceiver { 168 WidgetConfigStartupMonitor()169 public WidgetConfigStartupMonitor() { 170 super(WidgetConfigActivity.class.getName()); 171 } 172 getWidgetId()173 public int getWidgetId() throws InterruptedException { 174 Intent intent = blockingGetExtraIntent(); 175 assertNotNull(intent); 176 assertEquals(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, intent.getAction()); 177 int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 178 LauncherAppWidgetInfo.NO_ID); 179 assertNotSame(widgetId, LauncherAppWidgetInfo.NO_ID); 180 return widgetId; 181 } 182 } 183 } 184