/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;

import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.os.Environment;
import android.os.FileUtils;
import android.provider.Settings;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.DisplayInfo;
import android.view.Surface;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.DisplayContent.ForceScalingMode;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

/**
 * Current persistent settings about a display
 */
class DisplayWindowSettings {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM;

    private static final String SYSTEM_DIRECTORY = "system";
    private static final String DISPLAY_SETTINGS_FILE_NAME = "display_settings.xml";
    private static final String VENDOR_DISPLAY_SETTINGS_PATH = "etc/" + DISPLAY_SETTINGS_FILE_NAME;
    private static final String WM_DISPLAY_COMMIT_TAG = "wm-displays";

    private static final int IDENTIFIER_UNIQUE_ID = 0;
    private static final int IDENTIFIER_PORT = 1;
    @IntDef(prefix = { "IDENTIFIER_" }, value = {
            IDENTIFIER_UNIQUE_ID,
            IDENTIFIER_PORT,
    })
    @interface DisplayIdentifierType {}

    private final WindowManagerService mService;
    private final HashMap<String, Entry> mEntries = new HashMap<>();
    private final SettingPersister mStorage;

    /**
     * The preferred type of a display identifier to use when storing and retrieving entries.
     * {@link #getIdentifier(DisplayInfo)} must be used to get current preferred identifier for each
     * display. It will fall back to using {@link #IDENTIFIER_UNIQUE_ID} if the currently selected
     * one is not applicable to a particular display.
     */
    @DisplayIdentifierType
    private int mIdentifier = IDENTIFIER_UNIQUE_ID;

    /** Interface for persisting the display window settings. */
    interface SettingPersister {
        InputStream openRead() throws IOException;
        OutputStream startWrite() throws IOException;
        void finishWrite(OutputStream os, boolean success);
    }

    private static class Entry {
        private final String mName;
        private int mOverscanLeft;
        private int mOverscanTop;
        private int mOverscanRight;
        private int mOverscanBottom;
        private int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
        private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
        private int mUserRotation = Surface.ROTATION_0;
        private int mForcedWidth;
        private int mForcedHeight;
        private int mForcedDensity;
        private int mForcedScalingMode = FORCE_SCALING_MODE_AUTO;
        private int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
        private boolean mShouldShowWithInsecureKeyguard = false;
        private boolean mShouldShowSystemDecors = false;
        private boolean mShouldShowIme = false;
        private @DisplayRotation.FixedToUserRotation int mFixedToUserRotation =
                FIXED_TO_USER_ROTATION_DEFAULT;

        private Entry(String name) {
            mName = name;
        }

        private Entry(String name, Entry copyFrom) {
            this(name);
            mOverscanLeft = copyFrom.mOverscanLeft;
            mOverscanTop = copyFrom.mOverscanTop;
            mOverscanRight = copyFrom.mOverscanRight;
            mOverscanBottom = copyFrom.mOverscanBottom;
            mWindowingMode = copyFrom.mWindowingMode;
            mUserRotationMode = copyFrom.mUserRotationMode;
            mUserRotation = copyFrom.mUserRotation;
            mForcedWidth = copyFrom.mForcedWidth;
            mForcedHeight = copyFrom.mForcedHeight;
            mForcedDensity = copyFrom.mForcedDensity;
            mForcedScalingMode = copyFrom.mForcedScalingMode;
            mRemoveContentMode = copyFrom.mRemoveContentMode;
            mShouldShowWithInsecureKeyguard = copyFrom.mShouldShowWithInsecureKeyguard;
            mShouldShowSystemDecors = copyFrom.mShouldShowSystemDecors;
            mShouldShowIme = copyFrom.mShouldShowIme;
            mFixedToUserRotation = copyFrom.mFixedToUserRotation;
        }

        /** @return {@code true} if all values are default. */
        private boolean isEmpty() {
            return mOverscanLeft == 0 && mOverscanTop == 0 && mOverscanRight == 0
                    && mOverscanBottom == 0
                    && mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
                    && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
                    && mUserRotation == Surface.ROTATION_0
                    && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
                    && mForcedScalingMode == FORCE_SCALING_MODE_AUTO
                    && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
                    && !mShouldShowWithInsecureKeyguard
                    && !mShouldShowSystemDecors
                    && !mShouldShowIme
                    && mFixedToUserRotation == FIXED_TO_USER_ROTATION_DEFAULT;
        }
    }

    DisplayWindowSettings(WindowManagerService service) {
        this(service, new AtomicFileStorage());
    }

