blob: db96847e802b032f16d10fdcb4e2c9dd0eff0565 [file] [log] [blame]
Dianne Hackbornc652de82013-02-15 16:32:56 -08001/*
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
17package com.android.server.wm;
18
Chilun8753ad32018-10-09 15:56:45 +080019import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
20import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
21import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
22
Riddle Hsuf53da812018-08-15 22:00:27 +080023import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
24import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
Garfield Tan7fbca052019-02-19 10:45:35 -080025import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080026import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
28
Garfield Tane0846042018-07-26 13:42:04 -070029import android.app.WindowConfiguration;
Dianne Hackbornc652de82013-02-15 16:32:56 -080030import android.os.Environment;
Riddle Hsuf53da812018-08-15 22:00:27 +080031import android.provider.Settings;
Dianne Hackbornc652de82013-02-15 16:32:56 -080032import android.util.AtomicFile;
33import android.util.Slog;
34import android.util.Xml;
Garfield Tane0846042018-07-26 13:42:04 -070035import android.view.Display;
36import android.view.DisplayInfo;
Garfield Tan90c90052018-10-08 12:29:41 -070037import android.view.Surface;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080038
Garfield Tane0846042018-07-26 13:42:04 -070039import com.android.internal.annotations.VisibleForTesting;
Dianne Hackbornc652de82013-02-15 16:32:56 -080040import com.android.internal.util.FastXmlSerializer;
41import com.android.internal.util.XmlUtils;
Garfield Tan90c90052018-10-08 12:29:41 -070042import com.android.server.policy.WindowManagerPolicy;
Riddle Hsuf53da812018-08-15 22:00:27 +080043import com.android.server.wm.DisplayContent.ForceScalingMode;
Garfield Tan90c90052018-10-08 12:29:41 -070044
45import org.xmlpull.v1.XmlPullParser;
46import org.xmlpull.v1.XmlPullParserException;
47import org.xmlpull.v1.XmlSerializer;
Dianne Hackbornc652de82013-02-15 16:32:56 -080048
49import java.io.File;
50import java.io.FileInputStream;
51import java.io.FileNotFoundException;
52import java.io.FileOutputStream;
53import java.io.IOException;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010054import java.nio.charset.StandardCharsets;
Dianne Hackbornc652de82013-02-15 16:32:56 -080055import java.util.HashMap;
56
57/**
58 * Current persistent settings about a display
59 */
Chilun8753ad32018-10-09 15:56:45 +080060class DisplayWindowSettings {
61 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM;
Dianne Hackbornc652de82013-02-15 16:32:56 -080062
Garfield Tane0846042018-07-26 13:42:04 -070063 private final WindowManagerService mService;
Dianne Hackbornc652de82013-02-15 16:32:56 -080064 private final AtomicFile mFile;
65 private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>();
66
Garfield Tane0846042018-07-26 13:42:04 -070067 private static class Entry {
Garfield Tan90c90052018-10-08 12:29:41 -070068 private final String mName;
69 private int mOverscanLeft;
70 private int mOverscanTop;
71 private int mOverscanRight;
72 private int mOverscanBottom;
73 private int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
74 private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
75 private int mUserRotation = Surface.ROTATION_0;
Riddle Hsuf53da812018-08-15 22:00:27 +080076 private int mForcedWidth;
77 private int mForcedHeight;
78 private int mForcedDensity;
79 private int mForcedScalingMode = FORCE_SCALING_MODE_AUTO;
Chilun8753ad32018-10-09 15:56:45 +080080 private int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
81 private boolean mShouldShowWithInsecureKeyguard = false;
82 private boolean mShouldShowSystemDecors = false;
83 private boolean mShouldShowIme = false;
Garfield Tan7fbca052019-02-19 10:45:35 -080084 private @DisplayRotation.FixedToUserRotation int mFixedToUserRotation =
85 FIXED_TO_USER_ROTATION_DEFAULT;
Dianne Hackbornc652de82013-02-15 16:32:56 -080086
Chilun8753ad32018-10-09 15:56:45 +080087 private Entry(String name) {
88 mName = name;
Garfield Tan90c90052018-10-08 12:29:41 -070089 }
90
Riddle Hsuf53da812018-08-15 22:00:27 +080091 /** @return {@code true} if all values are default. */
Garfield Tan90c90052018-10-08 12:29:41 -070092 private boolean isEmpty() {
93 return mOverscanLeft == 0 && mOverscanTop == 0 && mOverscanRight == 0
94 && mOverscanBottom == 0
95 && mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
96 && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
Riddle Hsuf53da812018-08-15 22:00:27 +080097 && mUserRotation == Surface.ROTATION_0
98 && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
Chilun8753ad32018-10-09 15:56:45 +080099 && mForcedScalingMode == FORCE_SCALING_MODE_AUTO
100 && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
101 && !mShouldShowWithInsecureKeyguard
102 && !mShouldShowSystemDecors
Garfield Tanff362222018-11-14 17:52:32 -0800103 && !mShouldShowIme
Garfield Tan7fbca052019-02-19 10:45:35 -0800104 && mFixedToUserRotation == FIXED_TO_USER_ROTATION_DEFAULT;
Dianne Hackbornc652de82013-02-15 16:32:56 -0800105 }
106 }
107
Chilun8753ad32018-10-09 15:56:45 +0800108 DisplayWindowSettings(WindowManagerService service) {
Garfield Tane0846042018-07-26 13:42:04 -0700109 this(service, new File(Environment.getDataDirectory(), "system"));
Dianne Hackbornc652de82013-02-15 16:32:56 -0800110 }
111
Garfield Tane0846042018-07-26 13:42:04 -0700112 @VisibleForTesting
Chilun8753ad32018-10-09 15:56:45 +0800113 DisplayWindowSettings(WindowManagerService service, File folder) {
Garfield Tane0846042018-07-26 13:42:04 -0700114 mService = service;
115 mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
Riddle Hsuf53da812018-08-15 22:00:27 +0800116 readSettings();
Garfield Tane0846042018-07-26 13:42:04 -0700117 }
118
Riddle Hsuf53da812018-08-15 22:00:27 +0800119 private Entry getEntry(DisplayInfo displayInfo) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800120 // Try to get the entry with the unique if possible.
121 // Else, fall back on the display name.
122 Entry entry;
Riddle Hsuf53da812018-08-15 22:00:27 +0800123 if (displayInfo.uniqueId == null || (entry = mEntries.get(displayInfo.uniqueId)) == null) {
124 entry = mEntries.get(displayInfo.name);
Wale Ogunwale361ca212014-11-20 11:42:38 -0800125 }
Garfield Tane0846042018-07-26 13:42:04 -0700126 return entry;
127 }
128
Riddle Hsuf53da812018-08-15 22:00:27 +0800129 private Entry getOrCreateEntry(DisplayInfo displayInfo) {
130 final Entry entry = getEntry(displayInfo);
131 return entry != null ? entry : new Entry(displayInfo.uniqueId);
Garfield Tan90c90052018-10-08 12:29:41 -0700132 }
133
Riddle Hsuf53da812018-08-15 22:00:27 +0800134 void setOverscanLocked(DisplayInfo displayInfo, int left, int top, int right, int bottom) {
135 final Entry entry = getOrCreateEntry(displayInfo);
Garfield Tan90c90052018-10-08 12:29:41 -0700136 entry.mOverscanLeft = left;
137 entry.mOverscanTop = top;
138 entry.mOverscanRight = right;
139 entry.mOverscanBottom = bottom;
Riddle Hsuf53da812018-08-15 22:00:27 +0800140 writeSettingsIfNeeded(entry, displayInfo);
Dianne Hackbornc652de82013-02-15 16:32:56 -0800141 }
142
Riddle Hsuf53da812018-08-15 22:00:27 +0800143 void setUserRotation(DisplayContent displayContent, int rotationMode, int rotation) {
144 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
145 final Entry entry = getOrCreateEntry(displayInfo);
146 entry.mUserRotationMode = rotationMode;
147 entry.mUserRotation = rotation;
148 writeSettingsIfNeeded(entry, displayInfo);
149 }
150
151 void setForcedSize(DisplayContent displayContent, int width, int height) {
152 if (displayContent.isDefaultDisplay) {
153 final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
154 Settings.Global.putString(mService.mContext.getContentResolver(),
155 Settings.Global.DISPLAY_SIZE_FORCED, sizeString);
156 return;
157 }
158
159 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
160 final Entry entry = getOrCreateEntry(displayInfo);
161 entry.mForcedWidth = width;
162 entry.mForcedHeight = height;
163 writeSettingsIfNeeded(entry, displayInfo);
164 }
165
166 void setForcedDensity(DisplayContent displayContent, int density, int userId) {
167 if (displayContent.isDefaultDisplay) {
168 final String densityString = density == 0 ? "" : Integer.toString(density);
169 Settings.Secure.putStringForUser(mService.mContext.getContentResolver(),
170 Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId);
171 return;
172 }
173
174 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
175 final Entry entry = getOrCreateEntry(displayInfo);
176 entry.mForcedDensity = density;
177 writeSettingsIfNeeded(entry, displayInfo);
178 }
179
180 void setForcedScalingMode(DisplayContent displayContent, @ForceScalingMode int mode) {
181 if (displayContent.isDefaultDisplay) {
182 Settings.Global.putInt(mService.mContext.getContentResolver(),
183 Settings.Global.DISPLAY_SCALING_FORCE, mode);
184 return;
185 }
186
187 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
188 final Entry entry = getOrCreateEntry(displayInfo);
189 entry.mForcedScalingMode = mode;
190 writeSettingsIfNeeded(entry, displayInfo);
191 }
192
Garfield Tan7fbca052019-02-19 10:45:35 -0800193 void setFixedToUserRotation(DisplayContent displayContent,
194 @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
Garfield Tanff362222018-11-14 17:52:32 -0800195 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
196 final Entry entry = getOrCreateEntry(displayInfo);
197 entry.mFixedToUserRotation = fixedToUserRotation;
198 writeSettingsIfNeeded(entry, displayInfo);
199 }
200
Riddle Hsuf53da812018-08-15 22:00:27 +0800201 private int getWindowingModeLocked(Entry entry, int displayId) {
Garfield Tan90c90052018-10-08 12:29:41 -0700202 int windowingMode = entry != null ? entry.mWindowingMode
Garfield Tane0846042018-07-26 13:42:04 -0700203 : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
204 // This display used to be in freeform, but we don't support freeform anymore, so fall
205 // back to fullscreen.
206 if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
207 && !mService.mSupportsFreeformWindowManagement) {
208 return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
209 }
210 // No record is present so use default windowing mode policy.
211 if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
Andrii Kulian15cfb422018-11-07 13:38:49 -0800212 final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
213 && displayId != Display.DEFAULT_DISPLAY;
214 windowingMode = mService.mSupportsFreeformWindowManagement
215 && (mService.mIsPc || forceDesktopMode)
216 ? WindowConfiguration.WINDOWING_MODE_FREEFORM
217 : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Garfield Tane0846042018-07-26 13:42:04 -0700218 }
219 return windowingMode;
220 }
221
Chilun8753ad32018-10-09 15:56:45 +0800222 int getWindowingModeLocked(DisplayContent dc) {
223 final DisplayInfo displayInfo = dc.getDisplayInfo();
224 final Entry entry = getEntry(displayInfo);
225 return getWindowingModeLocked(entry, dc.getDisplayId());
226 }
227
228 void setWindowingModeLocked(DisplayContent dc, int mode) {
229 final DisplayInfo displayInfo = dc.getDisplayInfo();
230 final Entry entry = getOrCreateEntry(displayInfo);
231 entry.mWindowingMode = mode;
232 dc.setWindowingMode(mode);
233 writeSettingsIfNeeded(entry, displayInfo);
234 }
235
236 int getRemoveContentModeLocked(DisplayContent dc) {
237 final DisplayInfo displayInfo = dc.getDisplayInfo();
238 final Entry entry = getEntry(displayInfo);
239 if (entry == null || entry.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
240 if (dc.isPrivate()) {
241 // For private displays by default content is destroyed on removal.
242 return REMOVE_CONTENT_MODE_DESTROY;
243 }
244 // For other displays by default content is moved to primary on removal.
245 return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
246 }
247 return entry.mRemoveContentMode;
248 }
249
250 void setRemoveContentModeLocked(DisplayContent dc, int mode) {
251 final DisplayInfo displayInfo = dc.getDisplayInfo();
252 final Entry entry = getOrCreateEntry(displayInfo);
253 entry.mRemoveContentMode = mode;
254 writeSettingsIfNeeded(entry, displayInfo);
255 }
256
257 boolean shouldShowWithInsecureKeyguardLocked(DisplayContent dc) {
258 final DisplayInfo displayInfo = dc.getDisplayInfo();
259 final Entry entry = getEntry(displayInfo);
260 if (entry == null) {
261 return false;
262 }
263 return entry.mShouldShowWithInsecureKeyguard;
264 }
265
266 void setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow) {
267 if (!dc.isPrivate() && shouldShow) {
268 Slog.e(TAG, "Public display can't be allowed to show content when locked");
269 return;
270 }
271
272 final DisplayInfo displayInfo = dc.getDisplayInfo();
273 final Entry entry = getOrCreateEntry(displayInfo);
274 entry.mShouldShowWithInsecureKeyguard = shouldShow;
275 writeSettingsIfNeeded(entry, displayInfo);
276 }
277
278 boolean shouldShowSystemDecorsLocked(DisplayContent dc) {
279 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
280 // For default display should show system decors.
281 return true;
282 }
283
284 final DisplayInfo displayInfo = dc.getDisplayInfo();
285 final Entry entry = getEntry(displayInfo);
286 if (entry == null) {
287 return false;
288 }
289 return entry.mShouldShowSystemDecors;
290 }
291
292 void setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow) {
293 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
294 Slog.e(TAG, "Default display should show system decors");
295 return;
296 }
297
298 final DisplayInfo displayInfo = dc.getDisplayInfo();
299 final Entry entry = getOrCreateEntry(displayInfo);
300 entry.mShouldShowSystemDecors = shouldShow;
301 writeSettingsIfNeeded(entry, displayInfo);
302 }
303
304 boolean shouldShowImeLocked(DisplayContent dc) {
305 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
306 // For default display should shows IME.
307 return true;
308 }
309
310 final DisplayInfo displayInfo = dc.getDisplayInfo();
311 final Entry entry = getEntry(displayInfo);
312 if (entry == null) {
313 return false;
314 }
315 return entry.mShouldShowIme;
316 }
317
318 void setShouldShowImeLocked(DisplayContent dc, boolean shouldShow) {
319 if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
320 Slog.e(TAG, "Default display should show IME");
321 return;
322 }
323
324 final DisplayInfo displayInfo = dc.getDisplayInfo();
325 final Entry entry = getOrCreateEntry(displayInfo);
326 entry.mShouldShowIme = shouldShow;
327 writeSettingsIfNeeded(entry, displayInfo);
328 }
329
Riddle Hsuf53da812018-08-15 22:00:27 +0800330 void applySettingsToDisplayLocked(DisplayContent dc) {
Garfield Tan90c90052018-10-08 12:29:41 -0700331 final DisplayInfo displayInfo = dc.getDisplayInfo();
Tadashi G. Takaokafd911182018-12-20 18:19:57 +0900332 final Entry entry = getOrCreateEntry(displayInfo);
Garfield Tan90c90052018-10-08 12:29:41 -0700333
Riddle Hsuf53da812018-08-15 22:00:27 +0800334 // Setting windowing mode first, because it may override overscan values later.
335 dc.setWindowingMode(getWindowingModeLocked(entry, dc.getDisplayId()));
336
Riddle Hsuf53da812018-08-15 22:00:27 +0800337 displayInfo.overscanLeft = entry.mOverscanLeft;
338 displayInfo.overscanTop = entry.mOverscanTop;
339 displayInfo.overscanRight = entry.mOverscanRight;
340 displayInfo.overscanBottom = entry.mOverscanBottom;
341
Garfield Tanff362222018-11-14 17:52:32 -0800342 dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
343 entry.mUserRotation, entry.mFixedToUserRotation);
Riddle Hsuf53da812018-08-15 22:00:27 +0800344
345 if (entry.mForcedDensity != 0) {
346 dc.mBaseDisplayDensity = entry.mForcedDensity;
347 }
348 if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
349 dc.updateBaseDisplayMetrics(entry.mForcedWidth, entry.mForcedHeight,
350 dc.mBaseDisplayDensity);
351 }
352 dc.mDisplayScalingDisabled = entry.mForcedScalingMode == FORCE_SCALING_MODE_DISABLED;
Garfield Tan90c90052018-10-08 12:29:41 -0700353 }
354
Garfield Tanb5910b42019-03-14 14:50:59 -0700355 /**
356 * Updates settings for the given display after system features are loaded into window manager
357 * service, e.g. if this device is PC and if this device supports freeform.
358 *
359 * @param dc the given display.
360 * @return {@code true} if any settings for this display has changed; {@code false} if nothing
361 * changed.
362 */
363 boolean updateSettingsForDisplay(DisplayContent dc) {
364 if (dc.getWindowingMode() != getWindowingModeLocked(dc)) {
365 // For the time being the only thing that may change is windowing mode, so just update
366 // that.
367 dc.setWindowingMode(getWindowingModeLocked(dc));
368 return true;
369 }
370 return false;
371 }
372
Riddle Hsuf53da812018-08-15 22:00:27 +0800373 private void readSettings() {
Dianne Hackbornc652de82013-02-15 16:32:56 -0800374 FileInputStream stream;
375 try {
376 stream = mFile.openRead();
377 } catch (FileNotFoundException e) {
378 Slog.i(TAG, "No existing display settings " + mFile.getBaseFile()
379 + "; starting empty");
380 return;
381 }
382 boolean success = false;
383 try {
384 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100385 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackbornc652de82013-02-15 16:32:56 -0800386 int type;
387 while ((type = parser.next()) != XmlPullParser.START_TAG
388 && type != XmlPullParser.END_DOCUMENT) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800389 // Do nothing.
Dianne Hackbornc652de82013-02-15 16:32:56 -0800390 }
391
392 if (type != XmlPullParser.START_TAG) {
393 throw new IllegalStateException("no start tag found");
394 }
395
396 int outerDepth = parser.getDepth();
397 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
398 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
399 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
400 continue;
401 }
402
403 String tagName = parser.getName();
404 if (tagName.equals("display")) {
405 readDisplay(parser);
406 } else {
407 Slog.w(TAG, "Unknown element under <display-settings>: "
408 + parser.getName());
409 XmlUtils.skipCurrentTag(parser);
410 }
411 }
412 success = true;
413 } catch (IllegalStateException e) {
414 Slog.w(TAG, "Failed parsing " + e);
415 } catch (NullPointerException e) {
416 Slog.w(TAG, "Failed parsing " + e);
417 } catch (NumberFormatException e) {
418 Slog.w(TAG, "Failed parsing " + e);
419 } catch (XmlPullParserException e) {
420 Slog.w(TAG, "Failed parsing " + e);
421 } catch (IOException e) {
422 Slog.w(TAG, "Failed parsing " + e);
423 } catch (IndexOutOfBoundsException e) {
424 Slog.w(TAG, "Failed parsing " + e);
425 } finally {
426 if (!success) {
427 mEntries.clear();
428 }
429 try {
430 stream.close();
431 } catch (IOException e) {
432 }
433 }
434 }
435
436 private int getIntAttribute(XmlPullParser parser, String name) {
Garfield Tane0846042018-07-26 13:42:04 -0700437 return getIntAttribute(parser, name, 0 /* defaultValue */);
438 }
439
440 private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
Dianne Hackbornc652de82013-02-15 16:32:56 -0800441 try {
Chilun8753ad32018-10-09 15:56:45 +0800442 final String str = parser.getAttributeValue(null, name);
Garfield Tane0846042018-07-26 13:42:04 -0700443 return str != null ? Integer.parseInt(str) : defaultValue;
Dianne Hackbornc652de82013-02-15 16:32:56 -0800444 } catch (NumberFormatException e) {
Garfield Tane0846042018-07-26 13:42:04 -0700445 return defaultValue;
Dianne Hackbornc652de82013-02-15 16:32:56 -0800446 }
447 }
448
Chilun8753ad32018-10-09 15:56:45 +0800449 private boolean getBooleanAttribute(XmlPullParser parser, String name) {
450 return getBooleanAttribute(parser, name, false /* defaultValue */);
451 }
452
453 private boolean getBooleanAttribute(XmlPullParser parser, String name, boolean defaultValue) {
454 try {
455 final String str = parser.getAttributeValue(null, name);
456 return str != null ? Boolean.parseBoolean(str) : defaultValue;
457 } catch (NumberFormatException e) {
458 return defaultValue;
459 }
460 }
461
Dianne Hackbornc652de82013-02-15 16:32:56 -0800462 private void readDisplay(XmlPullParser parser) throws NumberFormatException,
463 XmlPullParserException, IOException {
464 String name = parser.getAttributeValue(null, "name");
465 if (name != null) {
466 Entry entry = new Entry(name);
Garfield Tan90c90052018-10-08 12:29:41 -0700467 entry.mOverscanLeft = getIntAttribute(parser, "overscanLeft");
468 entry.mOverscanTop = getIntAttribute(parser, "overscanTop");
469 entry.mOverscanRight = getIntAttribute(parser, "overscanRight");
470 entry.mOverscanBottom = getIntAttribute(parser, "overscanBottom");
471 entry.mWindowingMode = getIntAttribute(parser, "windowingMode",
Garfield Tane0846042018-07-26 13:42:04 -0700472 WindowConfiguration.WINDOWING_MODE_UNDEFINED);
Garfield Tan90c90052018-10-08 12:29:41 -0700473 entry.mUserRotationMode = getIntAttribute(parser, "userRotationMode",
474 WindowManagerPolicy.USER_ROTATION_FREE);
475 entry.mUserRotation = getIntAttribute(parser, "userRotation",
476 Surface.ROTATION_0);
Riddle Hsuf53da812018-08-15 22:00:27 +0800477 entry.mForcedWidth = getIntAttribute(parser, "forcedWidth");
478 entry.mForcedHeight = getIntAttribute(parser, "forcedHeight");
479 entry.mForcedDensity = getIntAttribute(parser, "forcedDensity");
480 entry.mForcedScalingMode = getIntAttribute(parser, "forcedScalingMode",
481 FORCE_SCALING_MODE_AUTO);
Chilun8753ad32018-10-09 15:56:45 +0800482 entry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode",
483 REMOVE_CONTENT_MODE_UNDEFINED);
484 entry.mShouldShowWithInsecureKeyguard = getBooleanAttribute(parser,
485 "shouldShowWithInsecureKeyguard");
486 entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
487 entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
Garfield Tan7fbca052019-02-19 10:45:35 -0800488 entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation");
Dianne Hackbornc652de82013-02-15 16:32:56 -0800489 mEntries.put(name, entry);
490 }
491 XmlUtils.skipCurrentTag(parser);
492 }
493
Riddle Hsuf53da812018-08-15 22:00:27 +0800494 private void writeSettingsIfNeeded(Entry changedEntry, DisplayInfo displayInfo) {
495 if (changedEntry.isEmpty()) {
496 boolean removed = mEntries.remove(displayInfo.uniqueId) != null;
497 // Legacy name might have been in used, so we need to clear it.
498 removed |= mEntries.remove(displayInfo.name) != null;
499 if (!removed) {
500 // The entry didn't exist so nothing is changed and no need to update the file.
501 return;
502 }
503 } else {
504 mEntries.put(displayInfo.uniqueId, changedEntry);
505 }
506
Dianne Hackbornc652de82013-02-15 16:32:56 -0800507 FileOutputStream stream;
508 try {
509 stream = mFile.startWrite();
510 } catch (IOException e) {
511 Slog.w(TAG, "Failed to write display settings: " + e);
512 return;
513 }
514
515 try {
516 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100517 out.setOutput(stream, StandardCharsets.UTF_8.name());
Dianne Hackbornc652de82013-02-15 16:32:56 -0800518 out.startDocument(null, true);
519 out.startTag(null, "display-settings");
520
521 for (Entry entry : mEntries.values()) {
522 out.startTag(null, "display");
Garfield Tan90c90052018-10-08 12:29:41 -0700523 out.attribute(null, "name", entry.mName);
524 if (entry.mOverscanLeft != 0) {
525 out.attribute(null, "overscanLeft", Integer.toString(entry.mOverscanLeft));
Dianne Hackbornc652de82013-02-15 16:32:56 -0800526 }
Garfield Tan90c90052018-10-08 12:29:41 -0700527 if (entry.mOverscanTop != 0) {
528 out.attribute(null, "overscanTop", Integer.toString(entry.mOverscanTop));
Dianne Hackbornc652de82013-02-15 16:32:56 -0800529 }
Garfield Tan90c90052018-10-08 12:29:41 -0700530 if (entry.mOverscanRight != 0) {
531 out.attribute(null, "overscanRight", Integer.toString(entry.mOverscanRight));
Dianne Hackbornc652de82013-02-15 16:32:56 -0800532 }
Garfield Tan90c90052018-10-08 12:29:41 -0700533 if (entry.mOverscanBottom != 0) {
534 out.attribute(null, "overscanBottom", Integer.toString(entry.mOverscanBottom));
Dianne Hackbornc652de82013-02-15 16:32:56 -0800535 }
Garfield Tan90c90052018-10-08 12:29:41 -0700536 if (entry.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
537 out.attribute(null, "windowingMode", Integer.toString(entry.mWindowingMode));
538 }
539 if (entry.mUserRotationMode != WindowManagerPolicy.USER_ROTATION_FREE) {
540 out.attribute(null, "userRotationMode",
541 Integer.toString(entry.mUserRotationMode));
542 }
543 if (entry.mUserRotation != Surface.ROTATION_0) {
544 out.attribute(null, "userRotation", Integer.toString(entry.mUserRotation));
Garfield Tane0846042018-07-26 13:42:04 -0700545 }
Riddle Hsuf53da812018-08-15 22:00:27 +0800546 if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
547 out.attribute(null, "forcedWidth", Integer.toString(entry.mForcedWidth));
548 out.attribute(null, "forcedHeight", Integer.toString(entry.mForcedHeight));
549 }
550 if (entry.mForcedDensity != 0) {
551 out.attribute(null, "forcedDensity", Integer.toString(entry.mForcedDensity));
552 }
553 if (entry.mForcedScalingMode != FORCE_SCALING_MODE_AUTO) {
554 out.attribute(null, "forcedScalingMode",
555 Integer.toString(entry.mForcedScalingMode));
556 }
Chilun8753ad32018-10-09 15:56:45 +0800557 if (entry.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED) {
558 out.attribute(null, "removeContentMode",
559 Integer.toString(entry.mRemoveContentMode));
560 }
561 if (entry.mShouldShowWithInsecureKeyguard) {
562 out.attribute(null, "shouldShowWithInsecureKeyguard",
563 Boolean.toString(entry.mShouldShowWithInsecureKeyguard));
564 }
565 if (entry.mShouldShowSystemDecors) {
566 out.attribute(null, "shouldShowSystemDecors",
567 Boolean.toString(entry.mShouldShowSystemDecors));
568 }
569 if (entry.mShouldShowIme) {
570 out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
571 }
Garfield Tan7fbca052019-02-19 10:45:35 -0800572 if (entry.mFixedToUserRotation != FIXED_TO_USER_ROTATION_DEFAULT) {
Garfield Tanff362222018-11-14 17:52:32 -0800573 out.attribute(null, "fixedToUserRotation",
Garfield Tan7fbca052019-02-19 10:45:35 -0800574 Integer.toString(entry.mFixedToUserRotation));
Garfield Tanff362222018-11-14 17:52:32 -0800575 }
Dianne Hackbornc652de82013-02-15 16:32:56 -0800576 out.endTag(null, "display");
577 }
578
579 out.endTag(null, "display-settings");
580 out.endDocument();
581 mFile.finishWrite(stream);
582 } catch (IOException e) {
583 Slog.w(TAG, "Failed to write display settings, restoring backup.", e);
584 mFile.failWrite(stream);
585 }
586 }
587}