ShortcutManagerCompatTest.java revision ab5e1a448f10ecacf1ac6a642523e48e79784e62
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.content.pm; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertNotNull; 22import static org.junit.Assert.assertTrue; 23import static org.mockito.Mockito.any; 24import static org.mockito.Mockito.anyInt; 25import static org.mockito.Mockito.doReturn; 26import static org.mockito.Mockito.eq; 27import static org.mockito.Mockito.isNull; 28import static org.mockito.Mockito.mock; 29import static org.mockito.Mockito.reset; 30import static org.mockito.Mockito.spy; 31import static org.mockito.Mockito.times; 32import static org.mockito.Mockito.verify; 33import static org.mockito.Mockito.when; 34 35import android.annotation.TargetApi; 36import android.app.PendingIntent; 37import android.content.BroadcastReceiver; 38import android.content.Context; 39import android.content.Intent; 40import android.content.IntentFilter; 41import android.content.IntentSender; 42import android.content.pm.ActivityInfo; 43import android.content.pm.PackageManager; 44import android.content.pm.ResolveInfo; 45import android.content.pm.ShortcutInfo; 46import android.content.pm.ShortcutManager; 47import android.graphics.Bitmap; 48import android.support.test.filters.SmallTest; 49import android.support.test.runner.AndroidJUnit4; 50import android.support.v4.BaseInstrumentationTestCase; 51import android.support.v4.app.TestSupportActivity; 52import android.support.v4.os.BuildCompat; 53 54import org.junit.Before; 55import org.junit.Test; 56import org.junit.runner.RunWith; 57import org.mockito.ArgumentCaptor; 58 59import java.util.Arrays; 60import java.util.concurrent.CountDownLatch; 61import java.util.concurrent.TimeUnit; 62 63@RunWith(AndroidJUnit4.class) 64@SmallTest 65public class ShortcutManagerCompatTest extends BaseInstrumentationTestCase<TestSupportActivity> { 66 67 Context mContext; 68 ShortcutInfoCompat mInfoCompat; 69 70 public ShortcutManagerCompatTest() { 71 super(TestSupportActivity.class); 72 } 73 74 @Before 75 public void setup() { 76 mContext = spy(mActivityTestRule.getActivity()); 77 mInfoCompat = new ShortcutInfoCompat.Builder(mContext, "test-id") 78 .setIcon(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)) 79 .setShortLabel("Test shortcut") 80 .setIntent(new Intent("Dummy")) 81 .build(); 82 } 83 84 @Test 85 @TargetApi(26) 86 public void testIsRequestPinShortcutSupported_v26() throws Throwable { 87 if (!BuildCompat.isAtLeastO()) { 88 return; 89 } 90 91 ShortcutManager mockShortcutManager = mockShortcutManager(); 92 when(mockShortcutManager.isRequestPinShortcutSupported()).thenReturn(true, false, true); 93 94 assertTrue(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 95 assertFalse(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 96 assertTrue(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 97 verify(mockShortcutManager, times(3)).isRequestPinShortcutSupported(); 98 } 99 100 @Test 101 @TargetApi(26) 102 public void testRequestPinShortcut_v26() throws Throwable { 103 if (!BuildCompat.isAtLeastO()) { 104 return; 105 } 106 107 ShortcutManager mockShortcutManager = mockShortcutManager(); 108 when(mockShortcutManager.requestPinShortcut( 109 any(ShortcutInfo.class), any(IntentSender.class))).thenReturn(true); 110 111 assertTrue(ShortcutManagerCompat.requestPinShortcut(mContext, mInfoCompat, null)); 112 ArgumentCaptor<ShortcutInfo> captor = ArgumentCaptor.forClass(ShortcutInfo.class); 113 verify(mockShortcutManager, times(1)).requestPinShortcut(captor.capture(), 114 (IntentSender) isNull()); 115 assertEquals("test-id", captor.getValue().getId()); 116 } 117 118 @Test 119 @TargetApi(26) 120 public void testCreateShortcutResultIntent_v26() throws Throwable { 121 if (!BuildCompat.isAtLeastO()) { 122 return; 123 } 124 125 ShortcutManager mockShortcutManager = mockShortcutManager(); 126 127 when(mockShortcutManager.createShortcutResultIntent(any(ShortcutInfo.class))) 128 .thenReturn(new Intent("some-dummy-action")); 129 130 Intent result = ShortcutManagerCompat.createShortcutResultIntent(mContext, mInfoCompat); 131 verifyLegacyIntent(result); 132 assertEquals("some-dummy-action", result.getAction()); 133 134 ArgumentCaptor<ShortcutInfo> captor = ArgumentCaptor.forClass(ShortcutInfo.class); 135 verify(mockShortcutManager, times(1)).createShortcutResultIntent(captor.capture()); 136 assertEquals("test-id", captor.getValue().getId()); 137 } 138 139 private ShortcutManager mockShortcutManager() { 140 ShortcutManager mockShortcutManager = mock(ShortcutManager.class); 141 doReturn(mockShortcutManager).when(mContext).getSystemService(eq(Context.SHORTCUT_SERVICE)); 142 return mockShortcutManager; 143 } 144 145 @Test 146 public void testIsRequestPinShortcutSupported_v4() throws Throwable { 147 if (BuildCompat.isAtLeastO()) { 148 return; 149 } 150 setMockPm(mockResolveInfo(null)); 151 assertTrue(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 152 153 // We do not have the permission 154 setMockPm(mockResolveInfo("com.android.permission.something-we-dont-have")); 155 assertFalse(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 156 157 // There are no receivers 158 setMockPm(); 159 assertFalse(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 160 161 // At least one receiver is supported 162 setMockPm(mockResolveInfo("com.android.permission.something-we-dont-have"), 163 mockResolveInfo(null)); 164 assertTrue(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 165 166 // We have the permission 167 setMockPm(mockResolveInfo(ShortcutManagerCompat.INSTALL_SHORTCUT_PERMISSION)); 168 assertTrue(ShortcutManagerCompat.isRequestPinShortcutSupported(mContext)); 169 } 170 171 @Test 172 public void testRequestPinShortcut_v4_noCallback() throws Throwable { 173 if (BuildCompat.isAtLeastO()) { 174 return; 175 } 176 177 setMockPm(mockResolveInfo(null)); 178 179 BlockingBroadcastReceiver receiver = 180 new BlockingBroadcastReceiver(ShortcutManagerCompat.ACTION_INSTALL_SHORTCUT); 181 assertTrue(ShortcutManagerCompat.requestPinShortcut(mContext, mInfoCompat, null)); 182 verifyLegacyIntent(receiver.blockingGetIntent()); 183 } 184 185 @Test 186 public void testRequestPinShortcut_v4_withCallback() throws Throwable { 187 if (BuildCompat.isAtLeastO()) { 188 return; 189 } 190 191 setMockPm(mockResolveInfo(null)); 192 193 BlockingBroadcastReceiver receiver = 194 new BlockingBroadcastReceiver(ShortcutManagerCompat.ACTION_INSTALL_SHORTCUT); 195 BlockingBroadcastReceiver callback = 196 new BlockingBroadcastReceiver("shortcut-callback"); 197 198 assertTrue(ShortcutManagerCompat.requestPinShortcut(mContext, mInfoCompat, 199 PendingIntent.getBroadcast(mContext, 0, new Intent("shortcut-callback"), 200 PendingIntent.FLAG_ONE_SHOT).getIntentSender())); 201 verifyLegacyIntent(receiver.blockingGetIntent()); 202 assertNotNull(callback.blockingGetIntent()); 203 } 204 205 @Test 206 public void testCreateShortcutResultIntent_v4() throws Throwable { 207 if (BuildCompat.isAtLeastO()) { 208 return; 209 } 210 211 verifyLegacyIntent(ShortcutManagerCompat.createShortcutResultIntent(mContext, mInfoCompat)); 212 } 213 214 private void verifyLegacyIntent(Intent intent) { 215 assertNotNull(intent); 216 assertEquals("Test shortcut", intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME)); 217 assertEquals("Dummy", ((Intent) intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT)) 218 .getAction()); 219 } 220 221 private void setMockPm(ResolveInfo... infos) { 222 PackageManager pm = mock(PackageManager.class); 223 when(pm.queryBroadcastReceivers(any(Intent.class), anyInt())) 224 .thenReturn(Arrays.asList(infos)); 225 reset(mContext); 226 doReturn(pm).when(mContext).getPackageManager(); 227 } 228 229 private ResolveInfo mockResolveInfo(String permission) { 230 ActivityInfo aInfo = new ActivityInfo(); 231 aInfo.packageName = mContext.getPackageName(); 232 aInfo.permission = permission; 233 ResolveInfo rInfo = new ResolveInfo(); 234 rInfo.activityInfo = aInfo; 235 return rInfo; 236 } 237 238 private class BlockingBroadcastReceiver extends BroadcastReceiver { 239 240 private final CountDownLatch mLatch = new CountDownLatch(1); 241 private Intent mIntent; 242 243 BlockingBroadcastReceiver(String action) { 244 mContext.registerReceiver(this, new IntentFilter(action)); 245 } 246 247 @Override 248 public void onReceive(Context context, Intent intent) { 249 mIntent = intent; 250 mLatch.countDown(); 251 } 252 253 public Intent blockingGetIntent() throws InterruptedException { 254 mLatch.await(5, TimeUnit.SECONDS); 255 mContext.unregisterReceiver(this); 256 return mIntent; 257 } 258 } 259} 260