1 /* 2 * Copyright (C) 2021 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.wm.shell.util; 18 19 import android.graphics.Point; 20 import android.util.RotationUtils; 21 import android.view.SurfaceControl; 22 23 /** 24 * Utility class that takes care of rotating unchanging child-surfaces to match the parent rotation 25 * during a transition animation. This gives the illusion that the child surfaces haven't rotated 26 * relative to the screen. 27 */ 28 public class CounterRotator { 29 private SurfaceControl mSurface = null; 30 31 /** Gets the surface with the counter-rotation. */ getSurface()32 public SurfaceControl getSurface() { 33 return mSurface; 34 } 35 36 /** 37 * Sets up this rotator. 38 * 39 * @param rotateDelta is the forward rotation change (the rotation the display is making). 40 * @param parentW (and H) Is the size of the rotating parent after the rotation. 41 */ setup(SurfaceControl.Transaction t, SurfaceControl parent, int rotateDelta, float parentW, float parentH)42 public void setup(SurfaceControl.Transaction t, SurfaceControl parent, int rotateDelta, 43 float parentW, float parentH) { 44 if (rotateDelta == 0) return; 45 mSurface = new SurfaceControl.Builder() 46 .setName("Transition Unrotate") 47 .setContainerLayer() 48 .setParent(parent) 49 .build(); 50 // Rotate forward to match the new rotation (rotateDelta is the forward rotation the parent 51 // already took). Child surfaces will be in the old rotation relative to the new parent 52 // rotation, so we need to forward-rotate the child surfaces to match. 53 RotationUtils.rotateSurface(t, mSurface, rotateDelta); 54 final Point tmpPt = new Point(0, 0); 55 // parentW/H are the size in the END rotation, the rotation utilities expect the starting 56 // size. So swap them if necessary 57 if ((rotateDelta % 2) != 0) { 58 final float w = parentW; 59 parentW = parentH; 60 parentH = w; 61 } 62 RotationUtils.rotatePoint(tmpPt, rotateDelta, (int) parentW, (int) parentH); 63 t.setPosition(mSurface, tmpPt.x, tmpPt.y); 64 t.show(mSurface); 65 } 66 67 /** 68 * Adds a surface that needs to be counter-rotate. 69 */ addChild(SurfaceControl.Transaction t, SurfaceControl child)70 public void addChild(SurfaceControl.Transaction t, SurfaceControl child) { 71 if (mSurface == null) return; 72 t.reparent(child, mSurface); 73 } 74 75 /** 76 * Clean-up. Since finishTransaction should reset all change leashes, we only need to remove the 77 * counter rotation surface. 78 */ cleanUp(SurfaceControl.Transaction finishTransaction)79 public void cleanUp(SurfaceControl.Transaction finishTransaction) { 80 if (mSurface == null) return; 81 finishTransaction.remove(mSurface); 82 } 83 } 84