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.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 
     55         public Entry(String _name) {
     56             name = _name;
     57         }
     58     }
     59 
     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 
     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 
     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 
     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 
    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 
    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 
    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