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.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
20 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
21 import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
22 import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
23 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
24 
25 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
26 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
27 
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.app.WindowConfiguration;
31 import android.provider.Settings;
32 import android.view.Display;
33 import android.view.DisplayInfo;
34 import android.view.IWindowManager;
35 import android.view.Surface;
36 import android.view.WindowManager.DisplayImePolicy;
37 
38 import com.android.server.policy.WindowManagerPolicy;
39 import com.android.server.wm.DisplayContent.ForceScalingMode;
40 
41 import java.util.Objects;
42 
43 /**
44  * Current persistent settings about a display. Provides policies for display settings and
45  * delegates the persistence and lookup of settings values to the supplied {@link SettingsProvider}.
46  */
47 class DisplayWindowSettings {
48     private final WindowManagerService mService;
49     private final SettingsProvider mSettingsProvider;
50 
DisplayWindowSettings(WindowManagerService service, SettingsProvider settingsProvider)51     DisplayWindowSettings(WindowManagerService service, SettingsProvider settingsProvider) {
52         mService = service;
53         mSettingsProvider = settingsProvider;
54     }
55 
setUserRotation(DisplayContent displayContent, int rotationMode, int rotation)56     void setUserRotation(DisplayContent displayContent, int rotationMode, int rotation) {
57         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
58         final SettingsProvider.SettingsEntry overrideSettings =
59                 mSettingsProvider.getOverrideSettings(displayInfo);
60         overrideSettings.mUserRotationMode = rotationMode;
61         overrideSettings.mUserRotation = rotation;
62         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
63     }
64 
setForcedSize(DisplayContent displayContent, int width, int height)65     void setForcedSize(DisplayContent displayContent, int width, int height) {
66         if (displayContent.isDefaultDisplay) {
67             final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
68             Settings.Global.putString(mService.mContext.getContentResolver(),
69                     Settings.Global.DISPLAY_SIZE_FORCED, sizeString);
70         }
71 
72         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
73         final SettingsProvider.SettingsEntry overrideSettings =
74                 mSettingsProvider.getOverrideSettings(displayInfo);
75         overrideSettings.mForcedWidth = width;
76         overrideSettings.mForcedHeight = height;
77         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
78     }
79 
setForcedDensity(DisplayInfo info, int density, int userId)80     void setForcedDensity(DisplayInfo info, int density, int userId) {
81         if (info.displayId == Display.DEFAULT_DISPLAY) {
82             final String densityString = density == 0 ? "" : Integer.toString(density);
83             Settings.Secure.putStringForUser(mService.mContext.getContentResolver(),
84                     Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId);
85         }
86 
87         final DisplayInfo displayInfo = info;
88         final SettingsProvider.SettingsEntry overrideSettings =
89                 mSettingsProvider.getOverrideSettings(displayInfo);
90         overrideSettings.mForcedDensity = density;
91         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
92     }
93 
setForcedScalingMode(DisplayContent displayContent, @ForceScalingMode int mode)94     void setForcedScalingMode(DisplayContent displayContent, @ForceScalingMode int mode) {
95         if (displayContent.isDefaultDisplay) {
96             Settings.Global.putInt(mService.mContext.getContentResolver(),
97                     Settings.Global.DISPLAY_SCALING_FORCE, mode);
98         }
99 
100         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
101         final SettingsProvider.SettingsEntry overrideSettings =
102                 mSettingsProvider.getOverrideSettings(displayInfo);
103         overrideSettings.mForcedScalingMode = mode;
104         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
105     }
106 
setFixedToUserRotation(DisplayContent displayContent, int fixedToUserRotation)107     void setFixedToUserRotation(DisplayContent displayContent, int fixedToUserRotation) {
108         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
109         final SettingsProvider.SettingsEntry overrideSettings =
110                 mSettingsProvider.getOverrideSettings(displayInfo);
111         overrideSettings.mFixedToUserRotation = fixedToUserRotation;
112         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
113     }
114 
setIgnoreOrientationRequest( DisplayContent displayContent, boolean ignoreOrientationRequest)115     void setIgnoreOrientationRequest(
116             DisplayContent displayContent, boolean ignoreOrientationRequest) {
117         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
118         final SettingsProvider.SettingsEntry overrideSettings =
119                 mSettingsProvider.getOverrideSettings(displayInfo);
120         overrideSettings.mIgnoreOrientationRequest = ignoreOrientationRequest;
121         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
122     }
123 
getWindowingModeLocked(SettingsProvider.SettingsEntry settings, DisplayContent dc)124     private int getWindowingModeLocked(SettingsProvider.SettingsEntry settings, DisplayContent dc) {
125         int windowingMode = settings.mWindowingMode;
126         // This display used to be in freeform, but we don't support freeform anymore, so fall
127         // back to fullscreen.
128         if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
129                 && !mService.mAtmService.mSupportsFreeformWindowManagement) {
130             return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
131         }
132         // No record is present so use default windowing mode policy.
133         if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
134             windowingMode = mService.mAtmService.mSupportsFreeformWindowManagement
135                     && (mService.mIsPc || dc.forceDesktopMode())
136                     ? WindowConfiguration.WINDOWING_MODE_FREEFORM
137                     : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
138         }
139         return windowingMode;
140     }
141 
getWindowingModeLocked(DisplayContent dc)142     int getWindowingModeLocked(DisplayContent dc) {
143         final DisplayInfo displayInfo = dc.getDisplayInfo();
144         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
145         return getWindowingModeLocked(settings, dc);
146     }
147 
setWindowingModeLocked(DisplayContent dc, int mode)148     void setWindowingModeLocked(DisplayContent dc, int mode) {
149         final DisplayInfo displayInfo = dc.getDisplayInfo();
150         final SettingsProvider.SettingsEntry overrideSettings =
151                 mSettingsProvider.getOverrideSettings(displayInfo);
152         overrideSettings.mWindowingMode = mode;
153         final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea();
154         if (defaultTda != null) {
155             defaultTda.setWindowingMode(mode);
156         }
157         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
158     }
159 
getRemoveContentModeLocked(DisplayContent dc)160     int getRemoveContentModeLocked(DisplayContent dc) {
161         final DisplayInfo displayInfo = dc.getDisplayInfo();
162         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
163         if (settings.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
164             if (dc.isPrivate()) {
165                 // For private displays by default content is destroyed on removal.
166                 return REMOVE_CONTENT_MODE_DESTROY;
167             }
168             // For other displays by default content is moved to primary on removal.
169             return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
170         }
171         return settings.mRemoveContentMode;
172     }
173 
setRemoveContentModeLocked(DisplayContent dc, int mode)174     void setRemoveContentModeLocked(DisplayContent dc, int mode) {
175         final DisplayInfo displayInfo = dc.getDisplayInfo();
176         final SettingsProvider.SettingsEntry overrideSettings =
177                 mSettingsProvider.getOverrideSettings(displayInfo);
178         overrideSettings.mRemoveContentMode = mode;
179         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
180     }
181 
shouldShowWithInsecureKeyguardLocked(DisplayContent dc)182     boolean shouldShowWithInsecureKeyguardLocked(DisplayContent dc) {
183         final DisplayInfo displayInfo = dc.getDisplayInfo();
184         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
185         return settings.mShouldShowWithInsecureKeyguard != null
186                 ? settings.mShouldShowWithInsecureKeyguard : false;
187     }
188 
setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow)189     void setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow) {
190         if (!dc.isPrivate() && shouldShow) {
191             throw new IllegalArgumentException("Public display can't be allowed to show content"
192                     + " when locked");
193         }
194 
195         final DisplayInfo displayInfo = dc.getDisplayInfo();
196         final SettingsProvider.SettingsEntry overrideSettings =
197                 mSettingsProvider.getOverrideSettings(displayInfo);
198         overrideSettings.mShouldShowWithInsecureKeyguard = shouldShow;
199         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
200     }
201 
setDontMoveToTop(DisplayContent dc, boolean dontMoveToTop)202     void setDontMoveToTop(DisplayContent dc, boolean dontMoveToTop) {
203         DisplayInfo displayInfo = dc.getDisplayInfo();
204         SettingsProvider.SettingsEntry overrideSettings =
205                 mSettingsProvider.getSettings(displayInfo);
206         overrideSettings.mDontMoveToTop = dontMoveToTop;
207         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
208     }
209 
shouldShowSystemDecorsLocked(DisplayContent dc)210     boolean shouldShowSystemDecorsLocked(DisplayContent dc) {
211         if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
212             // Default display should show system decors.
213             return true;
214         }
215 
216         final DisplayInfo displayInfo = dc.getDisplayInfo();
217         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
218         return settings.mShouldShowSystemDecors != null ? settings.mShouldShowSystemDecors : false;
219     }
220 
setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow)221     void setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow) {
222         final DisplayInfo displayInfo = dc.getDisplayInfo();
223         final SettingsProvider.SettingsEntry overrideSettings =
224                 mSettingsProvider.getOverrideSettings(displayInfo);
225         overrideSettings.mShouldShowSystemDecors = shouldShow;
226         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
227     }
228 
getImePolicyLocked(DisplayContent dc)229     @DisplayImePolicy int getImePolicyLocked(DisplayContent dc) {
230         if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
231             // Default display should show IME.
232             return DISPLAY_IME_POLICY_LOCAL;
233         }
234 
235         final DisplayInfo displayInfo = dc.getDisplayInfo();
236         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
237         return settings.mImePolicy != null ? settings.mImePolicy
238                 : DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
239     }
240 
setDisplayImePolicy(DisplayContent dc, @DisplayImePolicy int imePolicy)241     void setDisplayImePolicy(DisplayContent dc, @DisplayImePolicy int imePolicy) {
242         final DisplayInfo displayInfo = dc.getDisplayInfo();
243         final SettingsProvider.SettingsEntry overrideSettings =
244                 mSettingsProvider.getOverrideSettings(displayInfo);
245         overrideSettings.mImePolicy = imePolicy;
246         mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
247     }
248 
applySettingsToDisplayLocked(DisplayContent dc)249     void applySettingsToDisplayLocked(DisplayContent dc) {
250         applySettingsToDisplayLocked(dc, /* includeRotationSettings */ true);
251     }
252 
applySettingsToDisplayLocked(DisplayContent dc, boolean includeRotationSettings)253     void applySettingsToDisplayLocked(DisplayContent dc, boolean includeRotationSettings) {
254         final DisplayInfo displayInfo = dc.getDisplayInfo();
255         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
256 
257         // Setting windowing mode first, because it may override overscan values later.
258         final int windowingMode = getWindowingModeLocked(settings, dc);
259         final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea();
260         if (defaultTda != null) {
261             defaultTda.setWindowingMode(windowingMode);
262         }
263         final int userRotationMode = settings.mUserRotationMode != null
264                 ? settings.mUserRotationMode : WindowManagerPolicy.USER_ROTATION_FREE;
265         final int userRotation = settings.mUserRotation != null
266                 ? settings.mUserRotation : Surface.ROTATION_0;
267         final int mFixedToUserRotation = settings.mFixedToUserRotation != null
268                 ? settings.mFixedToUserRotation : IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
269         dc.getDisplayRotation().restoreSettings(userRotationMode, userRotation,
270                 mFixedToUserRotation);
271 
272         final boolean hasDensityOverride = settings.mForcedDensity != 0;
273         final boolean hasSizeOverride = settings.mForcedWidth != 0 && settings.mForcedHeight != 0;
274         dc.mIsDensityForced = hasDensityOverride;
275         dc.mIsSizeForced = hasSizeOverride;
276 
277         final boolean ignoreDisplayCutout = settings.mIgnoreDisplayCutout != null
278                 ? settings.mIgnoreDisplayCutout : false;
279         dc.mIgnoreDisplayCutout = ignoreDisplayCutout;
280 
281         final int width = hasSizeOverride ? settings.mForcedWidth : dc.mInitialDisplayWidth;
282         final int height = hasSizeOverride ? settings.mForcedHeight : dc.mInitialDisplayHeight;
283         final int density = hasDensityOverride ? settings.mForcedDensity
284                 : dc.getInitialDisplayDensity();
285         dc.updateBaseDisplayMetrics(width, height, density, dc.mBaseDisplayPhysicalXDpi,
286                 dc.mBaseDisplayPhysicalYDpi);
287 
288         final int forcedScalingMode = settings.mForcedScalingMode != null
289                 ? settings.mForcedScalingMode : FORCE_SCALING_MODE_AUTO;
290         dc.mDisplayScalingDisabled = forcedScalingMode == FORCE_SCALING_MODE_DISABLED;
291 
292         boolean dontMoveToTop = settings.mDontMoveToTop != null
293                 ? settings.mDontMoveToTop : false;
294         dc.mDontMoveToTop = !dc.canStealTopFocus() || dontMoveToTop;
295 
296         if (includeRotationSettings) applyRotationSettingsToDisplayLocked(dc);
297     }
298 
applyRotationSettingsToDisplayLocked(DisplayContent dc)299     void applyRotationSettingsToDisplayLocked(DisplayContent dc) {
300         final DisplayInfo displayInfo = dc.getDisplayInfo();
301         final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
302 
303         final boolean ignoreOrientationRequest = settings.mIgnoreOrientationRequest != null
304                 ? settings.mIgnoreOrientationRequest : false;
305         dc.setIgnoreOrientationRequest(ignoreOrientationRequest);
306 
307         dc.getDisplayRotation().resetAllowAllRotations();
308     }
309 
310     /**
311      * Updates settings for the given display after system features are loaded into window manager
312      * service, e.g. if this device is PC and if this device supports freeform.
313      *
314      * @param dc the given display.
315      * @return {@code true} if any settings for this display has changed; {@code false} if nothing
316      * changed.
317      */
updateSettingsForDisplay(DisplayContent dc)318     boolean updateSettingsForDisplay(DisplayContent dc) {
319         final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea();
320         if (defaultTda != null && defaultTda.getWindowingMode() != getWindowingModeLocked(dc)) {
321             // For the time being the only thing that may change is windowing mode, so just update
322             // that.
323             defaultTda.setWindowingMode(getWindowingModeLocked(dc));
324             return true;
325         }
326         return false;
327     }
328 
329     /**
330      * Provides the functionality to lookup the {@link SettingsEntry settings} for a given
331      * {@link DisplayInfo}.
332      * <p>
333      * NOTE: All interactions with implementations of this provider <b>must</b> be thread-safe
334      * externally.
335      */
336     interface SettingsProvider {
337         /**
338          * Returns the {@link SettingsEntry} for a given {@link DisplayInfo}. The values for the
339          * returned settings are guaranteed to match those previously set with
340          * {@link #updateOverrideSettings(DisplayInfo, SettingsEntry)} with all other values left
341          * to the implementation to determine.
342          */
343         @NonNull
getSettings(@onNull DisplayInfo info)344         SettingsEntry getSettings(@NonNull DisplayInfo info);
345 
346         /**
347          * Returns the existing override settings for the given {@link DisplayInfo}. All calls to
348          * {@link #getSettings(DisplayInfo)} for the provided {@code info} are required to have
349          * their values overridden with all set values from the returned {@link SettingsEntry}.
350          *
351          * @see #getSettings(DisplayInfo)
352          * @see #updateOverrideSettings(DisplayInfo, SettingsEntry)
353          */
354         @NonNull
getOverrideSettings(@onNull DisplayInfo info)355         SettingsEntry getOverrideSettings(@NonNull DisplayInfo info);
356 
357         /**
358          * Updates the override settings for a given {@link DisplayInfo}. All subsequent calls to
359          * {@link #getSettings(DisplayInfo)} for the provided {@link DisplayInfo} are required to
360          * have their values match all set values in {@code overrides}.
361          *
362          * @see #getSettings(DisplayInfo)
363          */
updateOverrideSettings(@onNull DisplayInfo info, @NonNull SettingsEntry overrides)364         void updateOverrideSettings(@NonNull DisplayInfo info, @NonNull SettingsEntry overrides);
365 
366         /**
367          * Settings for a display.
368          */
369         class SettingsEntry {
370             int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
371             @Nullable
372             Integer mUserRotationMode;
373             @Nullable
374             Integer mUserRotation;
375             int mForcedWidth;
376             int mForcedHeight;
377             int mForcedDensity;
378             @Nullable
379             Integer mForcedScalingMode;
380             int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
381             @Nullable
382             Boolean mShouldShowWithInsecureKeyguard;
383             @Nullable
384             Boolean mShouldShowSystemDecors;
385             @Nullable
386             Integer mImePolicy;
387             @Nullable
388             Integer mFixedToUserRotation;
389             @Nullable
390             Boolean mIgnoreOrientationRequest;
391             @Nullable
392             Boolean mIgnoreDisplayCutout;
393             @Nullable
394             Boolean mDontMoveToTop;
395 
SettingsEntry()396             SettingsEntry() {}
397 
SettingsEntry(SettingsEntry copyFrom)398             SettingsEntry(SettingsEntry copyFrom) {
399                 setTo(copyFrom);
400             }
401 
402             /**
403              * Copies all fields from {@code delta} into this {@link SettingsEntry} object, keeping
404              * track of whether a change has occurred.
405              *
406              * @return {@code true} if this settings have changed as a result of the copy,
407              *         {@code false} otherwise.
408              *
409              * @see #updateFrom(SettingsEntry)
410              */
setTo(@onNull SettingsEntry other)411             boolean setTo(@NonNull SettingsEntry other) {
412                 boolean changed = false;
413                 if (other.mWindowingMode != mWindowingMode) {
414                     mWindowingMode = other.mWindowingMode;
415                     changed = true;
416                 }
417                 if (!Objects.equals(other.mUserRotationMode, mUserRotationMode)) {
418                     mUserRotationMode = other.mUserRotationMode;
419                     changed = true;
420                 }
421                 if (!Objects.equals(other.mUserRotation, mUserRotation)) {
422                     mUserRotation = other.mUserRotation;
423                     changed = true;
424                 }
425                 if (other.mForcedWidth != mForcedWidth) {
426                     mForcedWidth = other.mForcedWidth;
427                     changed = true;
428                 }
429                 if (other.mForcedHeight != mForcedHeight) {
430                     mForcedHeight = other.mForcedHeight;
431                     changed = true;
432                 }
433                 if (other.mForcedDensity != mForcedDensity) {
434                     mForcedDensity = other.mForcedDensity;
435                     changed = true;
436                 }
437                 if (!Objects.equals(other.mForcedScalingMode, mForcedScalingMode)) {
438                     mForcedScalingMode = other.mForcedScalingMode;
439                     changed = true;
440                 }
441                 if (other.mRemoveContentMode != mRemoveContentMode) {
442                     mRemoveContentMode = other.mRemoveContentMode;
443                     changed = true;
444                 }
445                 if (!Objects.equals(
446                         other.mShouldShowWithInsecureKeyguard, mShouldShowWithInsecureKeyguard)) {
447                     mShouldShowWithInsecureKeyguard = other.mShouldShowWithInsecureKeyguard;
448                     changed = true;
449                 }
450                 if (!Objects.equals(other.mShouldShowSystemDecors, mShouldShowSystemDecors)) {
451                     mShouldShowSystemDecors = other.mShouldShowSystemDecors;
452                     changed = true;
453                 }
454                 if (!Objects.equals(other.mImePolicy, mImePolicy)) {
455                     mImePolicy = other.mImePolicy;
456                     changed = true;
457                 }
458                 if (!Objects.equals(other.mFixedToUserRotation, mFixedToUserRotation)) {
459                     mFixedToUserRotation = other.mFixedToUserRotation;
460                     changed = true;
461                 }
462                 if (!Objects.equals(other.mIgnoreOrientationRequest, mIgnoreOrientationRequest)) {
463                     mIgnoreOrientationRequest = other.mIgnoreOrientationRequest;
464                     changed = true;
465                 }
466                 if (!Objects.equals(other.mIgnoreDisplayCutout, mIgnoreDisplayCutout)) {
467                     mIgnoreDisplayCutout = other.mIgnoreDisplayCutout;
468                     changed = true;
469                 }
470                 if (!Objects.equals(other.mDontMoveToTop, mDontMoveToTop)) {
471                     mDontMoveToTop = other.mDontMoveToTop;
472                     changed = true;
473                 }
474                 return changed;
475             }
476 
477             /**
478              * Copies the fields from {@code delta} into this {@link SettingsEntry} object, keeping
479              * track of whether a change has occurred. Any undefined fields in {@code delta} are
480              * ignored and not copied into the current {@link SettingsEntry}.
481              *
482              * @return {@code true} if this settings have changed as a result of the copy,
483              *         {@code false} otherwise.
484              *
485              * @see #setTo(SettingsEntry)
486              */
updateFrom(@onNull SettingsEntry delta)487             boolean updateFrom(@NonNull SettingsEntry delta) {
488                 boolean changed = false;
489                 if (delta.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED
490                         && delta.mWindowingMode != mWindowingMode) {
491                     mWindowingMode = delta.mWindowingMode;
492                     changed = true;
493                 }
494                 if (delta.mUserRotationMode != null
495                         && !Objects.equals(delta.mUserRotationMode, mUserRotationMode)) {
496                     mUserRotationMode = delta.mUserRotationMode;
497                     changed = true;
498                 }
499                 if (delta.mUserRotation != null
500                         && !Objects.equals(delta.mUserRotation, mUserRotation)) {
501                     mUserRotation = delta.mUserRotation;
502                     changed = true;
503                 }
504                 if (delta.mForcedWidth != 0 && delta.mForcedWidth != mForcedWidth) {
505                     mForcedWidth = delta.mForcedWidth;
506                     changed = true;
507                 }
508                 if (delta.mForcedHeight != 0 && delta.mForcedHeight != mForcedHeight) {
509                     mForcedHeight = delta.mForcedHeight;
510                     changed = true;
511                 }
512                 if (delta.mForcedDensity != 0 && delta.mForcedDensity != mForcedDensity) {
513                     mForcedDensity = delta.mForcedDensity;
514                     changed = true;
515                 }
516                 if (delta.mForcedScalingMode != null
517                         && !Objects.equals(delta.mForcedScalingMode, mForcedScalingMode)) {
518                     mForcedScalingMode = delta.mForcedScalingMode;
519                     changed = true;
520                 }
521                 if (delta.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED
522                         && delta.mRemoveContentMode != mRemoveContentMode) {
523                     mRemoveContentMode = delta.mRemoveContentMode;
524                     changed = true;
525                 }
526                 if (delta.mShouldShowWithInsecureKeyguard != null && !Objects.equals(
527                         delta.mShouldShowWithInsecureKeyguard, mShouldShowWithInsecureKeyguard)) {
528                     mShouldShowWithInsecureKeyguard = delta.mShouldShowWithInsecureKeyguard;
529                     changed = true;
530                 }
531                 if (delta.mShouldShowSystemDecors != null && !Objects.equals(
532                         delta.mShouldShowSystemDecors, mShouldShowSystemDecors)) {
533                     mShouldShowSystemDecors = delta.mShouldShowSystemDecors;
534                     changed = true;
535                 }
536                 if (delta.mImePolicy != null
537                         && !Objects.equals(delta.mImePolicy, mImePolicy)) {
538                     mImePolicy = delta.mImePolicy;
539                     changed = true;
540                 }
541                 if (delta.mFixedToUserRotation != null
542                         && !Objects.equals(delta.mFixedToUserRotation, mFixedToUserRotation)) {
543                     mFixedToUserRotation = delta.mFixedToUserRotation;
544                     changed = true;
545                 }
546                 if (delta.mIgnoreOrientationRequest != null && !Objects.equals(
547                         delta.mIgnoreOrientationRequest, mIgnoreOrientationRequest)) {
548                     mIgnoreOrientationRequest = delta.mIgnoreOrientationRequest;
549                     changed = true;
550                 }
551                 if (delta.mIgnoreDisplayCutout != null && !Objects.equals(
552                         delta.mIgnoreDisplayCutout, mIgnoreDisplayCutout)) {
553                     mIgnoreDisplayCutout = delta.mIgnoreDisplayCutout;
554                     changed = true;
555                 }
556                 if (delta.mDontMoveToTop != null && !Objects.equals(
557                         delta.mDontMoveToTop, mDontMoveToTop)) {
558                     mDontMoveToTop = delta.mDontMoveToTop;
559                     changed = true;
560                 }
561                 return changed;
562             }
563 
564             /** @return {@code true} if all values are unset. */
isEmpty()565             boolean isEmpty() {
566                 return mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
567                         && mUserRotationMode == null
568                         && mUserRotation == null
569                         && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
570                         && mForcedScalingMode == null
571                         && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
572                         && mShouldShowWithInsecureKeyguard == null
573                         && mShouldShowSystemDecors == null
574                         && mImePolicy == null
575                         && mFixedToUserRotation == null
576                         && mIgnoreOrientationRequest == null
577                         && mIgnoreDisplayCutout == null
578                         && mDontMoveToTop == null;
579             }
580 
581             @Override
equals(@ullable Object o)582             public boolean equals(@Nullable Object o) {
583                 if (this == o) return true;
584                 if (o == null || getClass() != o.getClass()) return false;
585                 SettingsEntry that = (SettingsEntry) o;
586                 return mWindowingMode == that.mWindowingMode
587                         && mForcedWidth == that.mForcedWidth
588                         && mForcedHeight == that.mForcedHeight
589                         && mForcedDensity == that.mForcedDensity
590                         && mRemoveContentMode == that.mRemoveContentMode
591                         && Objects.equals(mUserRotationMode, that.mUserRotationMode)
592                         && Objects.equals(mUserRotation, that.mUserRotation)
593                         && Objects.equals(mForcedScalingMode, that.mForcedScalingMode)
594                         && Objects.equals(mShouldShowWithInsecureKeyguard,
595                                 that.mShouldShowWithInsecureKeyguard)
596                         && Objects.equals(mShouldShowSystemDecors, that.mShouldShowSystemDecors)
597                         && Objects.equals(mImePolicy, that.mImePolicy)
598                         && Objects.equals(mFixedToUserRotation, that.mFixedToUserRotation)
599                         && Objects.equals(mIgnoreOrientationRequest, that.mIgnoreOrientationRequest)
600                         && Objects.equals(mIgnoreDisplayCutout, that.mIgnoreDisplayCutout)
601                         && Objects.equals(mDontMoveToTop, that.mDontMoveToTop);
602             }
603 
604             @Override
hashCode()605             public int hashCode() {
606                 return Objects.hash(mWindowingMode, mUserRotationMode, mUserRotation, mForcedWidth,
607                         mForcedHeight, mForcedDensity, mForcedScalingMode, mRemoveContentMode,
608                         mShouldShowWithInsecureKeyguard, mShouldShowSystemDecors, mImePolicy,
609                         mFixedToUserRotation, mIgnoreOrientationRequest, mIgnoreDisplayCutout,
610                         mDontMoveToTop);
611             }
612 
613             @Override
toString()614             public String toString() {
615                 return "SettingsEntry{"
616                         + "mWindowingMode=" + mWindowingMode
617                         + ", mUserRotationMode=" + mUserRotationMode
618                         + ", mUserRotation=" + mUserRotation
619                         + ", mForcedWidth=" + mForcedWidth
620                         + ", mForcedHeight=" + mForcedHeight
621                         + ", mForcedDensity=" + mForcedDensity
622                         + ", mForcedScalingMode=" + mForcedScalingMode
623                         + ", mRemoveContentMode=" + mRemoveContentMode
624                         + ", mShouldShowWithInsecureKeyguard=" + mShouldShowWithInsecureKeyguard
625                         + ", mShouldShowSystemDecors=" + mShouldShowSystemDecors
626                         + ", mShouldShowIme=" + mImePolicy
627                         + ", mFixedToUserRotation=" + mFixedToUserRotation
628                         + ", mIgnoreOrientationRequest=" + mIgnoreOrientationRequest
629                         + ", mIgnoreDisplayCutout=" + mIgnoreDisplayCutout
630                         + ", mDontMoveToTop=" + mDontMoveToTop
631                         + '}';
632             }
633         }
634     }
635 }
636