1 /* 2 * Copyright (C) 2020 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.quickstep.util; 18 19 import static android.view.OrientationEventListener.ORIENTATION_UNKNOWN; 20 import static android.view.Surface.ROTATION_0; 21 import static android.view.Surface.ROTATION_180; 22 import static android.view.Surface.ROTATION_270; 23 import static android.view.Surface.ROTATION_90; 24 25 import static com.android.launcher3.LauncherPrefs.ALLOW_ROTATION; 26 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; 27 import static com.android.launcher3.util.SettingsCache.ROTATION_SETTING_URI; 28 import static com.android.quickstep.BaseActivityInterface.getTaskDimension; 29 30 import static java.lang.annotation.RetentionPolicy.SOURCE; 31 32 import android.content.Context; 33 import android.content.SharedPreferences; 34 import android.graphics.Matrix; 35 import android.graphics.Point; 36 import android.graphics.PointF; 37 import android.graphics.Rect; 38 import android.util.Log; 39 import android.view.MotionEvent; 40 import android.view.OrientationEventListener; 41 import android.view.Surface; 42 43 import androidx.annotation.IntDef; 44 import androidx.annotation.NonNull; 45 46 import com.android.launcher3.DeviceProfile; 47 import com.android.launcher3.InvariantDeviceProfile; 48 import com.android.launcher3.LauncherPrefs; 49 import com.android.launcher3.testing.shared.TestProtocol; 50 import com.android.launcher3.touch.PagedOrientationHandler; 51 import com.android.launcher3.util.DisplayController; 52 import com.android.launcher3.util.SettingsCache; 53 import com.android.quickstep.BaseActivityInterface; 54 import com.android.quickstep.SystemUiProxy; 55 import com.android.quickstep.TaskAnimationManager; 56 57 import java.lang.annotation.Retention; 58 import java.util.function.IntConsumer; 59 60 /** 61 * Container to hold orientation/rotation related information for Launcher. 62 * This is not meant to be an abstraction layer for applying different functionality between 63 * the different orientation/rotations. For that see {@link PagedOrientationHandler} 64 * 65 * This class has initial default state assuming the device and foreground app have 66 * no ({@link Surface#ROTATION_0} rotation. 67 */ 68 public class RecentsOrientedState implements 69 SharedPreferences.OnSharedPreferenceChangeListener { 70 71 private static final String TAG = "RecentsOrientedState"; 72 private static final boolean DEBUG = false; 73 74 @Retention(SOURCE) 75 @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}) 76 public @interface SurfaceRotation {} 77 78 private PagedOrientationHandler mOrientationHandler = PagedOrientationHandler.PORTRAIT; 79 80 private @SurfaceRotation int mTouchRotation = ROTATION_0; 81 private @SurfaceRotation int mDisplayRotation = ROTATION_0; 82 private @SurfaceRotation int mRecentsActivityRotation = ROTATION_0; 83 private @SurfaceRotation int mRecentsRotation = ROTATION_0 - 1; 84 85 // Launcher activity supports multiple orientation, but fallback activity does not 86 private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY = 1 << 0; 87 // Multiple orientation is only supported if density is < 600 88 private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY = 1 << 1; 89 // Shared prefs for rotation, only if activity supports it 90 private static final int FLAG_HOME_ROTATION_ALLOWED_IN_PREFS = 1 << 2; 91 // If the user has enabled system rotation 92 private static final int FLAG_SYSTEM_ROTATION_ALLOWED = 1 << 3; 93 // Multiple orientation is not supported in multiwindow mode 94 private static final int FLAG_MULTIWINDOW_ROTATION_ALLOWED = 1 << 4; 95 // Whether to rotation sensor is supported on the device 96 private static final int FLAG_ROTATION_WATCHER_SUPPORTED = 1 << 5; 97 // Whether to enable rotation watcher when multi-rotation is supported 98 private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 6; 99 // Enable home rotation for UI tests, ignoring home rotation value from prefs 100 private static final int FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING = 1 << 7; 101 // Whether the swipe gesture is running, so the recents would stay locked in the 102 // current orientation 103 private static final int FLAG_SWIPE_UP_NOT_RUNNING = 1 << 8; 104 // Ignore shared prefs for home rotation rotation, allowing it in if the activity supports it 105 private static final int FLAG_IGNORE_ALLOW_HOME_ROTATION_PREF = 1 << 9; 106 107 private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE = 108 FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY 109 | FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY; 110 111 // State for which rotation watcher will be enabled. We skip it when home rotation or 112 // multi-window is enabled as in that case, activity itself rotates. 113 private static final int VALUE_ROTATION_WATCHER_ENABLED = 114 MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED 115 | FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED 116 | FLAG_SWIPE_UP_NOT_RUNNING; 117 118 private final Context mContext; 119 private final OrientationEventListener mOrientationListener; 120 private final SettingsCache mSettingsCache; 121 private final SettingsCache.OnChangeListener mRotationChangeListener = 122 isEnabled -> updateAutoRotateSetting(); 123 124 private final Matrix mTmpMatrix = new Matrix(); 125 126 private int mFlags; 127 private int mPreviousRotation = ROTATION_0; 128 private boolean mListenersInitialized = false; 129 130 // Combined int which encodes the full state. 131 private int mStateId = 0; 132 133 /** 134 * @param rotationChangeListener Callback for receiving rotation events when rotation watcher 135 * is enabled 136 * @see #setRotationWatcherEnabled(boolean) 137 */ RecentsOrientedState(Context context, BaseActivityInterface sizeStrategy, IntConsumer rotationChangeListener)138 public RecentsOrientedState(Context context, BaseActivityInterface sizeStrategy, 139 IntConsumer rotationChangeListener) { 140 mContext = context; 141 mOrientationListener = new OrientationEventListener(context) { 142 @Override 143 public void onOrientationChanged(int degrees) { 144 int newRotation = getRotationForUserDegreesRotated(degrees, mPreviousRotation); 145 if (newRotation != mPreviousRotation) { 146 mPreviousRotation = newRotation; 147 rotationChangeListener.accept(newRotation); 148 } 149 } 150 }; 151 152 mFlags = sizeStrategy.rotationSupportedByActivity 153 ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0; 154 155 mFlags |= FLAG_SWIPE_UP_NOT_RUNNING; 156 mSettingsCache = SettingsCache.INSTANCE.get(mContext); 157 initFlags(); 158 } 159 160 /** 161 * Sets the device profile for the current state. 162 */ setDeviceProfile(DeviceProfile deviceProfile)163 public void setDeviceProfile(DeviceProfile deviceProfile) { 164 boolean oldMultipleOrientationsSupported = isMultipleOrientationSupportedByDevice(); 165 setFlag(FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY, !deviceProfile.isTablet); 166 if (mListenersInitialized) { 167 boolean newMultipleOrientationsSupported = isMultipleOrientationSupportedByDevice(); 168 // If isMultipleOrientationSupportedByDevice is changed, init or destroy listeners 169 // accordingly. 170 if (newMultipleOrientationsSupported != oldMultipleOrientationsSupported) { 171 if (newMultipleOrientationsSupported) { 172 initMultipleOrientationListeners(); 173 } else { 174 destroyMultipleOrientationListeners(); 175 } 176 } 177 } 178 } 179 180 /** 181 * Sets the rotation for the recents activity, which could affect the appearance of task view. 182 * @see #update(int, int) 183 */ setRecentsRotation(@urfaceRotation int recentsRotation)184 public boolean setRecentsRotation(@SurfaceRotation int recentsRotation) { 185 mRecentsRotation = recentsRotation; 186 return updateHandler(); 187 } 188 189 /** 190 * Sets if the host is in multi-window mode 191 */ setMultiWindowMode(boolean isMultiWindow)192 public void setMultiWindowMode(boolean isMultiWindow) { 193 setFlag(FLAG_MULTIWINDOW_ROTATION_ALLOWED, isMultiWindow); 194 } 195 196 /** 197 * Sets if the swipe up gesture is currently running or not 198 */ setGestureActive(boolean isGestureActive)199 public boolean setGestureActive(boolean isGestureActive) { 200 return setFlag(FLAG_SWIPE_UP_NOT_RUNNING, !isGestureActive); 201 } 202 203 /** 204 * Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler} 205 * @param touchRotation The rotation the nav bar region that is touched is in 206 * @param displayRotation Rotation of the display/device 207 * 208 * @return true if there was any change in the internal state as a result of this call, 209 * false otherwise 210 */ update( @urfaceRotation int touchRotation, @SurfaceRotation int displayRotation)211 public boolean update( 212 @SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) { 213 mDisplayRotation = displayRotation; 214 mTouchRotation = touchRotation; 215 mPreviousRotation = touchRotation; 216 return updateHandler(); 217 } 218 updateHandler()219 private boolean updateHandler() { 220 mRecentsActivityRotation = inferRecentsActivityRotation(mDisplayRotation); 221 if (mRecentsActivityRotation == mTouchRotation || isRecentsActivityRotationAllowed()) { 222 mOrientationHandler = PagedOrientationHandler.PORTRAIT; 223 } else if (mTouchRotation == ROTATION_90) { 224 mOrientationHandler = PagedOrientationHandler.LANDSCAPE; 225 } else if (mTouchRotation == ROTATION_270) { 226 mOrientationHandler = PagedOrientationHandler.SEASCAPE; 227 } else { 228 mOrientationHandler = PagedOrientationHandler.PORTRAIT; 229 } 230 if (DEBUG) { 231 Log.d(TAG, "current RecentsOrientedState: " + this); 232 } 233 234 int oldStateId = mStateId; 235 // Each SurfaceRotation value takes two bits 236 mStateId = (((((mFlags << 2) 237 | mDisplayRotation) << 2) 238 | mTouchRotation) << 3) 239 | (mRecentsRotation < 0 ? 7 : mRecentsRotation); 240 return mStateId != oldStateId; 241 } 242 243 @SurfaceRotation inferRecentsActivityRotation(@urfaceRotation int displayRotation)244 private int inferRecentsActivityRotation(@SurfaceRotation int displayRotation) { 245 if (isRecentsActivityRotationAllowed()) { 246 return mRecentsRotation < 0 ? displayRotation : mRecentsRotation; 247 } else { 248 return ROTATION_0; 249 } 250 } 251 setFlag(int mask, boolean enabled)252 private boolean setFlag(int mask, boolean enabled) { 253 boolean wasRotationEnabled = !TestProtocol.sDisableSensorRotation 254 && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED 255 && !isRecentsActivityRotationAllowed(); 256 if (enabled) { 257 mFlags |= mask; 258 } else { 259 mFlags &= ~mask; 260 } 261 262 boolean isRotationEnabled = !TestProtocol.sDisableSensorRotation 263 && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED 264 && !isRecentsActivityRotationAllowed(); 265 if (wasRotationEnabled != isRotationEnabled) { 266 UI_HELPER_EXECUTOR.execute(() -> { 267 if (isRotationEnabled) { 268 mOrientationListener.enable(); 269 } else { 270 mOrientationListener.disable(); 271 } 272 }); 273 } 274 return updateHandler(); 275 } 276 277 @Override onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s)278 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { 279 if (LauncherPrefs.ALLOW_ROTATION.getSharedPrefKey().equals(s)) { 280 updateHomeRotationSetting(); 281 } 282 } 283 updateAutoRotateSetting()284 private void updateAutoRotateSetting() { 285 setFlag(FLAG_SYSTEM_ROTATION_ALLOWED, 286 mSettingsCache.getValue(ROTATION_SETTING_URI, 1)); 287 } 288 updateHomeRotationSetting()289 private void updateHomeRotationSetting() { 290 boolean homeRotationEnabled = LauncherPrefs.get(mContext).get(ALLOW_ROTATION); 291 setFlag(FLAG_HOME_ROTATION_ALLOWED_IN_PREFS, homeRotationEnabled); 292 SystemUiProxy.INSTANCE.get(mContext).setHomeRotationEnabled(homeRotationEnabled); 293 } 294 initFlags()295 private void initFlags() { 296 setFlag(FLAG_ROTATION_WATCHER_SUPPORTED, mOrientationListener.canDetectOrientation()); 297 298 // initialize external flags 299 updateAutoRotateSetting(); 300 updateHomeRotationSetting(); 301 } 302 initMultipleOrientationListeners()303 private void initMultipleOrientationListeners() { 304 LauncherPrefs.get(mContext).addListener(this, ALLOW_ROTATION); 305 mSettingsCache.register(ROTATION_SETTING_URI, mRotationChangeListener); 306 updateAutoRotateSetting(); 307 } 308 destroyMultipleOrientationListeners()309 private void destroyMultipleOrientationListeners() { 310 LauncherPrefs.get(mContext).removeListener(this, ALLOW_ROTATION); 311 mSettingsCache.unregister(ROTATION_SETTING_URI, mRotationChangeListener); 312 } 313 314 /** 315 * Initializes any system values and registers corresponding change listeners. It must be 316 * paired with {@link #destroyListeners()} call 317 */ initListeners()318 public void initListeners() { 319 mListenersInitialized = true; 320 if (isMultipleOrientationSupportedByDevice()) { 321 initMultipleOrientationListeners(); 322 } 323 initFlags(); 324 } 325 326 /** 327 * Unregisters any previously registered listeners. 328 */ destroyListeners()329 public void destroyListeners() { 330 mListenersInitialized = false; 331 if (isMultipleOrientationSupportedByDevice()) { 332 destroyMultipleOrientationListeners(); 333 } 334 setRotationWatcherEnabled(false); 335 } 336 forceAllowRotationForTesting(boolean forceAllow)337 public void forceAllowRotationForTesting(boolean forceAllow) { 338 setFlag(FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING, forceAllow); 339 } 340 341 @SurfaceRotation getDisplayRotation()342 public int getDisplayRotation() { 343 if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) { 344 // When shell transitions are enabled, both the display and activity rotations should 345 // be the same once the gesture starts 346 return mRecentsActivityRotation; 347 } 348 return mDisplayRotation; 349 } 350 351 @SurfaceRotation getTouchRotation()352 public int getTouchRotation() { 353 return mTouchRotation; 354 } 355 356 @SurfaceRotation getRecentsActivityRotation()357 public int getRecentsActivityRotation() { 358 return mRecentsActivityRotation; 359 } 360 361 /** 362 * Returns an id that can be used to tracking internal changes 363 */ getStateId()364 public int getStateId() { 365 return mStateId; 366 } 367 isMultipleOrientationSupportedByDevice()368 public boolean isMultipleOrientationSupportedByDevice() { 369 return (mFlags & MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE) 370 == MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE; 371 } 372 ignoreAllowHomeRotationPreference()373 public void ignoreAllowHomeRotationPreference() { 374 setFlag(FLAG_IGNORE_ALLOW_HOME_ROTATION_PREF, true); 375 } 376 isRecentsActivityRotationAllowed()377 public boolean isRecentsActivityRotationAllowed() { 378 // Activity rotation is allowed if the multi-simulated-rotation is not supported 379 // (fallback recents or tablets) or activity rotation is enabled by various settings. 380 return ((mFlags & MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE) 381 != MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE) 382 || (mFlags & (FLAG_IGNORE_ALLOW_HOME_ROTATION_PREF 383 | FLAG_HOME_ROTATION_ALLOWED_IN_PREFS 384 | FLAG_MULTIWINDOW_ROTATION_ALLOWED 385 | FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING)) != 0; 386 } 387 388 /** 389 * Enables or disables the rotation watcher for listening to rotation callbacks 390 */ setRotationWatcherEnabled(boolean isEnabled)391 public void setRotationWatcherEnabled(boolean isEnabled) { 392 setFlag(FLAG_ROTATION_WATCHER_ENABLED, isEnabled); 393 } 394 395 /** 396 * Returns the scale and pivot so that the provided taskRect can fit the provided full size 397 */ getFullScreenScaleAndPivot(Rect taskView, DeviceProfile dp, PointF outPivot)398 public float getFullScreenScaleAndPivot(Rect taskView, DeviceProfile dp, PointF outPivot) { 399 getTaskDimension(mContext, dp, outPivot); 400 float scale = Math.min(outPivot.x / taskView.width(), outPivot.y / taskView.height()); 401 if (scale == 1) { 402 outPivot.set(taskView.centerX(), taskView.centerY()); 403 } else { 404 float factor = scale / (scale - 1); 405 outPivot.set(taskView.left * factor, taskView.top * factor); 406 } 407 return scale; 408 } 409 getOrientationHandler()410 public PagedOrientationHandler getOrientationHandler() { 411 return mOrientationHandler; 412 } 413 414 /** 415 * For landscape, since the navbar is already in a vertical position, we don't have to do any 416 * rotations as the change in Y coordinate is what is read. We only flip the sign of the 417 * y coordinate to make it match existing behavior of swipe to the top to go previous 418 */ flipVertical(MotionEvent ev)419 public void flipVertical(MotionEvent ev) { 420 mTmpMatrix.setScale(1, -1); 421 ev.transform(mTmpMatrix); 422 } 423 424 /** 425 * Creates a matrix to transform the given motion event specified by degrees. 426 * If inverse is {@code true}, the inverse of that matrix will be applied 427 */ transformEvent(float degrees, MotionEvent ev, boolean inverse)428 public void transformEvent(float degrees, MotionEvent ev, boolean inverse) { 429 mTmpMatrix.setRotate(inverse ? -degrees : degrees); 430 ev.transform(mTmpMatrix); 431 432 // TODO: Add scaling back in based on degrees 433 /* 434 if (getWidth() > 0 && getHeight() > 0) { 435 float scale = ((float) getWidth()) / getHeight(); 436 transform.postScale(scale, 1 / scale); 437 } 438 */ 439 } 440 441 @SurfaceRotation getRotationForUserDegreesRotated(float degrees, int currentRotation)442 public static int getRotationForUserDegreesRotated(float degrees, int currentRotation) { 443 if (degrees == ORIENTATION_UNKNOWN) { 444 return currentRotation; 445 } 446 447 int threshold = 70; 448 switch (currentRotation) { 449 case ROTATION_0: 450 if (degrees > 180 && degrees < (360 - threshold)) { 451 return ROTATION_90; 452 } 453 if (degrees < 180 && degrees > threshold) { 454 return ROTATION_270; 455 } 456 break; 457 case ROTATION_270: 458 if (degrees < (90 - threshold) || 459 (degrees > (270 + threshold) && degrees < 360)) { 460 return ROTATION_0; 461 } 462 if (degrees > (90 + threshold) && degrees < 180) { 463 return ROTATION_180; 464 } 465 // flip from seascape to landscape 466 if (degrees > (180 + threshold) && degrees < 360) { 467 return ROTATION_90; 468 } 469 break; 470 case ROTATION_180: 471 if (degrees < (180 - threshold)) { 472 return ROTATION_270; 473 } 474 if (degrees > (180 + threshold)) { 475 return ROTATION_90; 476 } 477 break; 478 case ROTATION_90: 479 if (degrees < (270 - threshold) && degrees > 90) { 480 return ROTATION_180; 481 } 482 if (degrees > (270 + threshold) && degrees < 360 483 || (degrees >= 0 && degrees < threshold)) { 484 return ROTATION_0; 485 } 486 // flip from landscape to seascape 487 if (degrees > threshold && degrees < 180) { 488 return ROTATION_270; 489 } 490 break; 491 } 492 493 return currentRotation; 494 } 495 isDisplayPhoneNatural()496 public boolean isDisplayPhoneNatural() { 497 return mDisplayRotation == Surface.ROTATION_0 || mDisplayRotation == Surface.ROTATION_180; 498 } 499 500 /** 501 * Posts the transformation on the matrix representing the provided display rotation 502 */ postDisplayRotation(@urfaceRotation int displayRotation, float screenWidth, float screenHeight, Matrix out)503 public static void postDisplayRotation(@SurfaceRotation int displayRotation, 504 float screenWidth, float screenHeight, Matrix out) { 505 switch (displayRotation) { 506 case ROTATION_0: 507 return; 508 case ROTATION_90: 509 out.postRotate(270); 510 out.postTranslate(0, screenWidth); 511 break; 512 case ROTATION_180: 513 out.postRotate(180); 514 out.postTranslate(screenHeight, screenWidth); 515 break; 516 case ROTATION_270: 517 out.postRotate(90); 518 out.postTranslate(screenHeight, 0); 519 break; 520 } 521 } 522 523 /** 524 * Contrary to {@link #postDisplayRotation}. 525 */ preDisplayRotation(@urfaceRotation int displayRotation, float screenWidth, float screenHeight, Matrix out)526 public static void preDisplayRotation(@SurfaceRotation int displayRotation, 527 float screenWidth, float screenHeight, Matrix out) { 528 switch (displayRotation) { 529 case ROTATION_0: 530 return; 531 case ROTATION_90: 532 out.postRotate(90); 533 out.postTranslate(screenWidth, 0); 534 break; 535 case ROTATION_180: 536 out.postRotate(180); 537 out.postTranslate(screenHeight, screenWidth); 538 break; 539 case ROTATION_270: 540 out.postRotate(270); 541 out.postTranslate(0, screenHeight); 542 break; 543 } 544 } 545 546 @NonNull 547 @Override toString()548 public String toString() { 549 boolean systemRotationOn = (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0; 550 return "[" 551 + "this=" + nameAndAddress(this) 552 + " mOrientationHandler=" + nameAndAddress(mOrientationHandler) 553 + " mDisplayRotation=" + mDisplayRotation 554 + " mTouchRotation=" + mTouchRotation 555 + " mRecentsActivityRotation=" + mRecentsActivityRotation 556 + " mRecentsRotation=" + mRecentsRotation 557 + " isRecentsActivityRotationAllowed=" + isRecentsActivityRotationAllowed() 558 + " mSystemRotation=" + systemRotationOn 559 + " mStateId=" + mStateId 560 + " mFlags=" + mFlags 561 + "]"; 562 } 563 564 /** 565 * Returns the device profile based on expected launcher rotation 566 */ getLauncherDeviceProfile()567 public DeviceProfile getLauncherDeviceProfile() { 568 InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext); 569 Point currentSize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize; 570 571 int width, height; 572 if ((mRecentsActivityRotation == ROTATION_90 || mRecentsActivityRotation == ROTATION_270)) { 573 width = Math.max(currentSize.x, currentSize.y); 574 height = Math.min(currentSize.x, currentSize.y); 575 } else { 576 width = Math.min(currentSize.x, currentSize.y); 577 height = Math.max(currentSize.x, currentSize.y); 578 } 579 return idp.getBestMatch(width, height, mRecentsActivityRotation); 580 } 581 nameAndAddress(Object obj)582 private static String nameAndAddress(Object obj) { 583 return obj.getClass().getSimpleName() + "@" + obj.hashCode(); 584 } 585 } 586