Home | History | Annotate | Download | only in widget
      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
     65     public void setUp() throws Exception {
     66         super.setUp();
     67         mWidgetInfo = findWidgetProvider(true /* hasConfigureScreen */);
     68         mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
     69     }
     70 
     71     @Test
     72     public void testWidgetConfig() throws Throwable {
     73         runTest(false, true);
     74     }
     75 
     76     @Test
     77     public void testWidgetConfig_rotate() throws Throwable {
     78         runTest(true, true);
     79     }
     80 
     81     @Test
     82     public void testConfigCancelled() throws Throwable {
     83         runTest(false, false);
     84     }
     85 
     86     @Test
     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      */
     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 
    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
    152         public boolean isTrue() throws Throwable {
    153             return mMainThreadExecutor.submit(mActivityMonitor.itemExists(this)).get();
    154         }
    155 
    156         @Override
    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 
    169         public WidgetConfigStartupMonitor() {
    170             super(WidgetConfigActivity.class.getName());
    171         }
    172 
    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