1 /* 2 * Copyright (C) 2024 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; 18 19 import android.annotation.NonNull; 20 import android.graphics.Point; 21 import android.graphics.Rect; 22 23 /** 24 * Some utility methods used by different Letterbox implementations. 25 */ 26 class AppCompatLetterboxUtils { 27 /** 28 * Provides the position of the top left letterbox area in the display coordinate system. 29 * 30 * @param activity The Letterboxed activity. 31 * @param outLetterboxPosition InOut parameter that will contain the desired letterbox position. 32 */ calculateLetterboxPosition(@onNull ActivityRecord activity, @NonNull Point outLetterboxPosition)33 static void calculateLetterboxPosition(@NonNull ActivityRecord activity, 34 @NonNull Point outLetterboxPosition) { 35 if (!activity.mAppCompatController.getLetterboxPolicy().isRunning()) { 36 outLetterboxPosition.set(0, 0); 37 return; 38 } 39 activity.getPosition(outLetterboxPosition); 40 } 41 42 /** 43 * Provides all the available space, in display coordinate, to fill with the letterboxed 44 * activity and the letterbox areas. 45 * 46 * @param activity The Letterboxed activity. 47 * @param outOuterBounds InOut parameter that will contain the outer bounds for the letterboxed 48 * activity. 49 */ calculateLetterboxOuterBounds(@onNull ActivityRecord activity, @NonNull Rect outOuterBounds)50 static void calculateLetterboxOuterBounds(@NonNull ActivityRecord activity, 51 @NonNull Rect outOuterBounds) { 52 if (!activity.mAppCompatController.getLetterboxPolicy().isRunning()) { 53 outOuterBounds.setEmpty(); 54 return; 55 } 56 // Get the bounds of the "space-to-fill". The transformed bounds have the highest 57 // priority because the activity is launched in a rotated environment. In multi-window 58 // mode, the taskFragment-level represents this for both split-screen 59 // and activity-embedding. In fullscreen-mode, the task container does 60 // (since the orientation letterbox is also applied to the task). 61 final Rect transformedBounds = 62 activity.getFixedRotationTransformDisplayBounds(); 63 outOuterBounds.set(transformedBounds != null 64 ? transformedBounds 65 : activity.inMultiWindowMode() 66 ? activity.getTaskFragment().getBounds() 67 : activity.getRootTask().getParent().getBounds()); 68 } 69 70 /** 71 * Provides the inner bounds for the letterboxed activity in display coordinates. This is the 72 * space the letterboxed activity will use. 73 * 74 * @param activity The Letterboxed activity. 75 * @param outInnerBounds InOut parameter that will contain the inner bounds for the letterboxed 76 * activity. 77 */ calculateLetterboxInnerBounds(@onNull ActivityRecord activity, @NonNull WindowState window, @NonNull Rect outInnerBounds)78 static void calculateLetterboxInnerBounds(@NonNull ActivityRecord activity, 79 @NonNull WindowState window, @NonNull Rect outInnerBounds) { 80 if (!activity.mAppCompatController.getLetterboxPolicy().isRunning()) { 81 outInnerBounds.setEmpty(); 82 return; 83 } 84 // In case of translucent activities an option is to use the WindowState#getFrame() of 85 // the first opaque activity beneath. In some cases (e.g. an opaque activity is using 86 // non MATCH_PARENT layouts or a Dialog theme) this might not provide the correct 87 // information and in particular it might provide a value for a smaller area making 88 // the letterbox overlap with the translucent activity's frame. 89 // If we use WindowState#getFrame() for the translucent activity's letterbox inner 90 // frame, the letterbox will then be overlapped with the translucent activity's frame. 91 // Because the surface layer of letterbox is lower than an activity window, this 92 // won't crop the content, but it may affect other features that rely on values stored 93 // in mLetterbox, e.g. transitions, a status bar scrim and recents preview in Launcher 94 // For this reason we use ActivityRecord#getBounds() that the translucent activity 95 // inherits from the first opaque activity beneath and also takes care of the scaling 96 // in case of activities in size compat mode. 97 final TransparentPolicy transparentPolicy = 98 activity.mAppCompatController.getTransparentPolicy(); 99 outInnerBounds.set( 100 transparentPolicy.isRunning() ? activity.getBounds() : window.getFrame()); 101 } 102 } 103