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