1 /* 2 * Copyright (C) 2018 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 com.android.server.wm.utils; 18 19 import static android.view.Surface.ROTATION_0; 20 import static android.view.Surface.ROTATION_180; 21 import static android.view.Surface.ROTATION_270; 22 import static android.view.Surface.ROTATION_90; 23 24 import static com.android.server.wm.utils.CoordinateTransforms.computeRotationMatrix; 25 import static com.android.server.wm.utils.CoordinateTransforms.transformLogicalToPhysicalCoordinates; 26 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates; 27 import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation; 28 29 import static org.hamcrest.Matchers.is; 30 import static org.junit.Assert.*; 31 32 import android.graphics.Matrix; 33 import android.graphics.Point; 34 import android.graphics.PointF; 35 import android.platform.test.annotations.Presubmit; 36 import android.view.DisplayInfo; 37 38 import org.junit.Before; 39 import org.junit.Rule; 40 import org.junit.Test; 41 import org.junit.rules.ErrorCollector; 42 43 /** 44 * Build/Install/Run: 45 * atest WmTests:CoordinateTransformsTest 46 */ 47 @Presubmit 48 public class CoordinateTransformsTest { 49 50 private static final int W = 200; 51 private static final int H = 400; 52 53 private final Matrix mMatrix = new Matrix(); 54 private final Matrix mMatrix2 = new Matrix(); 55 56 @Rule 57 public final ErrorCollector mErrorCollector = new ErrorCollector(); 58 59 @Before setUp()60 public void setUp() throws Exception { 61 mMatrix.setTranslate(0xdeadbeef, 0xdeadbeef); 62 mMatrix2.setTranslate(0xbeefdead, 0xbeefdead); 63 } 64 65 @Test transformPhysicalToLogicalCoordinates_rot0()66 public void transformPhysicalToLogicalCoordinates_rot0() { 67 transformPhysicalToLogicalCoordinates(ROTATION_0, W, H, mMatrix); 68 assertThat(mMatrix, is(Matrix.IDENTITY_MATRIX)); 69 } 70 71 @Test transformPhysicalToLogicalCoordinates_rot90()72 public void transformPhysicalToLogicalCoordinates_rot90() { 73 transformPhysicalToLogicalCoordinates(ROTATION_90, W, H, mMatrix); 74 75 checkPoint(0, 0).transformsTo(0, W); 76 checkPoint(W, H).transformsTo(H, 0); 77 } 78 79 @Test transformPhysicalToLogicalCoordinates_rot180()80 public void transformPhysicalToLogicalCoordinates_rot180() { 81 transformPhysicalToLogicalCoordinates(ROTATION_180, W, H, mMatrix); 82 83 checkPoint(0, 0).transformsTo(W, H); 84 checkPoint(W, H).transformsTo(0, 0); 85 } 86 87 @Test transformPhysicalToLogicalCoordinates_rot270()88 public void transformPhysicalToLogicalCoordinates_rot270() { 89 transformPhysicalToLogicalCoordinates(ROTATION_270, W, H, mMatrix); 90 91 checkPoint(0, 0).transformsTo(H, 0); 92 checkPoint(W, H).transformsTo(0, W); 93 } 94 95 @Test transformLogicalToPhysicalCoordinates_rot0()96 public void transformLogicalToPhysicalCoordinates_rot0() { 97 transformLogicalToPhysicalCoordinates(ROTATION_0, W, H, mMatrix); 98 assertThat(mMatrix, is(Matrix.IDENTITY_MATRIX)); 99 } 100 101 @Test transformLogicalToPhysicalCoordinates_rot90()102 public void transformLogicalToPhysicalCoordinates_rot90() { 103 transformLogicalToPhysicalCoordinates(ROTATION_90, W, H, mMatrix); 104 105 checkPoint(0, W).transformsTo(0, 0); 106 checkPoint(H, 0).transformsTo(W, H); 107 } 108 109 @Test transformLogicalToPhysicalCoordinates_rot180()110 public void transformLogicalToPhysicalCoordinates_rot180() { 111 transformLogicalToPhysicalCoordinates(ROTATION_180, W, H, mMatrix); 112 113 checkPoint(W, H).transformsTo(0, 0); 114 checkPoint(0, 0).transformsTo(W, H); 115 } 116 117 @Test transformLogicalToPhysicalCoordinates_rot270()118 public void transformLogicalToPhysicalCoordinates_rot270() { 119 transformLogicalToPhysicalCoordinates(ROTATION_270, W, H, mMatrix); 120 121 checkPoint(H, 0).transformsTo(0, 0); 122 checkPoint(0, W).transformsTo(W, H); 123 } 124 125 @Test transformLogicalToPhysicalCoordinatesIsInverse_rot0()126 public void transformLogicalToPhysicalCoordinatesIsInverse_rot0() { 127 transformLogicalToPhysicalCoordinates(ROTATION_0, W, H, mMatrix); 128 transformPhysicalToLogicalCoordinates(ROTATION_0, W, H, mMatrix2); 129 130 assertMatricesAreInverses(mMatrix, mMatrix2); 131 } 132 133 @Test transformLogicalToPhysicalCoordinatesIsInverse_rot90()134 public void transformLogicalToPhysicalCoordinatesIsInverse_rot90() { 135 transformLogicalToPhysicalCoordinates(ROTATION_90, W, H, mMatrix); 136 transformPhysicalToLogicalCoordinates(ROTATION_90, W, H, mMatrix2); 137 138 assertMatricesAreInverses(mMatrix, mMatrix2); 139 } 140 141 @Test transformLogicalToPhysicalCoordinatesIsInverse_rot180()142 public void transformLogicalToPhysicalCoordinatesIsInverse_rot180() { 143 transformLogicalToPhysicalCoordinates(ROTATION_180, W, H, mMatrix); 144 transformPhysicalToLogicalCoordinates(ROTATION_180, W, H, mMatrix2); 145 146 assertMatricesAreInverses(mMatrix, mMatrix2); 147 } 148 149 @Test transformLogicalToPhysicalCoordinatesIsInverse_rot270()150 public void transformLogicalToPhysicalCoordinatesIsInverse_rot270() { 151 transformLogicalToPhysicalCoordinates(ROTATION_270, W, H, mMatrix); 152 transformPhysicalToLogicalCoordinates(ROTATION_270, W, H, mMatrix2); 153 154 assertMatricesAreInverses(mMatrix, mMatrix2); 155 } 156 157 @Test transformBetweenRotations_rot180_rot270()158 public void transformBetweenRotations_rot180_rot270() { 159 // W,H are flipped, because they need to be given in the new orientation, i.e. ROT_270. 160 transformToRotation(ROTATION_180, ROTATION_270, H, W, mMatrix); 161 162 checkPoint(0, 0).transformsTo(0, W); 163 checkPoint(W, H).transformsTo(H, 0); 164 } 165 166 @Test transformBetweenRotations_rot90_rot0()167 public void transformBetweenRotations_rot90_rot0() { 168 transformToRotation(ROTATION_180, ROTATION_270, W, H, mMatrix); 169 170 checkPoint(0, 0).transformsTo(0, H); 171 // H,W is bottom right in ROT_90 172 checkPoint(H, W).transformsTo(W, 0); 173 } 174 175 @Test transformBetweenRotations_displayInfo()176 public void transformBetweenRotations_displayInfo() { 177 final DisplayInfo di = new DisplayInfo(); 178 di.rotation = ROTATION_90; 179 di.logicalWidth = H; // dimensions are flipped in ROT_90 180 di.logicalHeight = W; 181 transformToRotation(ROTATION_180, ROTATION_270, di, mMatrix); 182 183 // W,H are flipped, because they need to be given in the new orientation, i.e. ROT_270. 184 transformToRotation(ROTATION_180, ROTATION_270, H, W, mMatrix2); 185 186 assertEquals(mMatrix2, mMatrix); 187 } 188 189 @Test rotate_0_bottomRight()190 public void rotate_0_bottomRight() { 191 computeRotationMatrix(ROTATION_0, W, H, mMatrix); 192 PointF newPoints = checkMappedPoints(W, H); 193 assertEquals(W, newPoints.x, 0); 194 assertEquals(H, newPoints.y, 0); 195 } 196 197 @Test rotate_90_bottomRight()198 public void rotate_90_bottomRight() { 199 computeRotationMatrix(ROTATION_90, W, H, mMatrix); 200 PointF newPoints = checkMappedPoints(W, H); 201 assertEquals(0, newPoints.x, 0); 202 assertEquals(W, newPoints.y, 0); 203 } 204 205 @Test rotate_180_bottomRight()206 public void rotate_180_bottomRight() { 207 computeRotationMatrix(ROTATION_180, W, H, mMatrix); 208 PointF newPoints = checkMappedPoints(W, H); 209 assertEquals(0, newPoints.x, 0); 210 assertEquals(0, newPoints.y, 0); 211 } 212 213 @Test rotate_270_bottomRight()214 public void rotate_270_bottomRight() { 215 computeRotationMatrix(ROTATION_270, W, H, mMatrix); 216 PointF newPoints = checkMappedPoints(W, H); 217 assertEquals(H, newPoints.x, 0); 218 assertEquals(0, newPoints.y, 0); 219 } 220 checkMappedPoints(int x, int y)221 private PointF checkMappedPoints(int x, int y) { 222 final float[] fs = new float[] {x, y}; 223 mMatrix.mapPoints(fs); 224 return new PointF(fs[0], fs[1]); 225 } 226 assertMatricesAreInverses(Matrix matrix, Matrix matrix2)227 private void assertMatricesAreInverses(Matrix matrix, Matrix matrix2) { 228 final Matrix concat = new Matrix(); 229 concat.setConcat(matrix, matrix2); 230 assertTrue("expected identity, but was: " + concat, concat.isIdentity()); 231 } 232 checkPoint(int x, int y)233 private TransformPointAssertable checkPoint(int x, int y) { 234 final Point devicePoint = new Point(x, y); 235 final float[] fs = new float[] {x, y}; 236 mMatrix.mapPoints(fs); 237 final PointF transformedPoint = new PointF(fs[0], fs[1]); 238 239 return (expectedX, expectedY) -> { 240 mErrorCollector.checkThat("t(" + devicePoint + ")", 241 transformedPoint, is(new PointF(expectedX, expectedY))); 242 }; 243 } 244 245 public interface TransformPointAssertable { transformsTo(int x, int y)246 void transformsTo(int x, int y); 247 } 248 } 249