1 /* 2 * Copyright (C) 2017 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.systemui.util.leak; 18 19 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 20 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 21 22 import android.annotation.IntDef; 23 import android.content.Context; 24 import android.content.res.Configuration; 25 import android.content.res.Resources; 26 import android.view.Surface; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 31 /** 32 * Utility class that provides device orientation. 33 * 34 * <p>Consider using {@link Surface.Rotation} or add a function that respects device aspect ratio 35 * and {@code android.internal.R.bool.config_reverseDefaultRotation}. 36 * 37 * <p>If you only care about the rotation, use {@link Surface.Rotation}, as it always gives the 38 * counter clock-wise rotation. (e.g. If you have a device that has a charging port at the bottom, 39 * rotating three times in counter clock direction will give you {@link Surface#ROTATION_270} while 40 * having the charging port on the left side of the device.) 41 * 42 * <p>If you need whether the device is in portrait or landscape (or their opposites), please add a 43 * function here that respects the device aspect ratio and 44 * {@code android.internal.R.bool.config_reverseDefaultRotation} together. 45 * 46 * <p>Note that {@code android.internal.R.bool.config_reverseDefaultRotation} does not change the 47 * winding order. In other words, the rotation order (counter clock-wise) will remain the same. It 48 * only flips the device orientation, such that portrait becomes upside down, landscape becomes 49 * seascape. 50 */ 51 public final class RotationUtils { 52 53 public static final int ROTATION_NONE = 0; 54 public static final int ROTATION_LANDSCAPE = 1; 55 public static final int ROTATION_UPSIDE_DOWN = 2; 56 public static final int ROTATION_SEASCAPE = 3; 57 58 // Not to be confused with Surface.Rotation 59 @IntDef(prefix = { "ROTATION_" }, value = { 60 ROTATION_NONE, 61 ROTATION_LANDSCAPE, 62 ROTATION_SEASCAPE, 63 ROTATION_UPSIDE_DOWN, 64 }) 65 @Retention(RetentionPolicy.SOURCE) 66 public @interface Rotation {}; 67 68 /** 69 * @return the current rotation, differentiating between none (rot_0), landscape (rot_90), and 70 * seascape (rot_180). upside down is not distinguished here 71 */ 72 @Rotation getRotation(Context context)73 public static int getRotation(Context context) { 74 int rot = context.getDisplay().getRotation(); 75 if (rot == Surface.ROTATION_90) { 76 return ROTATION_LANDSCAPE; 77 } else if (rot == Surface.ROTATION_270) { 78 return ROTATION_SEASCAPE; 79 } else { 80 return ROTATION_NONE; 81 } 82 } 83 84 /** 85 * @return the current rotation, differentiating between landscape (rot_90), seascape 86 * (rot_270), and upside down (rot_180) 87 */ 88 @Rotation getExactRotation(Context context)89 public static int getExactRotation(Context context) { 90 int rot = context.getDisplay().getRotation(); 91 if (rot == Surface.ROTATION_90) { 92 return ROTATION_LANDSCAPE; 93 } else if (rot == Surface.ROTATION_270) { 94 return ROTATION_SEASCAPE; 95 } else if (rot == Surface.ROTATION_180) { 96 return ROTATION_UPSIDE_DOWN; 97 } else { 98 return ROTATION_NONE; 99 } 100 } 101 102 /** * To string */ toString(@otation int rot)103 public static String toString(@Rotation int rot) { 104 switch (rot) { 105 case ROTATION_NONE: 106 return "None (0)"; 107 case ROTATION_LANDSCAPE: 108 return "Landscape (1)"; 109 case ROTATION_UPSIDE_DOWN: 110 return "Upside down (2)"; 111 case ROTATION_SEASCAPE: 112 return "Seascape (3)"; 113 default: 114 return "Unknown (" + rot + ")"; 115 } 116 } 117 118 /** 119 * Create a Resources using the specified rotation for the configuration. Use this to retrieve 120 * resources in values or values-land without needing an actual rotation to happen. 121 * 122 * @param rot the target rotation for which to create the resources 123 * @param context a context 124 * @return a Resources object configured for the given orientation 125 */ getResourcesForRotation(@otation int rot, Context context)126 public static Resources getResourcesForRotation(@Rotation int rot, Context context) { 127 int orientation; 128 switch (rot) { 129 case ROTATION_NONE: 130 case ROTATION_UPSIDE_DOWN: 131 orientation = ORIENTATION_PORTRAIT; 132 break; 133 case ROTATION_LANDSCAPE: 134 case ROTATION_SEASCAPE: 135 orientation = ORIENTATION_LANDSCAPE; 136 break; 137 138 default: 139 throw new IllegalArgumentException("Unknown rotation: " + rot); 140 } 141 Configuration c = new Configuration(context.getResources().getConfiguration()); 142 c.orientation = orientation; 143 Context rotated = context.createConfigurationContext(c); 144 return rotated.getResources(); 145 } 146 } 147