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 android.graphics.Rect; 20 import android.os.Environment; 21 import android.util.AtomicFile; 22 import android.util.Slog; 23 import android.util.Xml; 24 import com.android.internal.util.FastXmlSerializer; 25 import com.android.internal.util.XmlUtils; 26 import org.xmlpull.v1.XmlPullParser; 27 import org.xmlpull.v1.XmlPullParserException; 28 import org.xmlpull.v1.XmlSerializer; 29 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileNotFoundException; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 import java.util.HashMap; 36 37 /** 38 * Current persistent settings about a display 39 */ 40 public class DisplaySettings { 41 private static final String TAG = WindowManagerService.TAG; 42 43 private final AtomicFile mFile; 44 private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>(); 45 46 public static class Entry { 47 public final String name; 48 public int overscanLeft; 49 public int overscanTop; 50 public int overscanRight; 51 public int overscanBottom; 52 Entry(String _name)53 public Entry(String _name) { 54 name = _name; 55 } 56 } 57 DisplaySettings()58 public DisplaySettings() { 59 File dataDir = Environment.getDataDirectory(); 60 File systemDir = new File(dataDir, "system"); 61 mFile = new AtomicFile(new File(systemDir, "display_settings.xml")); 62 } 63 getOverscanLocked(String name, String uniqueId, Rect outRect)64 public void getOverscanLocked(String name, String uniqueId, Rect outRect) { 65 // Try to get the entry with the unique if possible. 66 // Else, fall back on the display name. 67 Entry entry; 68 if (uniqueId == null || (entry = mEntries.get(uniqueId)) == null) { 69 entry = mEntries.get(name); 70 } 71 if (entry != null) { 72 outRect.left = entry.overscanLeft; 73 outRect.top = entry.overscanTop; 74 outRect.right = entry.overscanRight; 75 outRect.bottom = entry.overscanBottom; 76 } else { 77 outRect.set(0, 0, 0, 0); 78 } 79 } 80 setOverscanLocked(String name, int left, int top, int right, int bottom)81 public void setOverscanLocked(String name, int left, int top, int right, int bottom) { 82 if (left == 0 && top == 0 && right == 0 && bottom == 0) { 83 // Right now all we are storing is overscan; if there is no overscan, 84 // we have no need for the entry. 85 mEntries.remove(name); 86 return; 87 } 88 Entry entry = mEntries.get(name); 89 if (entry == null) { 90 entry = new Entry(name); 91 mEntries.put(name, entry); 92 } 93 entry.overscanLeft = left; 94 entry.overscanTop = top; 95 entry.overscanRight = right; 96 entry.overscanBottom = bottom; 97 } 98 readSettingsLocked()99 public void readSettingsLocked() { 100 FileInputStream stream; 101 try { 102 stream = mFile.openRead(); 103 } catch (FileNotFoundException e) { 104 Slog.i(TAG, "No existing display settings " + mFile.getBaseFile() 105 + "; starting empty"); 106 return; 107 } 108 boolean success = false; 109 try { 110 XmlPullParser parser = Xml.newPullParser(); 111 parser.setInput(stream, null); 112 int type; 113 while ((type = parser.next()) != XmlPullParser.START_TAG 114 && type != XmlPullParser.END_DOCUMENT) { 115 // Do nothing. 116 } 117 118 if (type != XmlPullParser.START_TAG) { 119 throw new IllegalStateException("no start tag found"); 120 } 121 122 int outerDepth = parser.getDepth(); 123 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 124 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 125 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 126 continue; 127 } 128 129 String tagName = parser.getName(); 130 if (tagName.equals("display")) { 131 readDisplay(parser); 132 } else { 133 Slog.w(TAG, "Unknown element under <display-settings>: " 134 + parser.getName()); 135 XmlUtils.skipCurrentTag(parser); 136 } 137 } 138 success = true; 139 } catch (IllegalStateException e) { 140 Slog.w(TAG, "Failed parsing " + e); 141 } catch (NullPointerException e) { 142 Slog.w(TAG, "Failed parsing " + e); 143 } catch (NumberFormatException e) { 144 Slog.w(TAG, "Failed parsing " + e); 145 } catch (XmlPullParserException e) { 146 Slog.w(TAG, "Failed parsing " + e); 147 } catch (IOException e) { 148 Slog.w(TAG, "Failed parsing " + e); 149 } catch (IndexOutOfBoundsException e) { 150 Slog.w(TAG, "Failed parsing " + e); 151 } finally { 152 if (!success) { 153 mEntries.clear(); 154 } 155 try { 156 stream.close(); 157 } catch (IOException e) { 158 } 159 } 160 } 161 getIntAttribute(XmlPullParser parser, String name)162 private int getIntAttribute(XmlPullParser parser, String name) { 163 try { 164 String str = parser.getAttributeValue(null, name); 165 return str != null ? Integer.parseInt(str) : 0; 166 } catch (NumberFormatException e) { 167 return 0; 168 } 169 } 170 readDisplay(XmlPullParser parser)171 private void readDisplay(XmlPullParser parser) throws NumberFormatException, 172 XmlPullParserException, IOException { 173 String name = parser.getAttributeValue(null, "name"); 174 if (name != null) { 175 Entry entry = new Entry(name); 176 entry.overscanLeft = getIntAttribute(parser, "overscanLeft"); 177 entry.overscanTop = getIntAttribute(parser, "overscanTop"); 178 entry.overscanRight = getIntAttribute(parser, "overscanRight"); 179 entry.overscanBottom = getIntAttribute(parser, "overscanBottom"); 180 mEntries.put(name, entry); 181 } 182 XmlUtils.skipCurrentTag(parser); 183 } 184 writeSettingsLocked()185 public void writeSettingsLocked() { 186 FileOutputStream stream; 187 try { 188 stream = mFile.startWrite(); 189 } catch (IOException e) { 190 Slog.w(TAG, "Failed to write display settings: " + e); 191 return; 192 } 193 194 try { 195 XmlSerializer out = new FastXmlSerializer(); 196 out.setOutput(stream, "utf-8"); 197 out.startDocument(null, true); 198 out.startTag(null, "display-settings"); 199 200 for (Entry entry : mEntries.values()) { 201 out.startTag(null, "display"); 202 out.attribute(null, "name", entry.name); 203 if (entry.overscanLeft != 0) { 204 out.attribute(null, "overscanLeft", Integer.toString(entry.overscanLeft)); 205 } 206 if (entry.overscanTop != 0) { 207 out.attribute(null, "overscanTop", Integer.toString(entry.overscanTop)); 208 } 209 if (entry.overscanRight != 0) { 210 out.attribute(null, "overscanRight", Integer.toString(entry.overscanRight)); 211 } 212 if (entry.overscanBottom != 0) { 213 out.attribute(null, "overscanBottom", Integer.toString(entry.overscanBottom)); 214 } 215 out.endTag(null, "display"); 216 } 217 218 out.endTag(null, "display-settings"); 219 out.endDocument(); 220 mFile.finishWrite(stream); 221 } catch (IOException e) { 222 Slog.w(TAG, "Failed to write display settings, restoring backup.", e); 223 mFile.failWrite(stream); 224 } 225 } 226 } 227