1 /* 2 * Copyright (C) 2013 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 static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; 20 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 21 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; 22 import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; 23 import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; 24 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; 25 26 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO; 27 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED; 28 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.app.WindowConfiguration; 32 import android.provider.Settings; 33 import android.view.Display; 34 import android.view.DisplayInfo; 35 import android.view.IWindowManager; 36 import android.view.Surface; 37 import android.view.WindowManager; 38 import android.view.WindowManager.DisplayImePolicy; 39 import android.window.DesktopExperienceFlags; 40 41 import com.android.server.policy.WindowManagerPolicy; 42 import com.android.server.wm.DisplayContent.ForceScalingMode; 43 44 import java.util.Objects; 45 46 /** 47 * Current persistent settings about a display. Provides policies for display settings and 48 * delegates the persistence and lookup of settings values to the supplied {@link SettingsProvider}. 49 */ 50 class DisplayWindowSettings { 51 @NonNull 52 private final WindowManagerService mService; 53 @NonNull 54 private final SettingsProvider mSettingsProvider; 55 DisplayWindowSettings(@onNull WindowManagerService service, @NonNull SettingsProvider settingsProvider)56 DisplayWindowSettings(@NonNull WindowManagerService service, 57 @NonNull SettingsProvider settingsProvider) { 58 mService = service; 59 mSettingsProvider = settingsProvider; 60 } 61 setUserRotation(@onNull DisplayContent displayContent, @WindowManagerPolicy.UserRotationMode int rotationMode, @Surface.Rotation int rotation)62 void setUserRotation(@NonNull DisplayContent displayContent, 63 @WindowManagerPolicy.UserRotationMode int rotationMode, 64 @Surface.Rotation int rotation) { 65 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 66 final SettingsProvider.SettingsEntry overrideSettings = 67 mSettingsProvider.getOverrideSettings(displayInfo); 68 overrideSettings.mUserRotationMode = rotationMode; 69 overrideSettings.mUserRotation = rotation; 70 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 71 } 72 73 /** Stores the size override settings. If the width or height is zero, it means to clear. */ setForcedSize(@onNull DisplayContent displayContent, int width, int height)74 void setForcedSize(@NonNull DisplayContent displayContent, int width, int height) { 75 if (displayContent.isDefaultDisplay) { 76 final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height); 77 Settings.Global.putString(mService.mContext.getContentResolver(), 78 Settings.Global.DISPLAY_SIZE_FORCED, sizeString); 79 } 80 81 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 82 final SettingsProvider.SettingsEntry overrideSettings = 83 mSettingsProvider.getOverrideSettings(displayInfo); 84 overrideSettings.mForcedWidth = width; 85 overrideSettings.mForcedHeight = height; 86 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 87 } 88 setForcedDensity(@onNull DisplayInfo info, int density, int userId)89 void setForcedDensity(@NonNull DisplayInfo info, int density, int userId) { 90 if (info.displayId == Display.DEFAULT_DISPLAY) { 91 final String densityString = density == 0 ? "" : Integer.toString(density); 92 Settings.Secure.putStringForUser(mService.mContext.getContentResolver(), 93 Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId); 94 } 95 96 final SettingsProvider.SettingsEntry overrideSettings = 97 mSettingsProvider.getOverrideSettings(info); 98 overrideSettings.mForcedDensity = density; 99 mSettingsProvider.updateOverrideSettings(info, overrideSettings); 100 } 101 setForcedDensityRatio(@onNull DisplayInfo info, float ratio)102 void setForcedDensityRatio(@NonNull DisplayInfo info, float ratio) { 103 final SettingsProvider.SettingsEntry overrideSettings = 104 mSettingsProvider.getOverrideSettings(info); 105 overrideSettings.mForcedDensityRatio = ratio; 106 mSettingsProvider.updateOverrideSettings(info, overrideSettings); 107 } 108 setForcedScalingMode(@onNull DisplayContent displayContent, @ForceScalingMode int mode)109 void setForcedScalingMode(@NonNull DisplayContent displayContent, @ForceScalingMode int mode) { 110 if (displayContent.isDefaultDisplay) { 111 Settings.Global.putInt(mService.mContext.getContentResolver(), 112 Settings.Global.DISPLAY_SCALING_FORCE, mode); 113 } 114 115 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 116 final SettingsProvider.SettingsEntry overrideSettings = 117 mSettingsProvider.getOverrideSettings(displayInfo); 118 overrideSettings.mForcedScalingMode = mode; 119 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 120 } 121 setFixedToUserRotation(@onNull DisplayContent displayContent, int fixedToUserRotation)122 void setFixedToUserRotation(@NonNull DisplayContent displayContent, int fixedToUserRotation) { 123 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 124 final SettingsProvider.SettingsEntry overrideSettings = 125 mSettingsProvider.getOverrideSettings(displayInfo); 126 overrideSettings.mFixedToUserRotation = fixedToUserRotation; 127 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 128 } 129 setIgnoreOrientationRequest(@onNull DisplayContent displayContent, @Nullable Boolean ignoreOrientationRequest)130 void setIgnoreOrientationRequest(@NonNull DisplayContent displayContent, 131 @Nullable Boolean ignoreOrientationRequest) { 132 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 133 final SettingsProvider.SettingsEntry overrideSettings = 134 mSettingsProvider.getOverrideSettings(displayInfo); 135 overrideSettings.mIgnoreOrientationRequest = ignoreOrientationRequest; 136 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 137 } 138 139 @WindowConfiguration.WindowingMode getWindowingModeLocked(@onNull SettingsProvider.SettingsEntry settings, @NonNull DisplayContent dc)140 private int getWindowingModeLocked(@NonNull SettingsProvider.SettingsEntry settings, 141 @NonNull DisplayContent dc) { 142 final int windowingModeFromDisplaySettings = settings.mWindowingMode; 143 // This display used to be in freeform, but we don't support freeform anymore, so fall 144 // back to fullscreen. 145 if (windowingModeFromDisplaySettings == WindowConfiguration.WINDOWING_MODE_FREEFORM 146 && !mService.mAtmService.mSupportsFreeformWindowManagement) { 147 return WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 148 } 149 if (windowingModeFromDisplaySettings != WindowConfiguration.WINDOWING_MODE_UNDEFINED) { 150 return windowingModeFromDisplaySettings; 151 } 152 // No record is present so use default windowing mode policy. 153 final boolean forceFreeForm = mService.mAtmService.mSupportsFreeformWindowManagement 154 && (mService.mIsPc || dc.isPublicSecondaryDisplayWithDesktopModeForceEnabled()); 155 if (forceFreeForm) { 156 return WindowConfiguration.WINDOWING_MODE_FREEFORM; 157 } 158 final int currentWindowingMode = dc.getDefaultTaskDisplayArea().getWindowingMode(); 159 if (currentWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) { 160 // No record preset in settings + no mode set via the display area policy. 161 // Move to fullscreen as a fallback. 162 return WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 163 } 164 if (currentWindowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM) { 165 // Freeform was enabled before but disabled now, the TDA should now move to fullscreen. 166 return WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 167 } 168 return currentWindowingMode; 169 } 170 171 @WindowConfiguration.WindowingMode getWindowingModeLocked(@onNull DisplayContent dc)172 int getWindowingModeLocked(@NonNull DisplayContent dc) { 173 final DisplayInfo displayInfo = dc.getDisplayInfo(); 174 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 175 return getWindowingModeLocked(settings, dc); 176 } 177 setWindowingModeLocked(@onNull DisplayContent dc, @WindowConfiguration.WindowingMode int mode)178 void setWindowingModeLocked(@NonNull DisplayContent dc, 179 @WindowConfiguration.WindowingMode int mode) { 180 final DisplayInfo displayInfo = dc.getDisplayInfo(); 181 final SettingsProvider.SettingsEntry overrideSettings = 182 mSettingsProvider.getOverrideSettings(displayInfo); 183 overrideSettings.mWindowingMode = mode; 184 final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea(); 185 if (defaultTda != null) { 186 defaultTda.setWindowingMode(mode); 187 } 188 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 189 } 190 191 @WindowManager.RemoveContentMode getRemoveContentModeLocked(@onNull DisplayContent dc)192 int getRemoveContentModeLocked(@NonNull DisplayContent dc) { 193 final DisplayInfo displayInfo = dc.getDisplayInfo(); 194 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 195 if (settings.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) { 196 if (dc.isPrivate() || dc.getDisplay().getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT) { 197 // For private displays by default content is destroyed on removal. 198 return REMOVE_CONTENT_MODE_DESTROY; 199 } 200 // For other displays by default content is moved to primary on removal. 201 return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; 202 } 203 return settings.mRemoveContentMode; 204 } 205 setRemoveContentModeLocked(@onNull DisplayContent dc, @WindowManager.RemoveContentMode int mode)206 void setRemoveContentModeLocked(@NonNull DisplayContent dc, 207 @WindowManager.RemoveContentMode int mode) { 208 final DisplayInfo displayInfo = dc.getDisplayInfo(); 209 final SettingsProvider.SettingsEntry overrideSettings = 210 mSettingsProvider.getOverrideSettings(displayInfo); 211 overrideSettings.mRemoveContentMode = mode; 212 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 213 } 214 shouldShowWithInsecureKeyguardLocked(@onNull DisplayContent dc)215 boolean shouldShowWithInsecureKeyguardLocked(@NonNull DisplayContent dc) { 216 final DisplayInfo displayInfo = dc.getDisplayInfo(); 217 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 218 return settings.mShouldShowWithInsecureKeyguard != null 219 ? settings.mShouldShowWithInsecureKeyguard : false; 220 } 221 setShouldShowWithInsecureKeyguardLocked(@onNull DisplayContent dc, boolean shouldShow)222 void setShouldShowWithInsecureKeyguardLocked(@NonNull DisplayContent dc, boolean shouldShow) { 223 if (!dc.isPrivate() && shouldShow) { 224 throw new IllegalArgumentException("Public display can't be allowed to show content" 225 + " when locked"); 226 } 227 228 final DisplayInfo displayInfo = dc.getDisplayInfo(); 229 final SettingsProvider.SettingsEntry overrideSettings = 230 mSettingsProvider.getOverrideSettings(displayInfo); 231 overrideSettings.mShouldShowWithInsecureKeyguard = shouldShow; 232 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 233 } 234 setDontMoveToTop(@onNull DisplayContent dc, boolean dontMoveToTop)235 void setDontMoveToTop(@NonNull DisplayContent dc, boolean dontMoveToTop) { 236 DisplayInfo displayInfo = dc.getDisplayInfo(); 237 SettingsProvider.SettingsEntry overrideSettings = 238 mSettingsProvider.getSettings(displayInfo); 239 overrideSettings.mDontMoveToTop = dontMoveToTop; 240 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 241 } 242 243 /** 244 * Returns {@code true} if either the display is the default display, or the display is allowed 245 * to dynamically add/remove system decorations and the system decorations should be shown on it 246 * currently. 247 */ shouldShowSystemDecorsLocked(@onNull DisplayContent dc)248 boolean shouldShowSystemDecorsLocked(@NonNull DisplayContent dc) { 249 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) { 250 // Default display should show system decors. 251 return true; 252 } 253 254 final DisplayInfo displayInfo = dc.getDisplayInfo(); 255 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 256 return settings.mShouldShowSystemDecors != null ? settings.mShouldShowSystemDecors : false; 257 } 258 setShouldShowSystemDecorsLocked(@onNull DisplayContent dc, boolean shouldShow)259 void setShouldShowSystemDecorsLocked(@NonNull DisplayContent dc, boolean shouldShow) { 260 final boolean changed = (shouldShow != shouldShowSystemDecorsLocked(dc)); 261 setShouldShowSystemDecorsInternalLocked(dc, shouldShow); 262 263 if (DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { 264 if (dc.isDefaultDisplay || dc.isPrivate() || !changed) { 265 return; 266 } 267 268 dc.getDisplayPolicy().updateHasNavigationBarIfNeeded(); 269 270 if (shouldShow) { 271 mService.mRoot.startSystemDecorations(dc, "setShouldShowSystemDecorsLocked"); 272 } else { 273 dc.getDisplayPolicy().notifyDisplayRemoveSystemDecorations(); 274 } 275 } 276 } 277 setShouldShowSystemDecorsInternalLocked(@onNull DisplayContent dc, boolean shouldShow)278 void setShouldShowSystemDecorsInternalLocked(@NonNull DisplayContent dc, 279 boolean shouldShow) { 280 final DisplayInfo displayInfo = dc.getDisplayInfo(); 281 final SettingsProvider.SettingsEntry overrideSettings = 282 mSettingsProvider.getOverrideSettings(displayInfo); 283 overrideSettings.mShouldShowSystemDecors = shouldShow; 284 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 285 } 286 isHomeSupportedLocked(@onNull DisplayContent dc)287 boolean isHomeSupportedLocked(@NonNull DisplayContent dc) { 288 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) { 289 // Default display should show home. 290 return true; 291 } 292 293 final DisplayInfo displayInfo = dc.getDisplayInfo(); 294 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 295 return settings.mIsHomeSupported != null 296 ? settings.mIsHomeSupported 297 : shouldShowSystemDecorsLocked(dc); 298 } 299 setHomeSupportedOnDisplayLocked(@onNull String displayUniqueId, int displayType, boolean supported)300 void setHomeSupportedOnDisplayLocked(@NonNull String displayUniqueId, int displayType, 301 boolean supported) { 302 final DisplayInfo displayInfo = new DisplayInfo(); 303 displayInfo.uniqueId = displayUniqueId; 304 displayInfo.type = displayType; 305 final SettingsProvider.SettingsEntry overrideSettings = 306 mSettingsProvider.getOverrideSettings(displayInfo); 307 overrideSettings.mIsHomeSupported = supported; 308 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 309 } 310 isIgnoreActivitySizeRestrictionsLocked(@onNull DisplayContent dc)311 boolean isIgnoreActivitySizeRestrictionsLocked(@NonNull DisplayContent dc) { 312 final DisplayInfo displayInfo = dc.getDisplayInfo(); 313 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 314 return settings.mIgnoreActivitySizeRestrictions != null 315 && settings.mIgnoreActivitySizeRestrictions; 316 } 317 setIgnoreActivitySizeRestrictionsOnDisplayLocked(@onNull String displayUniqueId, int displayType, boolean enabled)318 void setIgnoreActivitySizeRestrictionsOnDisplayLocked(@NonNull String displayUniqueId, 319 int displayType, boolean enabled) { 320 final DisplayInfo displayInfo = new DisplayInfo(); 321 displayInfo.uniqueId = displayUniqueId; 322 displayInfo.type = displayType; 323 final SettingsProvider.SettingsEntry overrideSettings = 324 mSettingsProvider.getOverrideSettings(displayInfo); 325 overrideSettings.mIgnoreActivitySizeRestrictions = enabled; 326 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 327 } 328 clearDisplaySettings(@onNull String displayUniqueId, int displayType)329 void clearDisplaySettings(@NonNull String displayUniqueId, int displayType) { 330 final DisplayInfo displayInfo = new DisplayInfo(); 331 displayInfo.uniqueId = displayUniqueId; 332 displayInfo.type = displayType; 333 mSettingsProvider.clearDisplaySettings(displayInfo); 334 } 335 336 @DisplayImePolicy getImePolicyLocked(@onNull DisplayContent dc)337 int getImePolicyLocked(@NonNull DisplayContent dc) { 338 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) { 339 // Default display should show IME. 340 return DISPLAY_IME_POLICY_LOCAL; 341 } 342 343 final DisplayInfo displayInfo = dc.getDisplayInfo(); 344 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 345 return settings.mImePolicy != null ? settings.mImePolicy 346 : DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 347 } 348 setDisplayImePolicy(@onNull DisplayContent dc, @DisplayImePolicy int imePolicy)349 void setDisplayImePolicy(@NonNull DisplayContent dc, @DisplayImePolicy int imePolicy) { 350 final DisplayInfo displayInfo = dc.getDisplayInfo(); 351 final SettingsProvider.SettingsEntry overrideSettings = 352 mSettingsProvider.getOverrideSettings(displayInfo); 353 overrideSettings.mImePolicy = imePolicy; 354 mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); 355 } 356 applySettingsToDisplayLocked(@onNull DisplayContent dc)357 void applySettingsToDisplayLocked(@NonNull DisplayContent dc) { 358 applySettingsToDisplayLocked(dc, /* includeRotationSettings */ true); 359 } 360 applySettingsToDisplayLocked(@onNull DisplayContent dc, boolean includeRotationSettings)361 void applySettingsToDisplayLocked(@NonNull DisplayContent dc, boolean includeRotationSettings) { 362 final DisplayInfo displayInfo = dc.getDisplayInfo(); 363 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 364 365 // Setting windowing mode first, because it may override overscan values later. 366 final int windowingMode = getWindowingModeLocked(settings, dc); 367 final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea(); 368 if (defaultTda != null) { 369 defaultTda.setWindowingMode(windowingMode); 370 } 371 final int userRotationMode = settings.mUserRotationMode != null 372 ? settings.mUserRotationMode : WindowManagerPolicy.USER_ROTATION_FREE; 373 final int userRotation = settings.mUserRotation != null 374 ? settings.mUserRotation : Surface.ROTATION_0; 375 final int mFixedToUserRotation = settings.mFixedToUserRotation != null 376 ? settings.mFixedToUserRotation : IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; 377 dc.getDisplayRotation().restoreSettings(userRotationMode, userRotation, 378 mFixedToUserRotation); 379 380 final boolean hasDensityOverride = settings.mForcedDensity != 0; 381 final boolean hasDensityOverrideRatio = settings.mForcedDensityRatio != 0.0f; 382 final boolean hasSizeOverride = settings.mForcedWidth != 0 && settings.mForcedHeight != 0; 383 dc.mIsDensityForced = hasDensityOverride; 384 dc.mIsSizeForced = hasSizeOverride; 385 386 dc.mIgnoreDisplayCutout = settings.mIgnoreDisplayCutout != null 387 ? settings.mIgnoreDisplayCutout : false; 388 389 final int width = hasSizeOverride ? settings.mForcedWidth : dc.mInitialDisplayWidth; 390 final int height = hasSizeOverride ? settings.mForcedHeight : dc.mInitialDisplayHeight; 391 final int density = hasDensityOverride ? settings.mForcedDensity 392 : dc.getInitialDisplayDensity(); 393 if (hasDensityOverrideRatio) { 394 dc.mForcedDisplayDensityRatio = settings.mForcedDensityRatio; 395 } 396 397 dc.updateBaseDisplayMetrics(width, height, density, dc.mBaseDisplayPhysicalXDpi, 398 dc.mBaseDisplayPhysicalYDpi); 399 400 final int forcedScalingMode = settings.mForcedScalingMode != null 401 ? settings.mForcedScalingMode : FORCE_SCALING_MODE_AUTO; 402 dc.mDisplayScalingDisabled = forcedScalingMode == FORCE_SCALING_MODE_DISABLED; 403 404 boolean dontMoveToTop = settings.mDontMoveToTop != null 405 ? settings.mDontMoveToTop : false; 406 dc.mDontMoveToTop = !dc.canStealTopFocus() || dontMoveToTop; 407 408 if (includeRotationSettings) applyRotationSettingsToDisplayLocked(dc); 409 } 410 applyRotationSettingsToDisplayLocked(@onNull DisplayContent dc)411 void applyRotationSettingsToDisplayLocked(@NonNull DisplayContent dc) { 412 final DisplayInfo displayInfo = dc.getDisplayInfo(); 413 final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); 414 415 if (settings.mIgnoreOrientationRequest != null) { 416 dc.setIgnoreOrientationRequest(settings.mIgnoreOrientationRequest); 417 } else if (dc.mHasSetIgnoreOrientationRequest) { 418 // Null entry is default behavior, i.e. do not ignore. 419 dc.setIgnoreOrientationRequest(false); 420 } 421 422 dc.getDisplayRotation().resetAllowAllRotations(); 423 } 424 425 /** 426 * Updates settings for the given display after system features are loaded into window manager 427 * service, e.g. if this device is PC and if this device supports freeform. 428 * 429 * @param dc the given display. 430 * @return {@code true} if any settings for this display has changed; {@code false} if nothing 431 * changed. 432 */ updateSettingsForDisplay(@onNull DisplayContent dc)433 boolean updateSettingsForDisplay(@NonNull DisplayContent dc) { 434 final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea(); 435 if (defaultTda != null && defaultTda.getWindowingMode() != getWindowingModeLocked(dc)) { 436 // For the time being the only thing that may change is windowing mode, so just update 437 // that. 438 defaultTda.setWindowingMode(getWindowingModeLocked(dc)); 439 return true; 440 } 441 return false; 442 } 443 444 /** 445 * Called when the given {@link DisplayContent} is removed to cleanup. 446 */ onDisplayRemoved(@onNull DisplayContent dc)447 void onDisplayRemoved(@NonNull DisplayContent dc) { 448 mSettingsProvider.onDisplayRemoved(dc.getDisplayInfo()); 449 } 450 451 /** 452 * Provides the functionality to lookup the {@link SettingsEntry settings} for a given 453 * {@link DisplayInfo}. 454 * <p> 455 * NOTE: All interactions with implementations of this provider <b>must</b> be thread-safe 456 * externally. 457 */ 458 interface SettingsProvider { 459 /** 460 * Returns the {@link SettingsEntry} for a given {@link DisplayInfo}. The values for the 461 * returned settings are guaranteed to match those previously set with 462 * {@link #updateOverrideSettings(DisplayInfo, SettingsEntry)} with all other values left 463 * to the implementation to determine. 464 */ 465 @NonNull getSettings(@onNull DisplayInfo info)466 SettingsEntry getSettings(@NonNull DisplayInfo info); 467 468 /** 469 * Returns the existing override settings for the given {@link DisplayInfo}. All calls to 470 * {@link #getSettings(DisplayInfo)} for the provided {@code info} are required to have 471 * their values overridden with all set values from the returned {@link SettingsEntry}. 472 * 473 * @see #getSettings(DisplayInfo) 474 * @see #updateOverrideSettings(DisplayInfo, SettingsEntry) 475 */ 476 @NonNull getOverrideSettings(@onNull DisplayInfo info)477 SettingsEntry getOverrideSettings(@NonNull DisplayInfo info); 478 479 /** 480 * Updates the override settings for a given {@link DisplayInfo}. All subsequent calls to 481 * {@link #getSettings(DisplayInfo)} for the provided {@link DisplayInfo} are required to 482 * have their values match all set values in {@code overrides}. 483 * 484 * @see #getSettings(DisplayInfo) 485 */ updateOverrideSettings(@onNull DisplayInfo info, @NonNull SettingsEntry overrides)486 void updateOverrideSettings(@NonNull DisplayInfo info, @NonNull SettingsEntry overrides); 487 488 /** 489 * Called when a display is removed to cleanup. Note that for non-virtual displays the 490 * relevant settings entry will be kept, if non-empty. 491 */ onDisplayRemoved(@onNull DisplayInfo info)492 void onDisplayRemoved(@NonNull DisplayInfo info); 493 494 /** 495 * Explicitly removes all settings entory for the given {@link DisplayInfo}, even if it is 496 * not empty. 497 */ clearDisplaySettings(@onNull DisplayInfo info)498 void clearDisplaySettings(@NonNull DisplayInfo info); 499 500 /** 501 * Settings for a display. 502 */ 503 class SettingsEntry { 504 @WindowConfiguration.WindowingMode 505 int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED; 506 @Nullable 507 @WindowManagerPolicy.UserRotationMode 508 Integer mUserRotationMode; 509 @Nullable 510 @Surface.Rotation 511 Integer mUserRotation; 512 int mForcedWidth; 513 int mForcedHeight; 514 int mForcedDensity; 515 /** 516 * The ratio of the forced density to the initial density of the display. This is only 517 * saved for external displays, and used to make sure ratio between forced density and 518 * initial density persist when a resolution change happens. Ratio is updated when 519 * mForcedDensity is changed. 520 */ 521 float mForcedDensityRatio; 522 @Nullable 523 @ForceScalingMode 524 Integer mForcedScalingMode; 525 @WindowManager.RemoveContentMode 526 int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED; 527 @Nullable 528 Boolean mShouldShowWithInsecureKeyguard; 529 @Nullable 530 Boolean mShouldShowSystemDecors; 531 @Nullable 532 Boolean mIsHomeSupported; 533 @Nullable 534 Integer mImePolicy; 535 @Nullable 536 Integer mFixedToUserRotation; 537 @Nullable 538 Boolean mIgnoreOrientationRequest; 539 @Nullable 540 Boolean mIgnoreDisplayCutout; 541 @Nullable 542 Boolean mDontMoveToTop; 543 @Nullable 544 Boolean mIgnoreActivitySizeRestrictions; 545 SettingsEntry()546 SettingsEntry() {} 547 SettingsEntry(@onNull SettingsEntry copyFrom)548 SettingsEntry(@NonNull SettingsEntry copyFrom) { 549 setTo(copyFrom); 550 } 551 552 /** 553 * Copies all fields from {@code delta} into this {@link SettingsEntry} object, keeping 554 * track of whether a change has occurred. 555 * 556 * @return {@code true} if this settings have changed as a result of the copy, 557 * {@code false} otherwise. 558 * 559 * @see #updateFrom(SettingsEntry) 560 */ setTo(@onNull SettingsEntry other)561 boolean setTo(@NonNull SettingsEntry other) { 562 boolean changed = false; 563 if (other.mWindowingMode != mWindowingMode) { 564 mWindowingMode = other.mWindowingMode; 565 changed = true; 566 } 567 if (!Objects.equals(other.mUserRotationMode, mUserRotationMode)) { 568 mUserRotationMode = other.mUserRotationMode; 569 changed = true; 570 } 571 if (!Objects.equals(other.mUserRotation, mUserRotation)) { 572 mUserRotation = other.mUserRotation; 573 changed = true; 574 } 575 if (other.mForcedWidth != mForcedWidth) { 576 mForcedWidth = other.mForcedWidth; 577 changed = true; 578 } 579 if (other.mForcedHeight != mForcedHeight) { 580 mForcedHeight = other.mForcedHeight; 581 changed = true; 582 } 583 if (other.mForcedDensity != mForcedDensity) { 584 mForcedDensity = other.mForcedDensity; 585 changed = true; 586 } 587 if (other.mForcedDensityRatio != mForcedDensityRatio) { 588 mForcedDensityRatio = other.mForcedDensityRatio; 589 changed = true; 590 } 591 if (!Objects.equals(other.mForcedScalingMode, mForcedScalingMode)) { 592 mForcedScalingMode = other.mForcedScalingMode; 593 changed = true; 594 } 595 if (other.mRemoveContentMode != mRemoveContentMode) { 596 mRemoveContentMode = other.mRemoveContentMode; 597 changed = true; 598 } 599 if (!Objects.equals( 600 other.mShouldShowWithInsecureKeyguard, mShouldShowWithInsecureKeyguard)) { 601 mShouldShowWithInsecureKeyguard = other.mShouldShowWithInsecureKeyguard; 602 changed = true; 603 } 604 if (!Objects.equals(other.mShouldShowSystemDecors, mShouldShowSystemDecors)) { 605 mShouldShowSystemDecors = other.mShouldShowSystemDecors; 606 changed = true; 607 } 608 if (!Objects.equals(other.mIsHomeSupported, mIsHomeSupported)) { 609 mIsHomeSupported = other.mIsHomeSupported; 610 changed = true; 611 } 612 if (!Objects.equals(other.mImePolicy, mImePolicy)) { 613 mImePolicy = other.mImePolicy; 614 changed = true; 615 } 616 if (!Objects.equals(other.mFixedToUserRotation, mFixedToUserRotation)) { 617 mFixedToUserRotation = other.mFixedToUserRotation; 618 changed = true; 619 } 620 if (!Objects.equals(other.mIgnoreOrientationRequest, mIgnoreOrientationRequest)) { 621 mIgnoreOrientationRequest = other.mIgnoreOrientationRequest; 622 changed = true; 623 } 624 if (!Objects.equals(other.mIgnoreDisplayCutout, mIgnoreDisplayCutout)) { 625 mIgnoreDisplayCutout = other.mIgnoreDisplayCutout; 626 changed = true; 627 } 628 if (!Objects.equals(other.mDontMoveToTop, mDontMoveToTop)) { 629 mDontMoveToTop = other.mDontMoveToTop; 630 changed = true; 631 } 632 if (!Objects.equals(other.mIgnoreActivitySizeRestrictions, 633 mIgnoreActivitySizeRestrictions)) { 634 mIgnoreActivitySizeRestrictions = other.mIgnoreActivitySizeRestrictions; 635 changed = true; 636 } 637 return changed; 638 } 639 640 /** 641 * Copies the fields from {@code delta} into this {@link SettingsEntry} object, keeping 642 * track of whether a change has occurred. Any undefined fields in {@code delta} are 643 * ignored and not copied into the current {@link SettingsEntry}. 644 * 645 * @return {@code true} if this settings have changed as a result of the copy, 646 * {@code false} otherwise. 647 * 648 * @see #setTo(SettingsEntry) 649 */ updateFrom(@onNull SettingsEntry delta)650 boolean updateFrom(@NonNull SettingsEntry delta) { 651 boolean changed = false; 652 if (delta.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED 653 && delta.mWindowingMode != mWindowingMode) { 654 mWindowingMode = delta.mWindowingMode; 655 changed = true; 656 } 657 if (delta.mUserRotationMode != null 658 && !Objects.equals(delta.mUserRotationMode, mUserRotationMode)) { 659 mUserRotationMode = delta.mUserRotationMode; 660 changed = true; 661 } 662 if (delta.mUserRotation != null 663 && !Objects.equals(delta.mUserRotation, mUserRotation)) { 664 mUserRotation = delta.mUserRotation; 665 changed = true; 666 } 667 if (delta.mForcedWidth != 0 && delta.mForcedWidth != mForcedWidth) { 668 mForcedWidth = delta.mForcedWidth; 669 changed = true; 670 } 671 if (delta.mForcedHeight != 0 && delta.mForcedHeight != mForcedHeight) { 672 mForcedHeight = delta.mForcedHeight; 673 changed = true; 674 } 675 if (delta.mForcedDensity != 0 && delta.mForcedDensity != mForcedDensity) { 676 mForcedDensity = delta.mForcedDensity; 677 changed = true; 678 } 679 if (delta.mForcedDensityRatio != 0 680 && delta.mForcedDensityRatio != mForcedDensityRatio) { 681 mForcedDensityRatio = delta.mForcedDensityRatio; 682 changed = true; 683 } 684 if (delta.mForcedScalingMode != null 685 && !Objects.equals(delta.mForcedScalingMode, mForcedScalingMode)) { 686 mForcedScalingMode = delta.mForcedScalingMode; 687 changed = true; 688 } 689 if (delta.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED 690 && delta.mRemoveContentMode != mRemoveContentMode) { 691 mRemoveContentMode = delta.mRemoveContentMode; 692 changed = true; 693 } 694 if (delta.mShouldShowWithInsecureKeyguard != null && !Objects.equals( 695 delta.mShouldShowWithInsecureKeyguard, mShouldShowWithInsecureKeyguard)) { 696 mShouldShowWithInsecureKeyguard = delta.mShouldShowWithInsecureKeyguard; 697 changed = true; 698 } 699 if (delta.mShouldShowSystemDecors != null && !Objects.equals( 700 delta.mShouldShowSystemDecors, mShouldShowSystemDecors)) { 701 mShouldShowSystemDecors = delta.mShouldShowSystemDecors; 702 changed = true; 703 } 704 if (delta.mIsHomeSupported != null && !Objects.equals( 705 delta.mIsHomeSupported, mIsHomeSupported)) { 706 mIsHomeSupported = delta.mIsHomeSupported; 707 changed = true; 708 } 709 if (delta.mImePolicy != null 710 && !Objects.equals(delta.mImePolicy, mImePolicy)) { 711 mImePolicy = delta.mImePolicy; 712 changed = true; 713 } 714 if (delta.mFixedToUserRotation != null 715 && !Objects.equals(delta.mFixedToUserRotation, mFixedToUserRotation)) { 716 mFixedToUserRotation = delta.mFixedToUserRotation; 717 changed = true; 718 } 719 if (delta.mIgnoreOrientationRequest != null && !Objects.equals( 720 delta.mIgnoreOrientationRequest, mIgnoreOrientationRequest)) { 721 mIgnoreOrientationRequest = delta.mIgnoreOrientationRequest; 722 changed = true; 723 } 724 if (delta.mIgnoreDisplayCutout != null && !Objects.equals( 725 delta.mIgnoreDisplayCutout, mIgnoreDisplayCutout)) { 726 mIgnoreDisplayCutout = delta.mIgnoreDisplayCutout; 727 changed = true; 728 } 729 if (delta.mDontMoveToTop != null && !Objects.equals( 730 delta.mDontMoveToTop, mDontMoveToTop)) { 731 mDontMoveToTop = delta.mDontMoveToTop; 732 changed = true; 733 } 734 if (delta.mIgnoreActivitySizeRestrictions != null && !Objects.equals( 735 delta.mIgnoreActivitySizeRestrictions, mIgnoreActivitySizeRestrictions)) { 736 mIgnoreActivitySizeRestrictions = delta.mIgnoreActivitySizeRestrictions; 737 changed = true; 738 } 739 return changed; 740 } 741 742 /** @return {@code true} if all values are unset. */ isEmpty()743 boolean isEmpty() { 744 return mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED 745 && mUserRotationMode == null 746 && mUserRotation == null 747 && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0 748 && mForcedDensityRatio == 0.0f 749 && mForcedScalingMode == null 750 && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED 751 && mShouldShowWithInsecureKeyguard == null 752 && mShouldShowSystemDecors == null 753 && mIsHomeSupported == null 754 && mImePolicy == null 755 && mFixedToUserRotation == null 756 && mIgnoreOrientationRequest == null 757 && mIgnoreDisplayCutout == null 758 && mDontMoveToTop == null 759 && mIgnoreActivitySizeRestrictions == null; 760 } 761 762 @Override equals(@ullable Object o)763 public boolean equals(@Nullable Object o) { 764 if (this == o) return true; 765 if (o == null || getClass() != o.getClass()) return false; 766 SettingsEntry that = (SettingsEntry) o; 767 return mWindowingMode == that.mWindowingMode 768 && mForcedWidth == that.mForcedWidth 769 && mForcedHeight == that.mForcedHeight 770 && mForcedDensity == that.mForcedDensity 771 && mRemoveContentMode == that.mRemoveContentMode 772 && mForcedDensityRatio == that.mForcedDensityRatio 773 && Objects.equals(mUserRotationMode, that.mUserRotationMode) 774 && Objects.equals(mUserRotation, that.mUserRotation) 775 && Objects.equals(mForcedScalingMode, that.mForcedScalingMode) 776 && Objects.equals(mShouldShowWithInsecureKeyguard, 777 that.mShouldShowWithInsecureKeyguard) 778 && Objects.equals(mShouldShowSystemDecors, that.mShouldShowSystemDecors) 779 && Objects.equals(mIsHomeSupported, that.mIsHomeSupported) 780 && Objects.equals(mImePolicy, that.mImePolicy) 781 && Objects.equals(mFixedToUserRotation, that.mFixedToUserRotation) 782 && Objects.equals(mIgnoreOrientationRequest, that.mIgnoreOrientationRequest) 783 && Objects.equals(mIgnoreDisplayCutout, that.mIgnoreDisplayCutout) 784 && Objects.equals(mDontMoveToTop, that.mDontMoveToTop) 785 && Objects.equals(mIgnoreActivitySizeRestrictions, 786 that.mIgnoreActivitySizeRestrictions); 787 } 788 789 @Override hashCode()790 public int hashCode() { 791 return Objects.hash(mWindowingMode, mUserRotationMode, mUserRotation, mForcedWidth, 792 mForcedHeight, mForcedDensity, mForcedDensityRatio, mForcedScalingMode, 793 mRemoveContentMode, mShouldShowWithInsecureKeyguard, 794 mShouldShowSystemDecors, mIsHomeSupported, mImePolicy, mFixedToUserRotation, 795 mIgnoreOrientationRequest, mIgnoreDisplayCutout, mDontMoveToTop, 796 mIgnoreActivitySizeRestrictions); 797 } 798 799 @Override toString()800 public String toString() { 801 return "SettingsEntry{" 802 + "mWindowingMode=" + mWindowingMode 803 + ", mUserRotationMode=" + mUserRotationMode 804 + ", mUserRotation=" + mUserRotation 805 + ", mForcedWidth=" + mForcedWidth 806 + ", mForcedHeight=" + mForcedHeight 807 + ", mForcedDensity=" + mForcedDensity 808 + ", mForcedDensityRatio=" + mForcedDensityRatio 809 + ", mForcedScalingMode=" + mForcedScalingMode 810 + ", mRemoveContentMode=" + mRemoveContentMode 811 + ", mShouldShowWithInsecureKeyguard=" + mShouldShowWithInsecureKeyguard 812 + ", mShouldShowSystemDecors=" + mShouldShowSystemDecors 813 + ", mIsHomeSupported=" + mIsHomeSupported 814 + ", mShouldShowIme=" + mImePolicy 815 + ", mFixedToUserRotation=" + mFixedToUserRotation 816 + ", mIgnoreOrientationRequest=" + mIgnoreOrientationRequest 817 + ", mIgnoreDisplayCutout=" + mIgnoreDisplayCutout 818 + ", mDontMoveToTop=" + mDontMoveToTop 819 + ", mForceAppsUniversalResizable=" + mIgnoreActivitySizeRestrictions 820 + '}'; 821 } 822 } 823 } 824 } 825