Home | History | Annotate | Download | only in launcher3
      1 /*
      2  * Copyright (C) 2015 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;
     17 
     18 import android.content.res.Resources;
     19 import android.graphics.Point;
     20 import android.graphics.PointF;
     21 import android.graphics.Rect;
     22 import android.test.AndroidTestCase;
     23 import android.test.suitebuilder.annotation.SmallTest;
     24 import android.util.Log;
     25 
     26 import java.util.ArrayList;
     27 
     28 /**
     29  * Tests the {@link DeviceProfile} and {@link InvariantDeviceProfile}.
     30  */
     31 @SmallTest
     32 public class InvariantDeviceProfileTest extends AndroidTestCase {
     33 
     34     private static final String TAG = "DeviceProfileTest";
     35     private static final boolean DEBUG = false;
     36 
     37     private InvariantDeviceProfile mInvariantProfile;
     38     private ArrayList<InvariantDeviceProfile> mPredefinedDeviceProfiles;
     39 
     40     @Override
     41     protected void setUp() throws Exception {
     42         super.setUp();
     43         mInvariantProfile = new InvariantDeviceProfile(getContext());
     44         mPredefinedDeviceProfiles = mInvariantProfile.getPredefinedDeviceProfiles();
     45     }
     46 
     47     @Override
     48     protected void tearDown() throws Exception {
     49         // Nothing to tear down as this class only tests static methods.
     50     }
     51 
     52     public void testFindClosestDeviceProfile2() {
     53         for (InvariantDeviceProfile idf: mPredefinedDeviceProfiles) {
     54             ArrayList<InvariantDeviceProfile> predefinedProfilesCopy =
     55                     new ArrayList<>(mPredefinedDeviceProfiles);
     56             ArrayList<InvariantDeviceProfile> closestProfiles =
     57                     mInvariantProfile.findClosestDeviceProfiles(
     58                             idf.minWidthDps, idf.minHeightDps, predefinedProfilesCopy
     59                     );
     60             assertTrue(closestProfiles.get(0).equals(idf));
     61         }
     62     }
     63 
     64     /**
     65      * Used to print out how the invDistWeightedInterpolate works between device profiles to
     66      * tweak the two constants that control how the interpolation curve is shaped.
     67      */
     68     public void testInvInterpolation() {
     69 
     70         InvariantDeviceProfile p1 = mPredefinedDeviceProfiles.get(7); // e.g., Large Phone
     71         InvariantDeviceProfile p2 = mPredefinedDeviceProfiles.get(8); // e.g., Nexus 7
     72 
     73         ArrayList<PointF> pts = createInterpolatedPoints(
     74                 new PointF(p1.minWidthDps, p1.minHeightDps),
     75                 new PointF(p2.minWidthDps, p2.minHeightDps),
     76                 20f);
     77 
     78         for (int i = 0; i < pts.size(); i++) {
     79             ArrayList<InvariantDeviceProfile> closestProfiles =
     80                     mInvariantProfile.findClosestDeviceProfiles(
     81                             pts.get(i).x, pts.get(i).y, mPredefinedDeviceProfiles);
     82             InvariantDeviceProfile result =
     83                     mInvariantProfile.invDistWeightedInterpolate(
     84                             pts.get(i).x, pts.get(i).y, closestProfiles);
     85             if (DEBUG) {
     86                 Log.d(TAG, String.format("width x height = (%f, %f)] iconSize = %f",
     87                         pts.get(i).x, pts.get(i).y, result.iconSize));
     88             }
     89         }
     90     }
     91 
     92     private ArrayList<PointF> createInterpolatedPoints(PointF a, PointF b, float numPts) {
     93         ArrayList<PointF> result = new ArrayList<PointF>();
     94         result.add(a);
     95         for (float i = 1; i < numPts; i = i + 1.0f) {
     96             result.add(new PointF((b.x * i +  a.x * (numPts - i)) / numPts,
     97                     (b.y * i + a.y * (numPts - i)) / numPts));
     98         }
     99         result.add(b);
    100         return result;
    101     }
    102 
    103     /**
    104      * Ensures that system calls (e.g., WindowManager, DisplayMetrics) that require contexts are
    105      * properly working to generate minimum width and height of the display.
    106      */
    107     public void test_hammerhead() {
    108         if (!android.os.Build.DEVICE.equals("hammerhead")) {
    109             return;
    110         }
    111         assertEquals(4, mInvariantProfile.numRows);
    112         assertEquals(4, mInvariantProfile.numColumns);
    113         assertEquals(5, mInvariantProfile.numHotseatIcons);
    114     }
    115 
    116     // Add more tests for other devices, however, running them once on a single device is enough
    117     // for verifying that for a platform version, the WindowManager and DisplayMetrics is
    118     // working as intended.
    119 
    120     /**
    121      * Make sure that the height for the QSB is what we expect in normal mode.
    122      */
    123     public void testQsbNormalHeight() {
    124         Resources resources = getContext().getResources();
    125         DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
    126         DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
    127         landscapeProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL);
    128         portraitProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL);
    129         Rect portraitBounds = portraitProfile.getSearchBarBounds(true); // RTL shouldn't matter.
    130         int portraitHeight = (int) Utilities.dpiFromPx(portraitBounds.height(),
    131                 resources.getDisplayMetrics());
    132         Rect landscapeBounds = landscapeProfile.getSearchBarBounds(true); // RTL shouldn't matter.
    133         int landscapeHeight = (int) Utilities.dpiFromPx(landscapeBounds.height(),
    134                 resources.getDisplayMetrics());
    135         if (portraitProfile.isTablet) {
    136             assertEquals(8 + 48 + 24, portraitHeight);
    137         } else {
    138             assertEquals(8 + 48 + 12, portraitHeight);
    139         }
    140         // Make sure the height that we pass in the widget options bundle is the height of the
    141         // search bar + 8dps padding top and bottom.
    142         Point portraitDimens = portraitProfile.getSearchBarDimensForWidgetOpts(resources);
    143         int portraitWidgetOptsHeight = portraitDimens.y;
    144         Point landscapeDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(resources);
    145         int landscapeWidgetOptsHeight = landscapeDimens.y;
    146         assertEquals(8 + 48 + 8, (int) Utilities.dpiFromPx(portraitWidgetOptsHeight,
    147                 resources.getDisplayMetrics()));
    148         if (!landscapeProfile.isVerticalBarLayout()) {
    149             assertEquals(portraitHeight, landscapeHeight);
    150             assertEquals(portraitWidgetOptsHeight, landscapeWidgetOptsHeight);
    151         }
    152     }
    153 
    154     /**
    155      * Make sure that the height for the QSB is what we expect in tall mode.
    156      */
    157     public void testQsbTallHeight() {
    158         Resources resources = getContext().getResources();
    159         DeviceProfile landscapeProfile = mInvariantProfile.landscapeProfile;
    160         DeviceProfile portraitProfile = mInvariantProfile.portraitProfile;
    161         landscapeProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL);
    162         portraitProfile.setSearchBarHeight(LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL);
    163         Rect portraitBounds = portraitProfile.getSearchBarBounds(true); // RTL shouldn't matter.
    164         int portraitHeight = (int) Utilities.dpiFromPx(portraitBounds.height(),
    165                 resources.getDisplayMetrics());
    166         Rect landscapeBounds = landscapeProfile.getSearchBarBounds(true); // RTL shouldn't matter.
    167         int landscapeHeight = (int) Utilities.dpiFromPx(landscapeBounds.height(),
    168                 resources.getDisplayMetrics());
    169         if (portraitProfile.isPhone) {
    170             // This fails on some devices due to http://b/26884580 (portraitHeight is 101, not 100).
    171             assertEquals(4 + 94 + 2, portraitHeight);
    172         } else {
    173             assertEquals(8 + 94 + 24, portraitHeight);
    174         }
    175         // Make sure the height that we pass in the widget options bundle is the height of the
    176         // search bar + 8dps padding top and bottom.
    177         Point portraitDimens = portraitProfile.getSearchBarDimensForWidgetOpts(resources);
    178         int portraitWidgetOptsHeight = portraitDimens.y;
    179         Point landscapeDimens = landscapeProfile.getSearchBarDimensForWidgetOpts(resources);
    180         int landscapeWidgetOptsHeight = landscapeDimens.y;
    181         assertEquals(8 + 94 + 8, (int) Utilities.dpiFromPx(portraitWidgetOptsHeight,
    182                 resources.getDisplayMetrics()));
    183         if (!landscapeProfile.isVerticalBarLayout()) {
    184             assertEquals(portraitHeight, landscapeHeight);
    185             assertEquals(portraitWidgetOptsHeight, landscapeWidgetOptsHeight);
    186         }
    187     }
    188 }
    189