    @VisibleForTesting
    DisplayWindowSettings(WindowManagerService service, SettingPersister storageImpl) {
        mService = service;
        mStorage = storageImpl;
        readSettings();
    }

    private @Nullable Entry getEntry(DisplayInfo displayInfo) {
        final String identifier = getIdentifier(displayInfo);
        Entry entry;
        // Try to get corresponding entry using preferred identifier for the current config.
        if ((entry = mEntries.get(identifier)) != null) {
            return entry;
        }
        // Else, fall back to the display name.
        if ((entry = mEntries.get(displayInfo.name)) != null) {
            // Found an entry stored with old identifier - upgrade to the new type now.
            return updateIdentifierForEntry(entry, displayInfo);
        }
        return null;
    }

    private Entry getOrCreateEntry(DisplayInfo displayInfo) {
        final Entry entry = getEntry(displayInfo);
        return entry != null ? entry : new Entry(getIdentifier(displayInfo));
    }

    /**
     * Upgrades the identifier of a legacy entry. Does it by copying the data from the old record
     * and clearing the old key in memory. The entry will be written to storage next time when a
     * setting changes.
     */
    private Entry updateIdentifierForEntry(Entry entry, DisplayInfo displayInfo) {
        final Entry newEntry = new Entry(getIdentifier(displayInfo), entry);
        removeEntry(displayInfo);
        mEntries.put(newEntry.mName, newEntry);
        return newEntry;
    }

    void setOverscanLocked(DisplayInfo displayInfo, int left, int top, int right, int bottom) {
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mOverscanLeft = left;
        entry.mOverscanTop = top;
        entry.mOverscanRight = right;
        entry.mOverscanBottom = bottom;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    void setUserRotation(DisplayContent displayContent, int rotationMode, int rotation) {
        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mUserRotationMode = rotationMode;
        entry.mUserRotation = rotation;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    void setForcedSize(DisplayContent displayContent, int width, int height) {
        if (displayContent.isDefaultDisplay) {
            final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
            Settings.Global.putString(mService.mContext.getContentResolver(),
                    Settings.Global.DISPLAY_SIZE_FORCED, sizeString);
            return;
        }

        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mForcedWidth = width;
        entry.mForcedHeight = height;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    void setForcedDensity(DisplayContent displayContent, int density, int userId) {
        if (displayContent.isDefaultDisplay) {
            final String densityString = density == 0 ? "" : Integer.toString(density);
            Settings.Secure.putStringForUser(mService.mContext.getContentResolver(),
                    Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId);
            return;
        }

        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mForcedDensity = density;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    void setForcedScalingMode(DisplayContent displayContent, @ForceScalingMode int mode) {
        if (displayContent.isDefaultDisplay) {
            Settings.Global.putInt(mService.mContext.getContentResolver(),
                    Settings.Global.DISPLAY_SCALING_FORCE, mode);
            return;
        }

        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mForcedScalingMode = mode;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    void setFixedToUserRotation(DisplayContent displayContent,
            @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mFixedToUserRotation = fixedToUserRotation;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    private int getWindowingModeLocked(Entry entry, int displayId) {
        int windowingMode = entry != null ? entry.mWindowingMode
                : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
        // This display used to be in freeform, but we don't support freeform anymore, so fall
        // back to fullscreen.
        if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
                && !mService.mSupportsFreeformWindowManagement) {
            return WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
        }
        // No record is present so use default windowing mode policy.
        if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
            final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
                    && displayId != Display.DEFAULT_DISPLAY;
            windowingMode = mService.mSupportsFreeformWindowManagement
                    && (mService.mIsPc || forceDesktopMode)
                    ? WindowConfiguration.WINDOWING_MODE_FREEFORM
                    : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
        }
        return windowingMode;
    }

    int getWindowingModeLocked(DisplayContent dc) {
        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getEntry(displayInfo);
        return getWindowingModeLocked(entry, dc.getDisplayId());
    }

    void setWindowingModeLocked(DisplayContent dc, int mode) {
        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mWindowingMode = mode;
        dc.setWindowingMode(mode);
        writeSettingsIfNeeded(entry, displayInfo);
    }

    int getRemoveContentModeLocked(DisplayContent dc) {
        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getEntry(displayInfo);
        if (entry == null || entry.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
            if (dc.isPrivate()) {
                // For private displays by default content is destroyed on removal.
                return REMOVE_CONTENT_MODE_DESTROY;
            }
            // For other displays by default content is moved to primary on removal.
            return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
        }
        return entry.mRemoveContentMode;
    }

    void setRemoveContentModeLocked(DisplayContent dc, int mode) {
        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mRemoveContentMode = mode;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    boolean shouldShowWithInsecureKeyguardLocked(DisplayContent dc) {
        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getEntry(displayInfo);
        if (entry == null) {
            return false;
        }
        return entry.mShouldShowWithInsecureKeyguard;
    }

    void setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow) {
        if (!dc.isPrivate() && shouldShow) {
            Slog.e(TAG, "Public display can't be allowed to show content when locked");
            return;
        }

        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mShouldShowWithInsecureKeyguard = shouldShow;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    boolean shouldShowSystemDecorsLocked(DisplayContent dc) {
        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
            // For default display should show system decors.
            return true;
        }

        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getEntry(displayInfo);
        if (entry == null) {
            return false;
        }
        return entry.mShouldShowSystemDecors;
    }

    void setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow) {
        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
            Slog.e(TAG, "Default display should show system decors");
            return;
        }

        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mShouldShowSystemDecors = shouldShow;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    boolean shouldShowImeLocked(DisplayContent dc) {
        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
            // For default display should shows IME.
            return true;
        }

        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getEntry(displayInfo);
        if (entry == null) {
            return false;
        }
        return entry.mShouldShowIme;
    }

    void setShouldShowImeLocked(DisplayContent dc, boolean shouldShow) {
        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
            Slog.e(TAG, "Default display should show IME");
            return;
        }

        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);
        entry.mShouldShowIme = shouldShow;
        writeSettingsIfNeeded(entry, displayInfo);
    }

