Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2016 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 
     17 package android.view.cts;
     18 
     19 import static org.junit.Assert.assertFalse;
     20 import static org.junit.Assert.assertNotNull;
     21 import static org.junit.Assert.assertTrue;
     22 import static org.mockito.Mockito.any;
     23 import static org.mockito.Mockito.mock;
     24 import static org.mockito.Mockito.never;
     25 import static org.mockito.Mockito.verify;
     26 
     27 import android.app.Activity;
     28 import android.app.Instrumentation;
     29 import android.graphics.Color;
     30 import android.graphics.Rect;
     31 import android.graphics.drawable.ColorDrawable;
     32 import android.graphics.drawable.Drawable;
     33 import android.platform.test.annotations.Presubmit;
     34 import android.support.test.InstrumentationRegistry;
     35 import android.support.test.annotation.UiThreadTest;
     36 import android.support.test.filters.MediumTest;
     37 import android.support.test.rule.ActivityTestRule;
     38 import android.support.test.runner.AndroidJUnit4;
     39 import android.util.Pair;
     40 import android.view.View;
     41 import android.view.ViewGroup;
     42 import android.view.ViewGroupOverlay;
     43 import android.view.cts.util.DrawingUtils;
     44 
     45 import com.android.compatibility.common.util.CtsTouchUtils;
     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.ArrayList;
     53 import java.util.List;
     54 
     55 @MediumTest
     56 @RunWith(AndroidJUnit4.class)
     57 public class ViewGroupOverlayTest {
     58     private Instrumentation mInstrumentation;
     59     private Activity mActivity;
     60     private ViewGroup mViewGroupWithOverlay;
     61     private ViewGroupOverlay mViewGroupOverlay;
     62 
     63     @Rule
     64     public ActivityTestRule<ViewGroupOverlayCtsActivity> mActivityRule =
     65             new ActivityTestRule<>(ViewGroupOverlayCtsActivity.class);
     66 
     67     @Before
     68     public void setup() {
     69         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     70         mActivity = mActivityRule.getActivity();
     71         mViewGroupWithOverlay = (ViewGroup) mActivity.findViewById(R.id.viewgroup_with_overlay);
     72         mViewGroupOverlay = mViewGroupWithOverlay.getOverlay();
     73     }
     74 
     75     @Presubmit
     76     @Test
     77     public void testBasics() {
     78         DrawingUtils.assertAllPixelsOfColor("Default fill", mViewGroupWithOverlay,
     79                 Color.WHITE, null);
     80         assertNotNull("Overlay is not null", mViewGroupOverlay);
     81     }
     82 
     83     @UiThreadTest
     84     @Test(expected=IllegalArgumentException.class)
     85     public void testAddNullView() {
     86         mViewGroupOverlay.add((View) null);
     87     }
     88 
     89     @UiThreadTest
     90     @Test(expected=IllegalArgumentException.class)
     91     public void testRemoveNullView() {
     92          mViewGroupOverlay.remove((View) null);
     93     }
     94 
     95     @UiThreadTest
     96     @Test
     97     public void testOverlayWithOneView() {
     98         // Add one colored view to the overlay
     99         final View redView = new View(mActivity);
    100         redView.setBackgroundColor(Color.RED);
    101         redView.layout(10, 20, 30, 40);
    102 
    103         mViewGroupOverlay.add(redView);
    104 
    105         final List<Pair<Rect, Integer>> colorRectangles = new ArrayList<>();
    106         colorRectangles.add(new Pair<>(new Rect(10, 20, 30, 40), Color.RED));
    107         DrawingUtils.assertAllPixelsOfColor("Overlay with one red view",
    108                 mViewGroupWithOverlay, Color.WHITE, colorRectangles);
    109 
    110         // Now remove that view from the overlay and test that we're back to pure white fill
    111         mViewGroupOverlay.remove(redView);
    112         DrawingUtils.assertAllPixelsOfColor("Back to default fill", mViewGroupWithOverlay,
    113                 Color.WHITE, null);
    114     }
    115 
    116     @UiThreadTest
    117     @Test
    118     public void testOverlayWithNonOverlappingViews() {
    119         // Add three views to the overlay
    120         final View redView = new View(mActivity);
    121         redView.setBackgroundColor(Color.RED);
    122         redView.layout(10, 20, 30, 40);
    123         final View greenView = new View(mActivity);
    124         greenView.setBackgroundColor(Color.GREEN);
    125         greenView.layout(60, 30, 90, 50);
    126         final View blueView = new View(mActivity);
    127         blueView.setBackgroundColor(Color.BLUE);
    128         blueView.layout(40, 60, 80, 90);
    129 
    130         mViewGroupOverlay.add(redView);
    131         mViewGroupOverlay.add(greenView);
    132         mViewGroupOverlay.add(blueView);
    133 
    134         final List<Pair<Rect, Integer>> colorRectangles = new ArrayList<>();
    135         colorRectangles.add(new Pair<>(new Rect(10, 20, 30, 40), Color.RED));
    136         colorRectangles.add(new Pair<>(new Rect(60, 30, 90, 50), Color.GREEN));
    137         colorRectangles.add(new Pair<>(new Rect(40, 60, 80, 90), Color.BLUE));
    138         DrawingUtils.assertAllPixelsOfColor("Overlay with three views", mViewGroupWithOverlay,
    139                 Color.WHITE, colorRectangles);
    140 
    141         // Remove one of the views from the overlay
    142         mViewGroupOverlay.remove(greenView);
    143         colorRectangles.clear();
    144         colorRectangles.add(new Pair<>(new Rect(10, 20, 30, 40), Color.RED));
    145         colorRectangles.add(new Pair<>(new Rect(40, 60, 80, 90), Color.BLUE));
    146         DrawingUtils.assertAllPixelsOfColor("Overlay with two views", mViewGroupWithOverlay,
    147                 Color.WHITE, colorRectangles);
    148 
    149         // Clear all views from the overlay and test that we're back to pure white fill
    150         mViewGroupOverlay.clear();
    151         DrawingUtils.assertAllPixelsOfColor("Back to default fill", mViewGroupWithOverlay,
    152                 Color.WHITE, null);
    153     }
    154 
    155     @UiThreadTest
    156     @Test
    157     public void testOverlayWithNonOverlappingViewAndDrawable() {
    158         // Add one view and one drawable to the overlay
    159         final View redView = new View(mActivity);
    160         redView.setBackgroundColor(Color.RED);
    161         redView.layout(10, 20, 30, 40);
    162         final Drawable greenDrawable = new ColorDrawable(Color.GREEN);
    163         greenDrawable.setBounds(60, 30, 90, 50);
    164 
    165         mViewGroupOverlay.add(redView);
    166         mViewGroupOverlay.add(greenDrawable);
    167 
    168         final List<Pair<Rect, Integer>> colorRectangles = new ArrayList<>();
    169         colorRectangles.add(new Pair<>(new Rect(10, 20, 30, 40), Color.RED));
    170         colorRectangles.add(new Pair<>(new Rect(60, 30, 90, 50), Color.GREEN));
    171         DrawingUtils.assertAllPixelsOfColor("Overlay with one view and one drawable",
    172                 mViewGroupWithOverlay, Color.WHITE, colorRectangles);
    173 
    174         // Remove the view from the overlay
    175         mViewGroupOverlay.remove(redView);
    176         colorRectangles.clear();
    177         colorRectangles.add(new Pair<>(new Rect(60, 30, 90, 50), Color.GREEN));
    178         DrawingUtils.assertAllPixelsOfColor("Overlay with one drawable", mViewGroupWithOverlay,
    179                 Color.WHITE, colorRectangles);
    180 
    181         // Clear everything from the overlay and test that we're back to pure white fill
    182         mViewGroupOverlay.clear();
    183         DrawingUtils.assertAllPixelsOfColor("Back to default fill", mViewGroupWithOverlay,
    184                 Color.WHITE, null);
    185     }
    186 
    187     @UiThreadTest
    188     @Test
    189     public void testOverlayWithOverlappingViews() {
    190         // Add two overlapping colored views to the overlay
    191         final View redView = new View(mActivity);
    192         redView.setBackgroundColor(Color.RED);
    193         redView.layout(10, 20, 60, 40);
    194         final View greenView = new View(mActivity);
    195         greenView.setBackgroundColor(Color.GREEN);
    196         greenView.layout(30, 20, 80, 40);
    197 
    198         mViewGroupOverlay.add(redView);
    199         mViewGroupOverlay.add(greenView);
    200 
    201         // Our overlay views overlap in horizontal 30-60 range. Here we test that the
    202         // second view is the one that is drawn last in that range.
    203         final List<Pair<Rect, Integer>> colorRectangles = new ArrayList<>();
    204         colorRectangles.add(new Pair<>(new Rect(10, 20, 30, 40), Color.RED));
    205         colorRectangles.add(new Pair<>(new Rect(30, 20, 80, 40), Color.GREEN));
    206         DrawingUtils.assertAllPixelsOfColor("Overlay with two drawables", mViewGroupWithOverlay,
    207                 Color.WHITE, colorRectangles);
    208 
    209         // Remove the second view from the overlay
    210         mViewGroupOverlay.remove(greenView);
    211         colorRectangles.clear();
    212         colorRectangles.add(new Pair<>(new Rect(10, 20, 60, 40), Color.RED));
    213         DrawingUtils.assertAllPixelsOfColor("Overlay with one drawable", mViewGroupWithOverlay,
    214                 Color.WHITE, colorRectangles);
    215 
    216         // Clear all views from the overlay and test that we're back to pure white fill
    217         mViewGroupOverlay.clear();
    218         DrawingUtils.assertAllPixelsOfColor("Back to default fill", mViewGroupWithOverlay,
    219                 Color.WHITE, null);
    220     }
    221 
    222     @UiThreadTest
    223     @Test
    224     public void testOverlayWithOverlappingViewAndDrawable() {
    225         // Add two overlapping colored views to the overlay
    226         final Drawable redDrawable = new ColorDrawable(Color.RED);
    227         redDrawable.setBounds(10, 20, 60, 40);
    228         final View greenView = new View(mActivity);
    229         greenView.setBackgroundColor(Color.GREEN);
    230         greenView.layout(30, 20, 80, 40);
    231 
    232         mViewGroupOverlay.add(redDrawable);
    233         mViewGroupOverlay.add(greenView);
    234 
    235         // Our overlay views overlap in horizontal 30-60 range. Even though the green view was
    236         // added after the red drawable, *all* overlay drawables are drawn after the overlay views.
    237         // So in the overlap range we expect color red
    238         final List<Pair<Rect, Integer>> colorRectangles = new ArrayList<>();
    239         colorRectangles.add(new Pair<>(new Rect(10, 20, 60, 40), Color.RED));
    240         colorRectangles.add(new Pair<>(new Rect(60, 20, 80, 40), Color.GREEN));
    241         DrawingUtils.assertAllPixelsOfColor("Overlay with one view and one drawable",
    242                 mViewGroupWithOverlay, Color.WHITE, colorRectangles);
    243 
    244         // Remove the drawable from the overlay
    245         mViewGroupOverlay.remove(redDrawable);
    246         colorRectangles.clear();
    247         colorRectangles.add(new Pair<>(new Rect(30, 20, 80, 40), Color.GREEN));
    248         DrawingUtils.assertAllPixelsOfColor("Overlay with one view", mViewGroupWithOverlay,
    249                 Color.WHITE, colorRectangles);
    250 
    251         // Clear all views from the overlay and test that we're back to pure white fill
    252         mViewGroupOverlay.clear();
    253         DrawingUtils.assertAllPixelsOfColor("Back to default fill", mViewGroupWithOverlay,
    254                 Color.WHITE, null);
    255     }
    256 
    257     @Test
    258     public void testOverlayViewNoClicks() throws Throwable {
    259         // Add one colored view with mock click listener to the overlay
    260         final View redView = new View(mActivity);
    261         redView.setBackgroundColor(Color.RED);
    262         final View.OnClickListener mockClickListener = mock(View.OnClickListener.class);
    263         redView.setOnClickListener(mockClickListener);
    264         redView.layout(10, 20, 30, 40);
    265 
    266         mActivityRule.runOnUiThread(() -> mViewGroupOverlay.add(redView));
    267 
    268         // Emulate a tap in the center of the view we've added to the overlay
    269         CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mViewGroupWithOverlay);
    270 
    271         // Verify that our mock listener hasn't been called
    272         verify(mockClickListener, never()).onClick(any(View.class));
    273     }
    274 
    275     @UiThreadTest
    276     @Test
    277     public void testOverlayReparenting() {
    278         // Find the view that we're about to add to our overlay
    279         final View level2View = mViewGroupWithOverlay.findViewById(R.id.level2);
    280         final View level3View = level2View.findViewById(R.id.level3);
    281 
    282         assertTrue(level2View == level3View.getParent());
    283 
    284         // Set the fill of this view to red
    285         level3View.setBackgroundColor(Color.RED);
    286         mViewGroupOverlay.add(level3View);
    287 
    288         // At this point we expect the view that was added to the overlay to have been removed
    289         // from its original parent
    290         assertFalse(level2View == level3View.getParent());
    291 
    292         // Check the expected visual appearance of our view group. We expect that the view that
    293         // was added to the overlay to maintain its relative location inside the activity.
    294         final List<Pair<Rect, Integer>> colorRectangles = new ArrayList<>();
    295         colorRectangles.add(new Pair<>(new Rect(65, 60, 85, 90), Color.RED));
    296         DrawingUtils.assertAllPixelsOfColor("Empty overlay before adding grandchild",
    297                 mViewGroupWithOverlay, Color.WHITE, colorRectangles);
    298 
    299     }
    300 }
    301