• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
setUp()41     protected void setUp() throws Exception {
42         super.setUp();
43         mInvariantProfile = new InvariantDeviceProfile(getContext());
44         mPredefinedDeviceProfiles = mInvariantProfile.getPredefinedDeviceProfiles();
45     }
46 
47     @Override
tearDown()48     protected void tearDown() throws Exception {
49         // Nothing to tear down as this class only tests static methods.
50     }
51 
testFindClosestDeviceProfile2()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      */
testInvInterpolation()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 
createInterpolatedPoints(PointF a, PointF b, float numPts)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      */
test_hammerhead()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      */
testQsbNormalHeight()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      */
testQsbTallHeight()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