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.widget; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertNotNull; 21import static org.junit.Assert.assertNull; 22import static org.junit.Assert.assertTrue; 23 24import android.appwidget.AppWidgetHostView; 25import android.appwidget.AppWidgetManager; 26import android.content.Context; 27import android.support.test.InstrumentationRegistry; 28import android.support.test.filters.SmallTest; 29import android.support.test.runner.AndroidJUnit4; 30import android.view.View; 31import android.view.ViewGroup.OnHierarchyChangeListener; 32 33import com.android.frameworks.coretests.R; 34 35import java.util.ArrayList; 36import java.util.concurrent.CountDownLatch; 37import java.util.concurrent.Executor; 38import java.util.concurrent.Future; 39 40import org.junit.Before; 41import org.junit.Rule; 42import org.junit.Test; 43import org.junit.rules.ExpectedException; 44import org.junit.runner.RunWith; 45 46/** 47 * Tests for AppWidgetHostView 48 */ 49@RunWith(AndroidJUnit4.class) 50@SmallTest 51public class AppWidgetHostViewTest { 52 53 @Rule 54 public final ExpectedException exception = ExpectedException.none(); 55 56 private Context mContext; 57 private String mPackage; 58 private AppWidgetHostView mHostView; 59 60 private ViewAddListener mViewAddListener; 61 private RemoteViews mViews; 62 63 @Before 64 public void setup() { 65 mContext = InstrumentationRegistry.getContext(); 66 mPackage = mContext.getPackageName(); 67 mHostView = new AppWidgetHostView(mContext); 68 mHostView.setAppWidget(0, AppWidgetManager.getInstance( 69 mContext).getInstalledProviders().get(0)); 70 71 mViewAddListener = new ViewAddListener(); 72 mHostView.setOnHierarchyChangeListener(mViewAddListener); 73 74 mViews = new RemoteViews(mPackage, R.layout.remote_views_test); 75 } 76 77 @Test 78 public void syncInflation() { 79 mHostView.updateAppWidget(mViews); 80 assertNotNull(mHostView.findViewById(R.id.image)); 81 } 82 83 @Test 84 public void asyncInflation() throws Exception { 85 RunnableList executor = new RunnableList(); 86 mHostView.setExecutor(executor); 87 88 mHostView.updateAppWidget(mViews); 89 assertNull(mHostView.findViewById(R.id.image)); 90 91 // Task queued. 92 assertEquals(1, executor.size()); 93 94 // Execute the pending task 95 executor.get(0).run(); 96 mViewAddListener.addLatch.await(); 97 assertNotNull(mHostView.findViewById(R.id.image)); 98 } 99 100 @Test 101 public void asyncInflation_cancelled() throws Exception { 102 RunnableList executor = new RunnableList(); 103 mHostView.setExecutor(executor); 104 105 mHostView.updateAppWidget(mViews.clone()); 106 mHostView.updateAppWidget(mViews.clone()); 107 assertNull(mHostView.findViewById(R.id.image)); 108 109 // Tasks queued. 110 assertEquals(2, executor.size()); 111 // First task cancelled 112 assertTrue(((Future) executor.get(0)).isCancelled()); 113 114 // Execute the pending task 115 executor.get(0).run(); 116 executor.get(1).run(); 117 mViewAddListener.addLatch.await(); 118 assertNotNull(mHostView.findViewById(R.id.image)); 119 } 120 121 private static class RunnableList extends ArrayList<Runnable> implements Executor { 122 123 @Override 124 public void execute(Runnable runnable) { 125 add(runnable); 126 } 127 } 128 129 private class ViewAddListener implements OnHierarchyChangeListener { 130 131 public final CountDownLatch addLatch = new CountDownLatch(1); 132 133 134 @Override 135 public void onChildViewAdded(View parent, View child) { 136 addLatch.countDown(); 137 } 138 139 @Override 140 public void onChildViewRemoved(View parent, View child) { 141 } 142 } 143} 144