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.systemui.shared.recents.utilities; 18 19 import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME; 20 import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE; 21 import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 23 24 import android.annotation.TargetApi; 25 import android.app.StatusBarManager.NavbarFlags; 26 import android.content.Context; 27 import android.content.res.Resources; 28 import android.graphics.Color; 29 import android.graphics.Rect; 30 import android.inputmethodservice.InputMethodService; 31 import android.inputmethodservice.InputMethodService.BackDispositionMode; 32 import android.os.Build; 33 import android.os.Handler; 34 import android.os.Message; 35 import android.util.DisplayMetrics; 36 import android.view.Surface; 37 import android.view.WindowManager; 38 39 import com.android.systemui.shared.recents.model.Task; 40 import com.android.systemui.utils.windowmanager.WindowManagerUtils; 41 42 /* Common code */ 43 public class Utilities { 44 45 private static final float TABLET_MIN_DPS = 600; 46 47 /** 48 * Posts a runnable on a handler at the front of the queue ignoring any sync barriers. 49 */ postAtFrontOfQueueAsynchronously(Handler h, Runnable r)50 public static void postAtFrontOfQueueAsynchronously(Handler h, Runnable r) { 51 Message msg = h.obtainMessage().setCallback(r); 52 h.sendMessageAtFrontOfQueue(msg); 53 } 54 isRotationAnimationCCW(int from, int to)55 public static boolean isRotationAnimationCCW(int from, int to) { 56 // All 180deg WM rotation animations are CCW, match that 57 if (from == Surface.ROTATION_0 && to == Surface.ROTATION_90) return false; 58 if (from == Surface.ROTATION_0 && to == Surface.ROTATION_180) return true; //180d so CCW 59 if (from == Surface.ROTATION_0 && to == Surface.ROTATION_270) return true; 60 if (from == Surface.ROTATION_90 && to == Surface.ROTATION_0) return true; 61 if (from == Surface.ROTATION_90 && to == Surface.ROTATION_180) return false; 62 if (from == Surface.ROTATION_90 && to == Surface.ROTATION_270) return true; //180d so CCW 63 if (from == Surface.ROTATION_180 && to == Surface.ROTATION_0) return true; //180d so CCW 64 if (from == Surface.ROTATION_180 && to == Surface.ROTATION_90) return true; 65 if (from == Surface.ROTATION_180 && to == Surface.ROTATION_270) return false; 66 if (from == Surface.ROTATION_270 && to == Surface.ROTATION_0) return false; 67 if (from == Surface.ROTATION_270 && to == Surface.ROTATION_90) return true; //180d so CCW 68 if (from == Surface.ROTATION_270 && to == Surface.ROTATION_180) return true; 69 return false; // Default 70 } 71 72 /** 73 * Compares the ratio of two quantities and returns whether that ratio is greater than the 74 * provided bound. Order of quantities does not matter. Bound should be a decimal representation 75 * of a percentage. 76 */ isRelativePercentDifferenceGreaterThan(float first, float second, float bound)77 public static boolean isRelativePercentDifferenceGreaterThan(float first, float second, 78 float bound) { 79 return (Math.abs(first - second) / Math.abs((first + second) / 2.0f)) > bound; 80 } 81 82 /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */ computeContrastBetweenColors(int bg, int fg)83 public static float computeContrastBetweenColors(int bg, int fg) { 84 float bgR = Color.red(bg) / 255f; 85 float bgG = Color.green(bg) / 255f; 86 float bgB = Color.blue(bg) / 255f; 87 bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f); 88 bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f); 89 bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f); 90 float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB; 91 92 float fgR = Color.red(fg) / 255f; 93 float fgG = Color.green(fg) / 255f; 94 float fgB = Color.blue(fg) / 255f; 95 fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f); 96 fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f); 97 fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f); 98 float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB; 99 100 return Math.abs((fgL + 0.05f) / (bgL + 0.05f)); 101 } 102 103 /** 104 * @return the clamped {@param value} between the provided {@param min} and {@param max}. 105 */ clamp(float value, float min, float max)106 public static float clamp(float value, float min, float max) { 107 return Math.max(min, Math.min(max, value)); 108 } 109 110 /** 111 * Updates the navigation bar state flags with the given IME state. 112 * 113 * @param oldFlags current navigation bar state flags. 114 * @param backDisposition the IME back disposition mode. Only takes effect if 115 * {@code isImeVisible} is {@code true}. 116 * @param isImeVisible whether the IME is currently visible. 117 * @param showImeSwitcher whether the IME Switcher button should be shown. Only takes effect if 118 * {@code isImeVisible} is {@code true}. 119 */ 120 @NavbarFlags updateNavbarFlagsFromIme(@avbarFlags int oldFlags, @BackDispositionMode int backDisposition, boolean isImeVisible, boolean showImeSwitcher)121 public static int updateNavbarFlagsFromIme(@NavbarFlags int oldFlags, 122 @BackDispositionMode int backDisposition, boolean isImeVisible, 123 boolean showImeSwitcher) { 124 int flags = oldFlags; 125 switch (backDisposition) { 126 case InputMethodService.BACK_DISPOSITION_DEFAULT: 127 case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: 128 case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: 129 if (isImeVisible) { 130 flags |= NAVBAR_BACK_DISMISS_IME; 131 } else { 132 flags &= ~NAVBAR_BACK_DISMISS_IME; 133 } 134 break; 135 case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING: 136 flags &= ~NAVBAR_BACK_DISMISS_IME; 137 break; 138 } 139 if (isImeVisible) { 140 flags |= NAVBAR_IME_VISIBLE; 141 } else { 142 flags &= ~NAVBAR_IME_VISIBLE; 143 } 144 if (showImeSwitcher && isImeVisible) { 145 flags |= NAVBAR_IME_SWITCHER_BUTTON_VISIBLE; 146 } else { 147 flags &= ~NAVBAR_IME_SWITCHER_BUTTON_VISIBLE; 148 } 149 150 return flags; 151 } 152 153 /** @return whether or not {@param context} represents that of a large screen device or not */ 154 @TargetApi(Build.VERSION_CODES.R) isLargeScreen(Context context)155 public static boolean isLargeScreen(Context context) { 156 return isLargeScreen(WindowManagerUtils.getWindowManager(context), context.getResources()); 157 } 158 159 /** @return whether or not {@param context} represents that of a large screen device or not */ isLargeScreen(WindowManager windowManager, Resources resources)160 public static boolean isLargeScreen(WindowManager windowManager, Resources resources) { 161 final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds(); 162 163 float smallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()), 164 resources.getConfiguration().densityDpi); 165 return smallestWidth >= TABLET_MIN_DPS; 166 } 167 dpiFromPx(float size, int densityDpi)168 public static float dpiFromPx(float size, int densityDpi) { 169 float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT; 170 return (size / densityRatio); 171 } 172 173 /** Whether a task is in freeform mode. */ isFreeformTask(Task task)174 public static boolean isFreeformTask(Task task) { 175 return task != null && task.getKey() != null 176 && task.getKey().windowingMode == WINDOWING_MODE_FREEFORM; 177 } 178 } 179