blob: 7f7968610151af14c107523b1fa6b4a103a17a56 [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
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080019import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
20import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
21
Dianne Hackbornc652de82013-02-15 16:32:56 -080022import android.graphics.Rect;
23import android.os.Environment;
24import android.util.AtomicFile;
25import android.util.Slog;
26import android.util.Xml;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080027
Dianne Hackbornc652de82013-02-15 16:32:56 -080028import com.android.internal.util.FastXmlSerializer;
29import com.android.internal.util.XmlUtils;
Dianne Hackbornc652de82013-02-15 16:32:56 -080030
31import java.io.File;
32import java.io.FileInputStream;
33import java.io.FileNotFoundException;
34import java.io.FileOutputStream;
35import java.io.IOException;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010036import java.nio.charset.StandardCharsets;
Dianne Hackbornc652de82013-02-15 16:32:56 -080037import java.util.HashMap;
38
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080039import org.xmlpull.v1.XmlPullParser;
40import org.xmlpull.v1.XmlPullParserException;
41import org.xmlpull.v1.XmlSerializer;
42
Dianne Hackbornc652de82013-02-15 16:32:56 -080043/**
44 * Current persistent settings about a display
45 */
46public class DisplaySettings {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080047 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplaySettings" : TAG_WM;
Dianne Hackbornc652de82013-02-15 16:32:56 -080048
Dianne Hackbornc652de82013-02-15 16:32:56 -080049 private final AtomicFile mFile;
50 private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>();
51
52 public static class Entry {
53 public final String name;
54 public int overscanLeft;
55 public int overscanTop;
56 public int overscanRight;
57 public int overscanBottom;
58
59 public Entry(String _name) {
60 name = _name;
61 }
62 }
63
Wale Ogunwale361ca212014-11-20 11:42:38 -080064 public DisplaySettings() {
Dianne Hackbornc652de82013-02-15 16:32:56 -080065 File dataDir = Environment.getDataDirectory();
66 File systemDir = new File(dataDir, "system");
67 mFile = new AtomicFile(new File(systemDir, "display_settings.xml"));
68 }
69
Wale Ogunwale361ca212014-11-20 11:42:38 -080070 public void getOverscanLocked(String name, String uniqueId, Rect outRect) {
71 // Try to get the entry with the unique if possible.
72 // Else, fall back on the display name.
73 Entry entry;
74 if (uniqueId == null || (entry = mEntries.get(uniqueId)) == null) {
75 entry = mEntries.get(name);
76 }
Dianne Hackbornc652de82013-02-15 16:32:56 -080077 if (entry != null) {
78 outRect.left = entry.overscanLeft;
79 outRect.top = entry.overscanTop;
80 outRect.right = entry.overscanRight;
81 outRect.bottom = entry.overscanBottom;
82 } else {
83 outRect.set(0, 0, 0, 0);
84 }
85 }
86
Filip Gruszczynski0a012ba2015-07-13 15:00:11 -070087 public void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
88 int bottom) {
Dianne Hackbornc652de82013-02-15 16:32:56 -080089 if (left == 0 && top == 0 && right == 0 && bottom == 0) {
90 // Right now all we are storing is overscan; if there is no overscan,
91 // we have no need for the entry.
Filip Gruszczynski0a012ba2015-07-13 15:00:11 -070092 mEntries.remove(uniqueId);
93 // Legacy name might have been in used, so we need to clear it.
Dianne Hackbornc652de82013-02-15 16:32:56 -080094 mEntries.remove(name);
95 return;
96 }
Filip Gruszczynski0a012ba2015-07-13 15:00:11 -070097 Entry entry = mEntries.get(uniqueId);
Dianne Hackbornc652de82013-02-15 16:32:56 -080098 if (entry == null) {
Filip Gruszczynski0a012ba2015-07-13 15:00:11 -070099 entry = new Entry(uniqueId);
100 mEntries.put(uniqueId, entry);
Dianne Hackbornc652de82013-02-15 16:32:56 -0800101 }
102 entry.overscanLeft = left;
103 entry.overscanTop = top;
104 entry.overscanRight = right;
105 entry.overscanBottom = bottom;
106 }
107
108 public void readSettingsLocked() {
109 FileInputStream stream;
110 try {
111 stream = mFile.openRead();
112 } catch (FileNotFoundException e) {
113 Slog.i(TAG, "No existing display settings " + mFile.getBaseFile()
114 + "; starting empty");
115 return;
116 }
117 boolean success = false;
118 try {
119 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100120 parser.setInput(stream, StandardCharsets.UTF_8.name());
Dianne Hackbornc652de82013-02-15 16:32:56 -0800121 int type;
122 while ((type = parser.next()) != XmlPullParser.START_TAG
123 && type != XmlPullParser.END_DOCUMENT) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800124 // Do nothing.
Dianne Hackbornc652de82013-02-15 16:32:56 -0800125 }
126
127 if (type != XmlPullParser.START_TAG) {
128 throw new IllegalStateException("no start tag found");
129 }
130
131 int outerDepth = parser.getDepth();
132 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
133 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
134 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
135 continue;
136 }
137
138 String tagName = parser.getName();
139 if (tagName.equals("display")) {
140 readDisplay(parser);
141 } else {
142 Slog.w(TAG, "Unknown element under <display-settings>: "
143 + parser.getName());
144 XmlUtils.skipCurrentTag(parser);
145 }
146 }
147 success = true;
148 } catch (IllegalStateException e) {
149 Slog.w(TAG, "Failed parsing " + e);
150 } catch (NullPointerException e) {
151 Slog.w(TAG, "Failed parsing " + e);
152 } catch (NumberFormatException e) {
153 Slog.w(TAG, "Failed parsing " + e);
154 } catch (XmlPullParserException e) {
155 Slog.w(TAG, "Failed parsing " + e);
156 } catch (IOException e) {
157 Slog.w(TAG, "Failed parsing " + e);
158 } catch (IndexOutOfBoundsException e) {
159 Slog.w(TAG, "Failed parsing " + e);
160 } finally {
161 if (!success) {
162 mEntries.clear();
163 }
164 try {
165 stream.close();
166 } catch (IOException e) {
167 }
168 }
169 }
170
171 private int getIntAttribute(XmlPullParser parser, String name) {
172 try {
173 String str = parser.getAttributeValue(null, name);
174 return str != null ? Integer.parseInt(str) : 0;
175 } catch (NumberFormatException e) {
176 return 0;
177 }
178 }
179
180 private void readDisplay(XmlPullParser parser) throws NumberFormatException,
181 XmlPullParserException, IOException {
182 String name = parser.getAttributeValue(null, "name");
183 if (name != null) {
184 Entry entry = new Entry(name);
185 entry.overscanLeft = getIntAttribute(parser, "overscanLeft");
186 entry.overscanTop = getIntAttribute(parser, "overscanTop");
187 entry.overscanRight = getIntAttribute(parser, "overscanRight");
188 entry.overscanBottom = getIntAttribute(parser, "overscanBottom");
189 mEntries.put(name, entry);
190 }
191 XmlUtils.skipCurrentTag(parser);
192 }
193
194 public void writeSettingsLocked() {
195 FileOutputStream stream;
196 try {
197 stream = mFile.startWrite();
198 } catch (IOException e) {
199 Slog.w(TAG, "Failed to write display settings: " + e);
200 return;
201 }
202
203 try {
204 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100205 out.setOutput(stream, StandardCharsets.UTF_8.name());
Dianne Hackbornc652de82013-02-15 16:32:56 -0800206 out.startDocument(null, true);
207 out.startTag(null, "display-settings");
208
209 for (Entry entry : mEntries.values()) {
210 out.startTag(null, "display");
211 out.attribute(null, "name", entry.name);
212 if (entry.overscanLeft != 0) {
213 out.attribute(null, "overscanLeft", Integer.toString(entry.overscanLeft));
214 }
215 if (entry.overscanTop != 0) {
216 out.attribute(null, "overscanTop", Integer.toString(entry.overscanTop));
217 }
218 if (entry.overscanRight != 0) {
219 out.attribute(null, "overscanRight", Integer.toString(entry.overscanRight));
220 }
221 if (entry.overscanBottom != 0) {
222 out.attribute(null, "overscanBottom", Integer.toString(entry.overscanBottom));
223 }
224 out.endTag(null, "display");
225 }
226
227 out.endTag(null, "display-settings");
228 out.endDocument();
229 mFile.finishWrite(stream);
230 } catch (IOException e) {
231 Slog.w(TAG, "Failed to write display settings, restoring backup.", e);
232 mFile.failWrite(stream);
233 }
234 }
235}