Home | History | Annotate | Download | only in wm
      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 
     53         public Entry(String _name) {
     54             name = _name;
     55         }
     56     }
     57 
     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 
     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 
     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 
     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 
    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 
    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 
    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