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.NAVIGATION_HINT_BACK_ALT; 20 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; 21 22 import android.annotation.TargetApi; 23 import android.content.Context; 24 import android.graphics.Color; 25 import android.graphics.Rect; 26 import android.inputmethodservice.InputMethodService; 27 import android.os.Build; 28 import android.os.Handler; 29 import android.os.Message; 30 import android.util.DisplayMetrics; 31 import android.view.Surface; 32 import android.view.WindowManager; 33 34 /* Common code */ 35 public class Utilities { 36 37 private static final float TABLET_MIN_DPS = 600; 38 39 /** 40 * Posts a runnable on a handler at the front of the queue ignoring any sync barriers. 41 */ postAtFrontOfQueueAsynchronously(Handler h, Runnable r)42 public static void postAtFrontOfQueueAsynchronously(Handler h, Runnable r) { 43 Message msg = h.obtainMessage().setCallback(r); 44 h.sendMessageAtFrontOfQueue(msg); 45 } 46 isRotationAnimationCCW(int from, int to)47 public static boolean isRotationAnimationCCW(int from, int to) { 48 // All 180deg WM rotation animations are CCW, match that 49 if (from == Surface.ROTATION_0 && to == Surface.ROTATION_90) return false; 50 if (from == Surface.ROTATION_0 && to == Surface.ROTATION_180) return true; //180d so CCW 51 if (from == Surface.ROTATION_0 && to == Surface.ROTATION_270) return true; 52 if (from == Surface.ROTATION_90 && to == Surface.ROTATION_0) return true; 53 if (from == Surface.ROTATION_90 && to == Surface.ROTATION_180) return false; 54 if (from == Surface.ROTATION_90 && to == Surface.ROTATION_270) return true; //180d so CCW 55 if (from == Surface.ROTATION_180 && to == Surface.ROTATION_0) return true; //180d so CCW 56 if (from == Surface.ROTATION_180 && to == Surface.ROTATION_90) return true; 57 if (from == Surface.ROTATION_180 && to == Surface.ROTATION_270) return false; 58 if (from == Surface.ROTATION_270 && to == Surface.ROTATION_0) return false; 59 if (from == Surface.ROTATION_270 && to == Surface.ROTATION_90) return true; //180d so CCW 60 if (from == Surface.ROTATION_270 && to == Surface.ROTATION_180) return true; 61 return false; // Default 62 } 63 64 /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */ computeContrastBetweenColors(int bg, int fg)65 public static float computeContrastBetweenColors(int bg, int fg) { 66 float bgR = Color.red(bg) / 255f; 67 float bgG = Color.green(bg) / 255f; 68 float bgB = Color.blue(bg) / 255f; 69 bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f); 70 bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f); 71 bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f); 72 float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB; 73 74 float fgR = Color.red(fg) / 255f; 75 float fgG = Color.green(fg) / 255f; 76 float fgB = Color.blue(fg) / 255f; 77 fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f); 78 fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f); 79 fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f); 80 float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB; 81 82 return Math.abs((fgL + 0.05f) / (bgL + 0.05f)); 83 } 84 85 /** 86 * @return the clamped {@param value} between the provided {@param min} and {@param max}. 87 */ clamp(float value, float min, float max)88 public static float clamp(float value, float min, float max) { 89 return Math.max(min, Math.min(max, value)); 90 } 91 92 /** 93 * @return updated set of flags from InputMethodService based off {@param oldHints} 94 * Leaves original hints unmodified 95 */ calculateBackDispositionHints(int oldHints, int backDisposition, boolean imeShown, boolean showImeSwitcher)96 public static int calculateBackDispositionHints(int oldHints, int backDisposition, 97 boolean imeShown, boolean showImeSwitcher) { 98 int hints = oldHints; 99 switch (backDisposition) { 100 case InputMethodService.BACK_DISPOSITION_DEFAULT: 101 case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: 102 case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: 103 if (imeShown) { 104 hints |= NAVIGATION_HINT_BACK_ALT; 105 } else { 106 hints &= ~NAVIGATION_HINT_BACK_ALT; 107 } 108 break; 109 case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING: 110 hints &= ~NAVIGATION_HINT_BACK_ALT; 111 break; 112 } 113 if (showImeSwitcher) { 114 hints |= NAVIGATION_HINT_IME_SHOWN; 115 } else { 116 hints &= ~NAVIGATION_HINT_IME_SHOWN; 117 } 118 119 return hints; 120 } 121 122 /** @return whether or not {@param context} represents that of a large screen device or not */ 123 @TargetApi(Build.VERSION_CODES.R) isTablet(Context context)124 public static boolean isTablet(Context context) { 125 final WindowManager windowManager = context.getSystemService(WindowManager.class); 126 final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds(); 127 128 float smallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()), 129 context.getResources().getConfiguration().densityDpi); 130 return smallestWidth >= TABLET_MIN_DPS; 131 } 132 dpiFromPx(float size, int densityDpi)133 public static float dpiFromPx(float size, int densityDpi) { 134 float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT; 135 return (size / densityRatio); 136 } 137 } 138