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