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