AppWidgetServiceImplTest.java revision b3a20ee45a23cfc65fb09f4a4841270fa885518c
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 com.android.server.appwidget; 18 19import static org.mockito.Matchers.any; 20import static org.mockito.Matchers.anyInt; 21import static org.mockito.Matchers.anyString; 22import static org.mockito.Matchers.eq; 23import static org.mockito.Mockito.mock; 24import static org.mockito.Mockito.reset; 25import static org.mockito.Mockito.times; 26import static org.mockito.Mockito.verify; 27import static org.mockito.Mockito.when; 28 29import android.app.admin.DevicePolicyManagerInternal; 30import android.appwidget.AppWidgetManager; 31import android.appwidget.AppWidgetProviderInfo; 32import android.appwidget.PendingHostUpdate; 33import android.content.BroadcastReceiver; 34import android.content.ComponentName; 35import android.content.ContextWrapper; 36import android.content.Intent; 37import android.content.IntentFilter; 38import android.content.IntentSender; 39import android.content.pm.ShortcutServiceInternal; 40import android.os.Handler; 41import android.os.UserHandle; 42import android.test.InstrumentationTestCase; 43import android.test.suitebuilder.annotation.SmallTest; 44import android.widget.RemoteViews; 45 46import com.android.internal.appwidget.IAppWidgetHost; 47import com.android.server.LocalServices; 48 49import org.mockito.ArgumentCaptor; 50 51import java.util.List; 52import java.util.Random; 53import java.util.concurrent.CountDownLatch; 54 55 56/** 57 * Tests for {@link AppWidgetManager} and {@link AppWidgetServiceImpl}. 58 * 59 m FrameworksServicesTests && 60 adb install \ 61 -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && 62 adb shell am instrument -e class com.android.server.appwidget.AppWidgetServiceImplTest \ 63 -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner 64 */ 65@SmallTest 66public class AppWidgetServiceImplTest extends InstrumentationTestCase { 67 68 private static final int HOST_ID = 42; 69 70 private TestContext mTestContext; 71 private String mPkgName; 72 private AppWidgetServiceImpl mService; 73 private AppWidgetManager mManager; 74 75 private ShortcutServiceInternal mMockShortcutService; 76 private IAppWidgetHost mMockHost; 77 78 @Override 79 protected void setUp() throws Exception { 80 super.setUp(); 81 LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); 82 LocalServices.removeServiceForTest(ShortcutServiceInternal.class); 83 84 mTestContext = new TestContext(); 85 mPkgName = mTestContext.getOpPackageName(); 86 mService = new AppWidgetServiceImpl(mTestContext); 87 mManager = new AppWidgetManager(mTestContext, mService); 88 89 mMockShortcutService = mock(ShortcutServiceInternal.class); 90 mMockHost = mock(IAppWidgetHost.class); 91 LocalServices.addService(ShortcutServiceInternal.class, mMockShortcutService); 92 mService.onStart(); 93 } 94 95 public void testRequestPinAppWidget_otherProvider() { 96 ComponentName otherProvider = null; 97 for (AppWidgetProviderInfo provider : mManager.getInstalledProviders()) { 98 if (!provider.provider.getPackageName().equals(mTestContext.getPackageName())) { 99 otherProvider = provider.provider; 100 break; 101 } 102 } 103 if (otherProvider == null) { 104 // No other provider found. Ignore this test. 105 } 106 assertFalse(mManager.requestPinAppWidget(otherProvider, null)); 107 } 108 109 public void testRequestPinAppWidget() { 110 ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class); 111 // Set up users. 112 when(mMockShortcutService.requestPinAppWidget(anyString(), 113 any(AppWidgetProviderInfo.class), any(IntentSender.class), anyInt())) 114 .thenReturn(true); 115 assertTrue(mManager.requestPinAppWidget(provider, null)); 116 117 final ArgumentCaptor<AppWidgetProviderInfo> providerCaptor = 118 ArgumentCaptor.forClass(AppWidgetProviderInfo.class); 119 verify(mMockShortcutService, times(1)).requestPinAppWidget(anyString(), 120 providerCaptor.capture(), eq(null), anyInt()); 121 assertEquals(provider, providerCaptor.getValue().provider); 122 } 123 124 public void testProviderUpdatesReceived() throws Exception { 125 int widgetId = setupHostAndWidget(); 126 RemoteViews view = new RemoteViews(mPkgName, android.R.layout.simple_list_item_1); 127 mManager.updateAppWidget(widgetId, view); 128 mManager.updateAppWidget(widgetId, view); 129 mManager.updateAppWidget(widgetId, view); 130 mManager.updateAppWidget(widgetId, view); 131 132 flushMainThread(); 133 verify(mMockHost, times(4)).updateAppWidget(eq(widgetId), any(RemoteViews.class)); 134 135 reset(mMockHost); 136 mManager.notifyAppWidgetViewDataChanged(widgetId, 22); 137 flushMainThread(); 138 verify(mMockHost, times(1)).viewDataChanged(eq(widgetId), eq(22)); 139 } 140 141 public void testProviderUpdatesNotReceived() throws Exception { 142 int widgetId = setupHostAndWidget(); 143 mService.stopListening(mPkgName, HOST_ID); 144 RemoteViews view = new RemoteViews(mPkgName, android.R.layout.simple_list_item_1); 145 mManager.updateAppWidget(widgetId, view); 146 mManager.notifyAppWidgetViewDataChanged(widgetId, 22); 147 148 flushMainThread(); 149 verify(mMockHost, times(0)).updateAppWidget(anyInt(), any(RemoteViews.class)); 150 verify(mMockHost, times(0)).viewDataChanged(anyInt(), eq(22)); 151 } 152 153 public void testNoUpdatesReceived_queueEmpty() { 154 int widgetId = setupHostAndWidget(); 155 RemoteViews view = new RemoteViews(mPkgName, android.R.layout.simple_list_item_1); 156 mManager.updateAppWidget(widgetId, view); 157 mManager.notifyAppWidgetViewDataChanged(widgetId, 22); 158 mService.stopListening(mPkgName, HOST_ID); 159 160 List<PendingHostUpdate> updates = mService.startListening( 161 mMockHost, mPkgName, HOST_ID, new int[0]).getList(); 162 assertTrue(updates.isEmpty()); 163 } 164 165 /** 166 * Sends dummy widget updates to {@link #mManager}. 167 * @param widgetId widget to update 168 * @param viewIds a list of view ids for which 169 * {@link AppWidgetManager#notifyAppWidgetViewDataChanged} will be called 170 */ 171 private void sendDummyUpdates(int widgetId, int... viewIds) { 172 Random r = new Random(); 173 RemoteViews view = new RemoteViews(mPkgName, android.R.layout.simple_list_item_1); 174 for (int i = r.nextInt(10) + 2; i >= 0; i--) { 175 mManager.updateAppWidget(widgetId, view); 176 } 177 178 for (int viewId : viewIds) { 179 mManager.notifyAppWidgetViewDataChanged(widgetId, viewId); 180 for (int i = r.nextInt(3); i >= 0; i--) { 181 mManager.updateAppWidget(widgetId, view); 182 } 183 } 184 } 185 186 public void testNoUpdatesReceived_queueNonEmpty_noWidgetId() { 187 int widgetId = setupHostAndWidget(); 188 mService.stopListening(mPkgName, HOST_ID); 189 190 sendDummyUpdates(widgetId, 22, 23); 191 List<PendingHostUpdate> updates = mService.startListening( 192 mMockHost, mPkgName, HOST_ID, new int[0]).getList(); 193 assertTrue(updates.isEmpty()); 194 } 195 196 public void testUpdatesReceived_queueNotEmpty_widgetIdProvided() { 197 int widgetId = setupHostAndWidget(); 198 int widgetId2 = bindNewWidget(); 199 mService.stopListening(mPkgName, HOST_ID); 200 201 sendDummyUpdates(widgetId, 22, 23); 202 sendDummyUpdates(widgetId2, 100, 101, 102); 203 204 List<PendingHostUpdate> updates = mService.startListening( 205 mMockHost, mPkgName, HOST_ID, new int[]{widgetId}).getList(); 206 // 3 updates corresponding to the first widget 207 assertEquals(3, updates.size()); 208 } 209 210 public void testUpdatesReceived_queueNotEmpty_widgetIdProvided2() { 211 int widgetId = setupHostAndWidget(); 212 int widgetId2 = bindNewWidget(); 213 mService.stopListening(mPkgName, HOST_ID); 214 215 sendDummyUpdates(widgetId, 22, 23); 216 sendDummyUpdates(widgetId2, 100, 101, 102); 217 218 List<PendingHostUpdate> updates = mService.startListening( 219 mMockHost, mPkgName, HOST_ID, new int[]{widgetId2}).getList(); 220 // 4 updates corresponding to the second widget 221 assertEquals(4, updates.size()); 222 } 223 224 public void testUpdatesReceived_queueNotEmpty_multipleWidgetIdProvided() { 225 int widgetId = setupHostAndWidget(); 226 int widgetId2 = bindNewWidget(); 227 mService.stopListening(mPkgName, HOST_ID); 228 229 sendDummyUpdates(widgetId, 22, 23); 230 sendDummyUpdates(widgetId2, 100, 101, 102); 231 232 List<PendingHostUpdate> updates = mService.startListening( 233 mMockHost, mPkgName, HOST_ID, new int[]{widgetId, widgetId2}).getList(); 234 // 3 updates for first widget and 4 for second 235 assertEquals(7, updates.size()); 236 } 237 238 private int setupHostAndWidget() { 239 List<PendingHostUpdate> updates = mService.startListening( 240 mMockHost, mPkgName, HOST_ID, new int[0]).getList(); 241 assertTrue(updates.isEmpty()); 242 return bindNewWidget(); 243 } 244 245 private int bindNewWidget() { 246 ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class); 247 int widgetId = mService.allocateAppWidgetId(mPkgName, HOST_ID); 248 assertTrue(mManager.bindAppWidgetIdIfAllowed(widgetId, provider)); 249 assertEquals(provider, mManager.getAppWidgetInfo(widgetId).provider); 250 251 return widgetId; 252 } 253 254 private void flushMainThread() throws Exception { 255 CountDownLatch latch = new CountDownLatch(1); 256 new Handler(mTestContext.getMainLooper()).post(latch::countDown); 257 latch.await(); 258 } 259 260 private class TestContext extends ContextWrapper { 261 262 public TestContext() { 263 super(getInstrumentation().getContext()); 264 } 265 266 @Override 267 public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, 268 IntentFilter filter, String broadcastPermission, Handler scheduler) { 269 // ignore. 270 return null; 271 } 272 273 @Override 274 public void unregisterReceiver(BroadcastReceiver receiver) { 275 // ignore. 276 } 277 278 @Override 279 public void enforceCallingOrSelfPermission(String permission, String message) { 280 // ignore. 281 } 282 283 @Override 284 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 285 // ignore. 286 } 287 } 288} 289