    void applySettingsToDisplayLocked(DisplayContent dc) {
        final DisplayInfo displayInfo = dc.getDisplayInfo();
        final Entry entry = getOrCreateEntry(displayInfo);

        // Setting windowing mode first, because it may override overscan values later.
        dc.setWindowingMode(getWindowingModeLocked(entry, dc.getDisplayId()));

        displayInfo.overscanLeft = entry.mOverscanLeft;
        displayInfo.overscanTop = entry.mOverscanTop;
        displayInfo.overscanRight = entry.mOverscanRight;
        displayInfo.overscanBottom = entry.mOverscanBottom;

        dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
                entry.mUserRotation, entry.mFixedToUserRotation);

        if (entry.mForcedDensity != 0) {
            dc.mBaseDisplayDensity = entry.mForcedDensity;
        }
        if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
            dc.updateBaseDisplayMetrics(entry.mForcedWidth, entry.mForcedHeight,
                    dc.mBaseDisplayDensity);
        }
        dc.mDisplayScalingDisabled = entry.mForcedScalingMode == FORCE_SCALING_MODE_DISABLED;
    }

    /**
     * Updates settings for the given display after system features are loaded into window manager
     * service, e.g. if this device is PC and if this device supports freeform.
     *
     * @param dc the given display.
     * @return {@code true} if any settings for this display has changed; {@code false} if nothing
     * changed.
     */
    boolean updateSettingsForDisplay(DisplayContent dc) {
        if (dc.getWindowingMode() != getWindowingModeLocked(dc)) {
            // For the time being the only thing that may change is windowing mode, so just update
            // that.
            dc.setWindowingMode(getWindowingModeLocked(dc));
            return true;
        }
        return false;
    }

    private void readSettings() {
        InputStream stream;
        try {
            stream = mStorage.openRead();
        } catch (IOException e) {
            Slog.i(TAG, "No existing display settings, starting empty");
            return;
        }
        boolean success = false;
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(stream, StandardCharsets.UTF_8.name());
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG
                    && type != XmlPullParser.END_DOCUMENT) {
                // Do nothing.
            }

            if (type != XmlPullParser.START_TAG) {
                throw new IllegalStateException("no start tag found");
            }

            int outerDepth = parser.getDepth();
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }

                String tagName = parser.getName();
                if (tagName.equals("display")) {
                    readDisplay(parser);
                } else if (tagName.equals("config")) {
                    readConfig(parser);
                } else {
                    Slog.w(TAG, "Unknown element under <display-settings>: "
                            + parser.getName());
                    XmlUtils.skipCurrentTag(parser);
                }
            }
            success = true;
        } catch (IllegalStateException e) {
            Slog.w(TAG, "Failed parsing " + e);
        } catch (NullPointerException e) {
            Slog.w(TAG, "Failed parsing " + e);
        } catch (NumberFormatException e) {
            Slog.w(TAG, "Failed parsing " + e);
        } catch (XmlPullParserException e) {
            Slog.w(TAG, "Failed parsing " + e);
        } catch (IOException e) {
            Slog.w(TAG, "Failed parsing " + e);
        } catch (IndexOutOfBoundsException e) {
            Slog.w(TAG, "Failed parsing " + e);
        } finally {
            if (!success) {
                mEntries.clear();
            }
            try {
                stream.close();
            } catch (IOException e) {
            }
        }
    }

    private int getIntAttribute(XmlPullParser parser, String name) {
        return getIntAttribute(parser, name, 0 /* defaultValue */);
    }

    private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
        try {
            final String str = parser.getAttributeValue(null, name);
            return str != null ? Integer.parseInt(str) : defaultValue;
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    private boolean getBooleanAttribute(XmlPullParser parser, String name) {
        return getBooleanAttribute(parser, name, false /* defaultValue */);
    }

    private boolean getBooleanAttribute(XmlPullParser parser, String name, boolean defaultValue) {
        try {
            final String str = parser.getAttributeValue(null, name);
            return str != null ? Boolean.parseBoolean(str) : defaultValue;
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    private void readDisplay(XmlPullParser parser) throws NumberFormatException,
            XmlPullParserException, IOException {
        String name = parser.getAttributeValue(null, "name");
        if (name != null) {
            Entry entry = new Entry(name);
            entry.mOverscanLeft = getIntAttribute(parser, "overscanLeft");
            entry.mOverscanTop = getIntAttribute(parser, "overscanTop");
            entry.mOverscanRight = getIntAttribute(parser, "overscanRight");
            entry.mOverscanBottom = getIntAttribute(parser, "overscanBottom");
            entry.mWindowingMode = getIntAttribute(parser, "windowingMode",
                    WindowConfiguration.WINDOWING_MODE_UNDEFINED);
            entry.mUserRotationMode = getIntAttribute(parser, "userRotationMode",
                    WindowManagerPolicy.USER_ROTATION_FREE);
            entry.mUserRotation = getIntAttribute(parser, "userRotation",
                    Surface.ROTATION_0);
            entry.mForcedWidth = getIntAttribute(parser, "forcedWidth");
            entry.mForcedHeight = getIntAttribute(parser, "forcedHeight");
            entry.mForcedDensity = getIntAttribute(parser, "forcedDensity");
            entry.mForcedScalingMode = getIntAttribute(parser, "forcedScalingMode",
                    FORCE_SCALING_MODE_AUTO);
            entry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode",
                    REMOVE_CONTENT_MODE_UNDEFINED);
            entry.mShouldShowWithInsecureKeyguard = getBooleanAttribute(parser,
                    "shouldShowWithInsecureKeyguard");
            entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
            entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
            entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation");
            mEntries.put(name, entry);
        }
        XmlUtils.skipCurrentTag(parser);
    }

    private void readConfig(XmlPullParser parser) throws NumberFormatException,
            XmlPullParserException, IOException {
        mIdentifier = getIntAttribute(parser, "identifier");
        XmlUtils.skipCurrentTag(parser);
    }

    private void writeSettingsIfNeeded(Entry changedEntry, DisplayInfo displayInfo) {
        if (changedEntry.isEmpty() && !removeEntry(displayInfo)) {
            // The entry didn't exist so nothing is changed and no need to update the file.
            return;
        }

        mEntries.put(getIdentifier(displayInfo), changedEntry);
        writeSettings();
    }

    private void writeSettings() {
        OutputStream stream;
        try {
            stream = mStorage.startWrite();
        } catch (IOException e) {
            Slog.w(TAG, "Failed to write display settings: " + e);
            return;
        }

        try {
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(stream, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);

            out.startTag(null, "display-settings");

            out.startTag(null, "config");
            out.attribute(null, "identifier", Integer.toString(mIdentifier));
            out.endTag(null, "config");

            for (Entry entry : mEntries.values()) {
                out.startTag(null, "display");
                out.attribute(null, "name", entry.mName);
                if (entry.mOverscanLeft != 0) {
                    out.attribute(null, "overscanLeft", Integer.toString(entry.mOverscanLeft));
                }
                if (entry.mOverscanTop != 0) {
                    out.attribute(null, "overscanTop", Integer.toString(entry.mOverscanTop));
                }
                if (entry.mOverscanRight != 0) {
                    out.attribute(null, "overscanRight", Integer.toString(entry.mOverscanRight));
                }
                if (entry.mOverscanBottom != 0) {
                    out.attribute(null, "overscanBottom", Integer.toString(entry.mOverscanBottom));
                }
                if (entry.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
                    out.attribute(null, "windowingMode", Integer.toString(entry.mWindowingMode));
                }
                if (entry.mUserRotationMode != WindowManagerPolicy.USER_ROTATION_FREE) {
                    out.attribute(null, "userRotationMode",
                            Integer.toString(entry.mUserRotationMode));
                }
                if (entry.mUserRotation != Surface.ROTATION_0) {
                    out.attribute(null, "userRotation", Integer.toString(entry.mUserRotation));
                }
                if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
                    out.attribute(null, "forcedWidth", Integer.toString(entry.mForcedWidth));
                    out.attribute(null, "forcedHeight", Integer.toString(entry.mForcedHeight));
                }
                if (entry.mForcedDensity != 0) {
                    out.attribute(null, "forcedDensity", Integer.toString(entry.mForcedDensity));
                }
                if (entry.mForcedScalingMode != FORCE_SCALING_MODE_AUTO) {
                    out.attribute(null, "forcedScalingMode",
                            Integer.toString(entry.mForcedScalingMode));
                }
                if (entry.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED) {
                    out.attribute(null, "removeContentMode",
                            Integer.toString(entry.mRemoveContentMode));
                }
                if (entry.mShouldShowWithInsecureKeyguard) {
                    out.attribute(null, "shouldShowWithInsecureKeyguard",
                            Boolean.toString(entry.mShouldShowWithInsecureKeyguard));
                }
                if (entry.mShouldShowSystemDecors) {
                    out.attribute(null, "shouldShowSystemDecors",
                            Boolean.toString(entry.mShouldShowSystemDecors));
                }
                if (entry.mShouldShowIme) {
                    out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
                }
                if (entry.mFixedToUserRotation != FIXED_TO_USER_ROTATION_DEFAULT) {
                    out.attribute(null, "fixedToUserRotation",
                            Integer.toString(entry.mFixedToUserRotation));
                }
                out.endTag(null, "display");
            }

            out.endTag(null, "display-settings");
            out.endDocument();
            mStorage.finishWrite(stream, true /* success */);
        } catch (IOException e) {
            Slog.w(TAG, "Failed to write display window settings.", e);
            mStorage.finishWrite(stream, false /* success */);
        }
    }

    /**
     * Removes an entry from {@link #mEntries} cache. Looks up by new and previously used
     * identifiers.
     */
    private boolean removeEntry(DisplayInfo displayInfo) {
        // Remove entry based on primary identifier.
        boolean removed = mEntries.remove(getIdentifier(displayInfo)) != null;
        // Ensure that legacy entries are cleared as well.
        removed |= mEntries.remove(displayInfo.uniqueId) != null;
        removed |= mEntries.remove(displayInfo.name) != null;
        return removed;
    }

    /** Gets the identifier of choice for the current config. */
    private String getIdentifier(DisplayInfo displayInfo) {
        if (mIdentifier == IDENTIFIER_PORT && displayInfo.address != null) {
            // Config suggests using port as identifier for physical displays.
            if (displayInfo.address instanceof DisplayAddress.Physical) {
                return "port:" + ((DisplayAddress.Physical) displayInfo.address).getPort();
            }
        }
        return displayInfo.uniqueId;
    }

    private static class AtomicFileStorage implements SettingPersister {
        private final AtomicFile mAtomicFile;

        AtomicFileStorage() {
            final File folder = new File(Environment.getDataDirectory(), SYSTEM_DIRECTORY);
            final File settingsFile = new File(folder, DISPLAY_SETTINGS_FILE_NAME);
            // If display_settings.xml doesn't exist, try to copy the vendor's one instead
            // in order to provide the vendor specific initialization.
            if (!settingsFile.exists()) {
                copyVendorSettings(settingsFile);
            }
            mAtomicFile = new AtomicFile(settingsFile, WM_DISPLAY_COMMIT_TAG);
        }

        private static void copyVendorSettings(File target) {
            final File vendorFile = new File(Environment.getVendorDirectory(),
                    VENDOR_DISPLAY_SETTINGS_PATH);
            if (vendorFile.canRead()) {
                try {
                    FileUtils.copy(vendorFile, target);
                } catch (IOException e) {
                    Slog.e(TAG, "Failed to copy vendor display_settings.xml");
                }
            }
        }

        @Override
        public InputStream openRead() throws FileNotFoundException {
            return mAtomicFile.openRead();
        }

        @Override
        public OutputStream startWrite() throws IOException {
            return mAtomicFile.startWrite();
        }

        @Override
        public void finishWrite(OutputStream os, boolean success) {
            if (!(os instanceof FileOutputStream)) {
                throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os);
            }
            FileOutputStream fos = (FileOutputStream) os;
            if (success) {
                mAtomicFile.finishWrite(fos);
            } else {
                mAtomicFile.failWrite(fos);
            }
        }
    }
}
