blob: 05f556c0f98a3b14d5a712958a429bc2382a8703 [file] [log] [blame]
Vishnu Nair83537a72018-07-19 21:27:48 -07001/*
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
17package com.android.server.wm;
18
19import static android.view.Surface.ROTATION_270;
20import static android.view.Surface.ROTATION_90;
21
22import android.graphics.Matrix;
23import android.view.DisplayInfo;
Vishnu Nairec634062018-09-20 20:16:18 -070024import android.view.Surface;
Adrian Roosfaa102f2018-08-02 15:56:15 +020025import android.view.Surface.Rotation;
Vishnu Nairddd80742018-08-21 14:12:46 -070026import android.view.SurfaceControl.Transaction;
Vishnu Nair83537a72018-07-19 21:27:48 -070027
28import com.android.server.wm.utils.CoordinateTransforms;
29
Adrian Roos27a90d22018-07-06 02:39:54 -070030import java.io.PrintWriter;
31import java.io.StringWriter;
32
Vishnu Nair83537a72018-07-19 21:27:48 -070033/**
Vishnu Nairddd80742018-08-21 14:12:46 -070034 * Helper class for seamless rotation.
Vishnu Nair83537a72018-07-19 21:27:48 -070035 *
Vishnu Nairec634062018-09-20 20:16:18 -070036 * Works by transforming the {@link WindowState} back into the old display rotation.
Vishnu Nair83537a72018-07-19 21:27:48 -070037 *
Vishnu Nairec634062018-09-20 20:16:18 -070038 * Uses {@link android.view.SurfaceControl#deferTransactionUntil(Surface, long)} instead of
39 * latching on the buffer size to allow for seamless 180 degree rotations.
Vishnu Nair83537a72018-07-19 21:27:48 -070040 */
Vishnu Nairddd80742018-08-21 14:12:46 -070041public class SeamlessRotator {
Vishnu Nair83537a72018-07-19 21:27:48 -070042
43 private final Matrix mTransform = new Matrix();
44 private final float[] mFloat9 = new float[9];
Adrian Roos27a90d22018-07-06 02:39:54 -070045 private final int mOldRotation;
46 private final int mNewRotation;
Vishnu Nair83537a72018-07-19 21:27:48 -070047
Vishnu Nairec634062018-09-20 20:16:18 -070048 public SeamlessRotator(@Rotation int oldRotation, @Rotation int newRotation, DisplayInfo info) {
Adrian Roos27a90d22018-07-06 02:39:54 -070049 mOldRotation = oldRotation;
50 mNewRotation = newRotation;
51
Vishnu Nair83537a72018-07-19 21:27:48 -070052 final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
53 final int h = flipped ? info.logicalWidth : info.logicalHeight;
54 final int w = flipped ? info.logicalHeight : info.logicalWidth;
55
56 final Matrix tmp = new Matrix();
57 CoordinateTransforms.transformLogicalToPhysicalCoordinates(oldRotation, w, h, mTransform);
58 CoordinateTransforms.transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
59 mTransform.postConcat(tmp);
60 }
61
62 /**
Vishnu Nairec634062018-09-20 20:16:18 -070063 * Applies a transform to the {@link WindowState} surface that undoes the effect of the global
Vishnu Nair83537a72018-07-19 21:27:48 -070064 * display rotation.
65 */
Vishnu Nairec634062018-09-20 20:16:18 -070066 public void unrotate(Transaction transaction, WindowState win) {
67 transaction.setMatrix(win.getSurfaceControl(), mTransform, mFloat9);
68
69 // WindowState sets the position of the window so transform the position and update it.
70 final float[] winSurfacePos = {win.mLastSurfacePosition.x, win.mLastSurfacePosition.y};
71 mTransform.mapPoints(winSurfacePos);
72 transaction.setPosition(win.getSurfaceControl(), winSurfacePos[0], winSurfacePos[1]);
Vishnu Nair83537a72018-07-19 21:27:48 -070073 }
74
75 /**
Adrian Roosfaa102f2018-08-02 15:56:15 +020076 * Returns the rotation of the display before it started rotating.
77 *
78 * @return the old rotation of the display
79 */
80 @Rotation
81 public int getOldRotation() {
82 return mOldRotation;
83 }
84
85 /**
Vishnu Nairec634062018-09-20 20:16:18 -070086 * Removes the transform and sets the previously known surface position for {@link WindowState}
87 * surface that undoes the effect of the global display rotation.
Vishnu Nair83537a72018-07-19 21:27:48 -070088 *
Vishnu Nairec634062018-09-20 20:16:18 -070089 * Removing the transform and the result of the {@link WindowState} layout are both tied to the
90 * {@link WindowState} next frame, such that they apply at the same time the client draws the
Vishnu Nair83537a72018-07-19 21:27:48 -070091 * window in the new orientation.
Vishnu Nairba183352018-11-21 11:16:49 -080092 *
93 * In the case of a rotation timeout, we want to remove the transform immediately and not defer
94 * it.
Vishnu Nair83537a72018-07-19 21:27:48 -070095 */
Vishnu Nairba183352018-11-21 11:16:49 -080096 public void finish(WindowState win, boolean timeout) {
Vishnu Nair83537a72018-07-19 21:27:48 -070097 mTransform.reset();
Vishnu Nairec634062018-09-20 20:16:18 -070098 final Transaction t = win.getPendingTransaction();
99 t.setMatrix(win.mSurfaceControl, mTransform, mFloat9);
100 t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y);
Vishnu Nairba183352018-11-21 11:16:49 -0800101 if (win.mWinAnimator.mSurfaceController != null && !timeout) {
Vishnu Nairec634062018-09-20 20:16:18 -0700102 t.deferTransactionUntil(win.mSurfaceControl,
103 win.mWinAnimator.mSurfaceController.getHandle(), win.getFrameNumber());
104 t.deferTransactionUntil(win.mWinAnimator.mSurfaceController.mSurfaceControl,
105 win.mWinAnimator.mSurfaceController.getHandle(), win.getFrameNumber());
Adrian Roosdcb24ca2018-07-23 15:07:11 +0200106 }
Vishnu Nair83537a72018-07-19 21:27:48 -0700107 }
Adrian Roos27a90d22018-07-06 02:39:54 -0700108
109 public void dump(PrintWriter pw) {
110 pw.print("{old="); pw.print(mOldRotation); pw.print(", new="); pw.print(mNewRotation);
111 pw.print("}");
112 }
113
114 @Override
115 public String toString() {
116 StringWriter sw = new StringWriter();
117 dump(new PrintWriter(sw));
118 return "ForcedSeamlessRotator" + sw.toString();
119 }
Vishnu Nair83537a72018-07-19 21:27:48 -0700120}