• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.app.PendingIntent.FLAG_MUTABLE;
19 import static android.app.PendingIntent.FLAG_ONE_SHOT;
20 
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNotSame;
23 
24 import android.app.PendingIntent;
25 import android.appwidget.AppWidgetManager;
26 import android.content.Intent;
27 import android.graphics.Color;
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.LauncherSettings.Favorites;
35 import com.android.launcher3.celllayout.FavoriteItemsTransaction;
36 import com.android.launcher3.model.data.ItemInfo;
37 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
38 import com.android.launcher3.model.data.WorkspaceItemInfo;
39 import com.android.launcher3.shortcuts.ShortcutKey;
40 import com.android.launcher3.tapl.AddToHomeScreenPrompt;
41 import com.android.launcher3.testcomponent.AppWidgetNoConfig;
42 import com.android.launcher3.testcomponent.AppWidgetWithConfig;
43 import com.android.launcher3.testcomponent.RequestPinItemActivity;
44 import com.android.launcher3.ui.AbstractLauncherUiTest;
45 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
46 import com.android.launcher3.util.Wait;
47 import com.android.launcher3.util.Wait.Condition;
48 import com.android.launcher3.util.rule.ShellCommandRule;
49 
50 import org.junit.Before;
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 
55 import java.util.UUID;
56 
57 /**
58  * Test to verify pin item request flow.
59  */
60 @LargeTest
61 @RunWith(AndroidJUnit4.class)
62 public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
63 
64     @Rule
65     public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
66 
67     private String mCallbackAction;
68     private String mShortcutId;
69     private int mAppWidgetId;
70 
71     @Override
72     @Before
setUp()73     public void setUp() throws Exception {
74         super.setUp();
75         mCallbackAction = UUID.randomUUID().toString();
76         mShortcutId = UUID.randomUUID().toString();
77     }
78 
79     @Test
testEmpty()80     public void testEmpty() throws Throwable { /* needed while the broken tests are being fixed */ }
81 
82     @Test
testPinWidgetNoConfig()83     public void testPinWidgetNoConfig() throws Throwable {
84         runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo &&
85                 ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
86                 ((LauncherAppWidgetInfo) info).providerName.getClassName()
87                         .equals(AppWidgetNoConfig.class.getName()));
88     }
89 
90     @Test
testPinWidgetNoConfig_customPreview()91     public void testPinWidgetNoConfig_customPreview() throws Throwable {
92         // Command to set custom preview
93         Intent command = RequestPinItemActivity.getCommandIntent(
94                 RequestPinItemActivity.class, "setRemoteViewColor").putExtra(
95                 RequestPinItemActivity.EXTRA_PARAM + "0", Color.RED);
96 
97         runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo &&
98                 ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
99                 ((LauncherAppWidgetInfo) info).providerName.getClassName()
100                         .equals(AppWidgetNoConfig.class.getName()), command);
101     }
102 
103     @Test
testPinWidgetWithConfig()104     public void testPinWidgetWithConfig() throws Throwable {
105         runTest("pinWidgetWithConfig", true,
106                 (info, view) -> info instanceof LauncherAppWidgetInfo &&
107                         ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
108                         ((LauncherAppWidgetInfo) info).providerName.getClassName()
109                                 .equals(AppWidgetWithConfig.class.getName()));
110     }
111 
112     @Test
testPinShortcut()113     public void testPinShortcut() throws Throwable {
114         // Command to set the shortcut id
115         Intent command = RequestPinItemActivity.getCommandIntent(
116                 RequestPinItemActivity.class, "setShortcutId").putExtra(
117                 RequestPinItemActivity.EXTRA_PARAM + "0", mShortcutId);
118 
119         runTest("pinShortcut", false, new ItemOperator() {
120             @Override
121             public boolean evaluate(ItemInfo info, View view) {
122                 return info instanceof WorkspaceItemInfo &&
123                         info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
124                         ShortcutKey.fromItemInfo(info).getId().equals(mShortcutId);
125             }
126         }, command);
127     }
128 
runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher, Intent... commandIntents)129     private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
130             Intent... commandIntents) throws Throwable {
131         commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
132 
133         // Open Pin item activity
134         BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver(
135                 RequestPinItemActivity.class.getName());
136         mLauncher.
137                 getWorkspace().
138                 switchToAllApps().
139                 getAppIcon("Test Pin Item").
140                 launch(getAppPackageName());
141         assertNotNull(openMonitor.blockingGetExtraIntent());
142 
143         // Set callback
144         PendingIntent callback = PendingIntent.getBroadcast(mTargetContext, 0,
145                 new Intent(mCallbackAction).setPackage(mTargetContext.getPackageName()),
146                 FLAG_ONE_SHOT | FLAG_MUTABLE);
147         mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
148                 RequestPinItemActivity.class, "setCallback").putExtra(
149                 RequestPinItemActivity.EXTRA_PARAM + "0", callback));
150 
151         for (Intent command : commandIntents) {
152             mTargetContext.sendBroadcast(command);
153         }
154 
155         // call the requested method to start the flow
156         mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
157                 RequestPinItemActivity.class, activityMethod));
158         final AddToHomeScreenPrompt addToHomeScreenPrompt = mLauncher.getAddToHomeScreenPrompt();
159 
160         // Accept confirmation:
161         BlockingBroadcastReceiver resultReceiver = new BlockingBroadcastReceiver(mCallbackAction);
162         addToHomeScreenPrompt.addAutomatically();
163         Intent result = resultReceiver.blockingGetIntent();
164         assertNotNull(result);
165         mAppWidgetId = result.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
166         if (isWidget) {
167             assertNotSame(-1, mAppWidgetId);
168         }
169 
170         // Go back to home
171         mLauncher.goHome();
172         Wait.atMost("", new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT,
173                 mLauncher);
174     }
175 
176     /**
177      * Condition for for an item
178      */
179     private class ItemSearchCondition implements Condition {
180 
181         private final ItemOperator mOp;
182 
ItemSearchCondition(ItemOperator op)183         ItemSearchCondition(ItemOperator op) {
184             mOp = op;
185         }
186 
187         @Override
isTrue()188         public boolean isTrue() throws Throwable {
189             return mMainThreadExecutor.submit(() -> {
190                 Launcher l = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
191                 return l != null && l.getWorkspace().getFirstMatch(mOp) != null;
192             }).get();
193         }
194     }
195 }
196