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