/*
 * Copyright (C) 2019 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.display;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;

import com.android.internal.R;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;

/**
 * The DisplayModeDirector is responsible for determining what modes are allowed to be
 * automatically picked by the system based on system-wide and display-specific configuration.
 */
public class DisplayModeDirector {
    private static final String TAG = "DisplayModeDirector";
    private static final boolean DEBUG = false;

    private static final int MSG_ALLOWED_MODES_CHANGED = 1;

    // Special ID used to indicate that given vote is to be applied globally, rather than to a
    // specific display.
    private static final int GLOBAL_ID = -1;

    // The tolerance within which we consider something approximately equals.
    private static final float EPSILON = 0.001f;

    private final Object mLock = new Object();
    private final Context mContext;

    private final DisplayModeDirectorHandler mHandler;

    // A map from the display ID to the collection of votes and their priority. The latter takes
    // the form of another map from the priority to the vote itself so that each priority is
    // guaranteed to have exactly one vote, which is also easily and efficiently replaceable.
    private final SparseArray<SparseArray<Vote>> mVotesByDisplay;
    // A map from the display ID to the supported modes on that display.
    private final SparseArray<Display.Mode[]> mSupportedModesByDisplay;
    // A map from the display ID to the default mode of that display.
    private final SparseArray<Display.Mode> mDefaultModeByDisplay;

    private final AppRequestObserver mAppRequestObserver;
    private final SettingsObserver mSettingsObserver;
    private final DisplayObserver mDisplayObserver;


    private Listener mListener;

    public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
        mContext = context;
        mHandler = new DisplayModeDirectorHandler(handler.getLooper());
        mVotesByDisplay = new SparseArray<>();
        mSupportedModesByDisplay = new SparseArray<>();
        mDefaultModeByDisplay =  new SparseArray<>();
        mAppRequestObserver = new AppRequestObserver();
        mSettingsObserver = new SettingsObserver(context, handler);
        mDisplayObserver = new DisplayObserver(context, handler);
    }

    /**
     * Tells the DisplayModeDirector to update allowed votes and begin observing relevant system
     * state.
     *
     * This has to be deferred because the object may be constructed before the rest of the system
     * is ready.
     */
    public void start() {
        mSettingsObserver.observe();
        mDisplayObserver.observe();
        mSettingsObserver.observe();
        synchronized (mLock) {
            // We may have a listener already registered before the call to start, so go ahead and
            // notify them to pick up our newly initialized state.
            notifyAllowedModesChangedLocked();
        }
    }

    /**
     * Calculates the modes the system is allowed to freely switch between based on global and
     * display-specific constraints.
     *
     * @param displayId The display to query for.
     * @return The IDs of the modes the system is allowed to freely switch between.
     */
    @NonNull
    public int[] getAllowedModes(int displayId) {
        synchronized (mLock) {
            SparseArray<Vote> votes = getVotesLocked(displayId);
            Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
            Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId);
            if (modes == null || defaultMode == null) {
                Slog.e(TAG, "Asked about unknown display, returning empty allowed set! (id="
                        + displayId + ")");
                return new int[0];
            }
            return getAllowedModesLocked(votes, modes, defaultMode);
        }
    }

    @NonNull
    private SparseArray<Vote> getVotesLocked(int displayId) {
        SparseArray<Vote> displayVotes = mVotesByDisplay.get(displayId);
        final SparseArray<Vote> votes;
        if (displayVotes != null) {
            votes = displayVotes.clone();
        } else {
            votes = new SparseArray<>();
        }

        SparseArray<Vote> globalVotes = mVotesByDisplay.get(GLOBAL_ID);
        if (globalVotes != null) {
            for (int i = 0; i < globalVotes.size(); i++) {
                int priority = globalVotes.keyAt(i);
                if (votes.indexOfKey(priority) < 0) {
                    votes.put(priority, globalVotes.valueAt(i));
                }
            }
        }
        return votes;
    }

    @NonNull
    private int[] getAllowedModesLocked(@NonNull SparseArray<Vote> votes,
            @NonNull Display.Mode[] modes, @NonNull Display.Mode defaultMode) {
        int lowestConsideredPriority = Vote.MIN_PRIORITY;
        while (lowestConsideredPriority <= Vote.MAX_PRIORITY) {
            float minRefreshRate = 0f;
            float maxRefreshRate = Float.POSITIVE_INFINITY;
            int height = Vote.INVALID_SIZE;
            int width = Vote.INVALID_SIZE;

            for (int priority = Vote.MAX_PRIORITY;
                    priority >= lowestConsideredPriority;
                    priority--) {
                Vote vote = votes.get(priority);
                if (vote == null) {
                    continue;
                }
                // For refresh rates, just use the tightest bounds of all the votes
                minRefreshRate = Math.max(minRefreshRate, vote.minRefreshRate);
                maxRefreshRate = Math.min(maxRefreshRate, vote.maxRefreshRate);
                // For display size, use only the first vote we come across (i.e. the highest
                // priority vote that includes the width / height).
                if (height == Vote.INVALID_SIZE && width == Vote.INVALID_SIZE
                        && vote.height > 0 && vote.width > 0) {
                    width = vote.width;
                    height = vote.height;
                }
            }

            // If we don't have anything specifying the width / height of the display, just use the
            // default width and height. We don't want these switching out from underneath us since
            // it's a pretty disruptive behavior.
            if (height == Vote.INVALID_SIZE || width == Vote.INVALID_SIZE) {
                width = defaultMode.getPhysicalWidth();
                height = defaultMode.getPhysicalHeight();
            }

            int[] availableModes =
                    filterModes(modes, width, height, minRefreshRate, maxRefreshRate);
            if (availableModes.length > 0) {
                if (DEBUG) {
                    Slog.w(TAG, "Found available modes=" + Arrays.toString(availableModes)
                            + " with lowest priority considered "
                            + Vote.priorityToString(lowestConsideredPriority)
                            + " and constraints: "
                            + "width=" + width
                            + ", height=" + height
                            + ", minRefreshRate=" + minRefreshRate
                            + ", maxRefreshRate=" + maxRefreshRate);
                }
                return availableModes;
            }

            if (DEBUG) {
                Slog.w(TAG, "Couldn't find available modes with lowest priority set to "
                        + Vote.priorityToString(lowestConsideredPriority)
                        + " and with the following constraints: "
                        + "width=" + width
                        + ", height=" + height
                        + ", minRefreshRate=" + minRefreshRate
                        + ", maxRefreshRate=" + maxRefreshRate);
            }
            // If we haven't found anything with the current set of votes, drop the current lowest
            // priority vote.
            lowestConsideredPriority++;
        }

        // If we still haven't found anything that matches our current set of votes, just fall back
        // to the default mode.
        return new int[] { defaultMode.getModeId() };
    }

    private int[] filterModes(Display.Mode[] supportedModes,
            int width, int height, float minRefreshRate, float maxRefreshRate) {
        ArrayList<Display.Mode> availableModes = new ArrayList<>();
        for (Display.Mode mode : supportedModes) {
            if (mode.getPhysicalWidth() != width || mode.getPhysicalHeight() != height) {
                if (DEBUG) {
                    Slog.w(TAG, "Discarding mode " + mode.getModeId() + ", wrong size"
                            + ": desiredWidth=" + width
                            + ": desiredHeight=" + height
                            + ": actualWidth=" + mode.getPhysicalWidth()
                            + ": actualHeight=" + mode.getPhysicalHeight());
                }
                continue;
            }
            final float refreshRate = mode.getRefreshRate();
            // Some refresh rates are calculated based on frame timings, so they aren't *exactly*
            // equal to expected refresh rate. Given that, we apply a bit of tolerance to this
            // comparison.
            if (refreshRate < (minRefreshRate - EPSILON)
                    || refreshRate > (maxRefreshRate + EPSILON)) {
                if (DEBUG) {
                    Slog.w(TAG, "Discarding mode " + mode.getModeId()
                            + ", outside refresh rate bounds"
                            + ": minRefreshRate=" + minRefreshRate
                            + ", maxRefreshRate=" + maxRefreshRate
                            + ", modeRefreshRate=" + refreshRate);
                }
                continue;
            }
            availableModes.add(mode);
        }
        final int size = availableModes.size();
        int[] availableModeIds = new int[size];
        for (int i = 0; i < size; i++) {
            availableModeIds[i] = availableModes.get(i).getModeId();
        }
        return availableModeIds;
    }

    /**
     * Gets the observer responsible for application display mode requests.
     */
    @NonNull
    public AppRequestObserver getAppRequestObserver() {
        // We don't need to lock here because mAppRequestObserver is a final field, which is
        // guaranteed to be visible on all threads after construction.
        return mAppRequestObserver;
    }

    /**
     * Sets the listener for changes to allowed display modes.
     */
    public void setListener(@Nullable Listener listener) {
        synchronized (mLock) {
            mListener = listener;
        }
    }

    /**
     * Print the object's state and debug information into the given stream.
     *
     * @param pw The stream to dump information to.
     */
    public void dump(PrintWriter pw) {
        pw.println("DisplayModeDirector");
        synchronized (mLock) {
            pw.println("  mSupportedModesByDisplay:");
            for (int i = 0; i < mSupportedModesByDisplay.size(); i++) {
                final int id = mSupportedModesByDisplay.keyAt(i);
                final Display.Mode[] modes = mSupportedModesByDisplay.valueAt(i);
                pw.println("    " + id + " -> " + Arrays.toString(modes));
            }
            pw.println("  mDefaultModeByDisplay:");
            for (int i = 0; i < mDefaultModeByDisplay.size(); i++) {
                final int id = mDefaultModeByDisplay.keyAt(i);
                final Display.Mode mode = mDefaultModeByDisplay.valueAt(i);
                pw.println("    " + id + " -> " + mode);
            }
            pw.println("  mVotesByDisplay:");
            for (int i = 0; i < mVotesByDisplay.size(); i++) {
                pw.println("    " + mVotesByDisplay.keyAt(i) + ":");
                SparseArray<Vote> votes = mVotesByDisplay.valueAt(i);
                for (int p = Vote.MAX_PRIORITY; p >= Vote.MIN_PRIORITY; p--) {
                    Vote vote = votes.get(p);
                    if (vote == null) {
                        continue;
                    }
                    pw.println("      " + Vote.priorityToString(p) + " -> " + vote);
                }
            }
            mSettingsObserver.dumpLocked(pw);
            mAppRequestObserver.dumpLocked(pw);
        }
    }

    private void updateVoteLocked(int priority, Vote vote) {
        updateVoteLocked(GLOBAL_ID, priority, vote);
    }

    private void updateVoteLocked(int displayId, int priority, Vote vote) {
        if (DEBUG) {
            Slog.i(TAG, "updateVoteLocked(displayId=" + displayId
                    + ", priority=" + Vote.priorityToString(priority)
                    + ", vote=" + vote + ")");
        }
        if (priority < Vote.MIN_PRIORITY || priority > Vote.MAX_PRIORITY) {
            Slog.w(TAG, "Received a vote with an invalid priority, ignoring:"
                    + " priority=" + Vote.priorityToString(priority)
                    + ", vote=" + vote, new Throwable());
            return;
        }
        final SparseArray<Vote> votes = getOrCreateVotesByDisplay(displayId);

        Vote currentVote = votes.get(priority);
        if (vote != null) {
            votes.put(priority, vote);
        } else {
            votes.remove(priority);
        }

        if (votes.size() == 0) {
            if (DEBUG) {
                Slog.i(TAG, "No votes left for display " + displayId + ", removing.");
            }
            mVotesByDisplay.remove(displayId);
        }

        notifyAllowedModesChangedLocked();
    }

    private void notifyAllowedModesChangedLocked() {
        if (mListener != null && !mHandler.hasMessages(MSG_ALLOWED_MODES_CHANGED)) {
            // We need to post this to a handler to avoid calling out while holding the lock
            // since we know there are things that both listen for changes as well as provide
            // information. If we did call out while holding the lock, then there's no guaranteed
            // lock order and we run the real of risk deadlock.
            Message msg = mHandler.obtainMessage(MSG_ALLOWED_MODES_CHANGED, mListener);
            msg.sendToTarget();
        }
    }

    private SparseArray<Vote> getOrCreateVotesByDisplay(int displayId) {
        int index = mVotesByDisplay.indexOfKey(displayId);
        if (mVotesByDisplay.indexOfKey(displayId) >= 0) {
            return mVotesByDisplay.get(displayId);
        } else {
            SparseArray<Vote> votes = new SparseArray<>();
            mVotesByDisplay.put(displayId, votes);
            return votes;
        }
    }

    /**
     * Listens for changes to display mode coordination.
     */
    public interface Listener {
        /**
         * Called when the allowed display modes may have changed.
         */
        void onAllowedDisplayModesChanged();
    }

    private static final class DisplayModeDirectorHandler extends Handler {
        DisplayModeDirectorHandler(Looper looper) {
            super(looper, null, true /*async*/);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_ALLOWED_MODES_CHANGED:
                    Listener listener = (Listener) msg.obj;
                    listener.onAllowedDisplayModesChanged();
                    break;
            }
        }
    }

    private static final class Vote {
        // We split the app request into two priorities in case we can satisfy one desire without
        // the other.
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 0;
        public static final int PRIORITY_APP_REQUEST_SIZE = 1;
        public static final int PRIORITY_USER_SETTING_REFRESH_RATE = 2;
        public static final int PRIORITY_LOW_BRIGHTNESS = 3;
        public static final int PRIORITY_LOW_POWER_MODE = 4;

        // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
        // appropriate, as well as priorityToString.

        public static final int MIN_PRIORITY = PRIORITY_APP_REQUEST_REFRESH_RATE;
        public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;

        /**
         * A value signifying an invalid width or height in a vote.
         */
        public static final int INVALID_SIZE = -1;

        /**
         * The requested width of the display in pixels, or INVALID_SIZE;
         */
        public final int width;
        /**
         * The requested height of the display in pixels, or INVALID_SIZE;
         */
        public final int height;

        /**
         * The lowest desired refresh rate.
         */
        public final float minRefreshRate;
        /**
         * The highest desired refresh rate.
         */
        public final float maxRefreshRate;

        public static Vote forRefreshRates(float minRefreshRate, float maxRefreshRate) {
            return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate);
        }

        public static Vote forSize(int width, int height) {
            return new Vote(width, height, 0f, Float.POSITIVE_INFINITY);
        }

        private Vote(int width, int height,
                float minRefreshRate, float maxRefreshRate) {
            this.width = width;
            this.height = height;
            this.minRefreshRate = minRefreshRate;
            this.maxRefreshRate = maxRefreshRate;
        }

        public static String priorityToString(int priority) {
            switch (priority) {
                case PRIORITY_APP_REQUEST_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_SIZE:
                    return "PRIORITY_APP_REQUEST_SIZE";
                case PRIORITY_USER_SETTING_REFRESH_RATE:
                    return "PRIORITY_USER_SETTING_REFRESH_RATE";
                case PRIORITY_LOW_POWER_MODE:
                    return "PRIORITY_LOW_POWER_MODE";
                default:
                    return Integer.toString(priority);
            }
        }

        @Override
        public String toString() {
            return "Vote{"
                + "width=" + width
                + ", height=" + height
                + ", minRefreshRate=" + minRefreshRate
                + ", maxRefreshRate=" + maxRefreshRate
                + "}";
        }
    }

    private final class SettingsObserver extends ContentObserver {
        private final Uri mRefreshRateSetting =
                Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
        private final Uri mLowPowerModeSetting =
                Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE);
        private final Uri mBrightnessSetting =
                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);

        private final Context mContext;
        private final float mDefaultPeakRefreshRate;
        private final int mBrightnessThreshold;

        SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
            super(handler);
            mContext = context;
            mDefaultPeakRefreshRate = (float) context.getResources().getInteger(
                    R.integer.config_defaultPeakRefreshRate);
            mBrightnessThreshold = context.getResources().getInteger(
                    R.integer.config_brightnessThresholdOfPeakRefreshRate);
        }

        public void observe() {
            final ContentResolver cr = mContext.getContentResolver();
            cr.registerContentObserver(mRefreshRateSetting, false /*notifyDescendants*/, this,
                    UserHandle.USER_SYSTEM);
            cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
                    UserHandle.USER_SYSTEM);
            if (mBrightnessThreshold >= 0) {
                cr.registerContentObserver(mBrightnessSetting, false /*notifyDescendants*/, this,
                    UserHandle.USER_SYSTEM);
            }
            synchronized (mLock) {
                updateRefreshRateSettingLocked();
                updateLowPowerModeSettingLocked();
                updateBrightnessSettingLocked();
            }
        }

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            synchronized (mLock) {
                if (mRefreshRateSetting.equals(uri)) {
                    updateRefreshRateSettingLocked();
                } else if (mLowPowerModeSetting.equals(uri)) {
                    updateLowPowerModeSettingLocked();
                } else if (mBrightnessThreshold >=0 && mBrightnessSetting.equals(uri)) {
                    updateBrightnessSettingLocked();
                }
            }
        }

        private void updateLowPowerModeSettingLocked() {
            boolean inLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
                    Settings.Global.LOW_POWER_MODE, 0 /*default*/) != 0;
            final Vote vote;
            if (inLowPowerMode) {
                vote = Vote.forRefreshRates(0f, 60f);
            } else {
                vote = null;
            }
            updateVoteLocked(Vote.PRIORITY_LOW_POWER_MODE, vote);
        }

        private void updateRefreshRateSettingLocked() {
            float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
                    Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
            Vote vote = Vote.forRefreshRates(0f, peakRefreshRate);
            updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote);
        }

        private void updateBrightnessSettingLocked() {
            int brightness = Settings.System.getInt(mContext.getContentResolver(),
                    Settings.System.SCREEN_BRIGHTNESS, -1);

            if (brightness < 0) {
                return;
            }

            final Vote vote;
            if (brightness <= mBrightnessThreshold) {
                vote = Vote.forRefreshRates(0f, 60f);
            } else {
                vote = null;
            }
            updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
        }

        public void dumpLocked(PrintWriter pw) {
            pw.println("  SettingsObserver");
            pw.println("    mDefaultPeakRefreshRate: " + mDefaultPeakRefreshRate);
        }
    }

    final class AppRequestObserver {
        private SparseArray<Display.Mode> mAppRequestedModeByDisplay;

        AppRequestObserver() {
            mAppRequestedModeByDisplay = new SparseArray<>();
        }

        public void setAppRequestedMode(int displayId, int modeId) {
            synchronized (mLock) {
                setAppRequestedModeLocked(displayId, modeId);
            }
        }

        private void setAppRequestedModeLocked(int displayId, int modeId) {
            final Display.Mode requestedMode = findModeByIdLocked(displayId, modeId);
            if (Objects.equals(requestedMode, mAppRequestedModeByDisplay.get(displayId))) {
                return;
            }

            final Vote refreshRateVote;
            final Vote sizeVote;
            if (requestedMode != null) {
                mAppRequestedModeByDisplay.put(displayId, requestedMode);
                float refreshRate = requestedMode.getRefreshRate();
                refreshRateVote = Vote.forRefreshRates(refreshRate, refreshRate);
                sizeVote = Vote.forSize(requestedMode.getPhysicalWidth(),
                        requestedMode.getPhysicalHeight());
            } else {
                mAppRequestedModeByDisplay.remove(displayId);
                refreshRateVote = null;
                sizeVote = null;
            }
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
            return;
        }

        private Display.Mode findModeByIdLocked(int displayId, int modeId) {
            Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
            if (modes == null) {
                return null;
            }
            for (Display.Mode mode : modes) {
                if (mode.getModeId() == modeId) {
                    return mode;
                }
            }
            return null;
        }

        public void dumpLocked(PrintWriter pw) {
            pw.println("  AppRequestObserver");
            pw.println("    mAppRequestedModeByDisplay:");
            for (int i = 0; i < mAppRequestedModeByDisplay.size(); i++) {
                final int id = mAppRequestedModeByDisplay.keyAt(i);
                final Display.Mode mode = mAppRequestedModeByDisplay.valueAt(i);
                pw.println("    " + id + " -> " + mode);
            }
        }
    }

    private final class DisplayObserver implements DisplayManager.DisplayListener {
        // Note that we can never call into DisplayManager or any of the non-POD classes it
        // returns, while holding mLock since it may call into DMS, which might be simultaneously
        // calling into us already holding its own lock.
        private final Context mContext;
        private final Handler mHandler;

        DisplayObserver(Context context, Handler handler) {
            mContext = context;
            mHandler = handler;
        }

        public void observe() {
            DisplayManager dm = mContext.getSystemService(DisplayManager.class);
            dm.registerDisplayListener(this, mHandler);

            // Populate existing displays
            SparseArray<Display.Mode[]> modes = new SparseArray<>();
            SparseArray<Display.Mode> defaultModes = new SparseArray<>();
            DisplayInfo info = new DisplayInfo();
            Display[] displays = dm.getDisplays();
            for (Display d : displays) {
                final int displayId = d.getDisplayId();
                d.getDisplayInfo(info);
                modes.put(displayId, info.supportedModes);
                defaultModes.put(displayId, info.getDefaultMode());
            }
            synchronized (mLock) {
                final int size = modes.size();
                for (int i = 0; i < size; i++) {
                    mSupportedModesByDisplay.put(modes.keyAt(i), modes.valueAt(i));
                    mDefaultModeByDisplay.put(defaultModes.keyAt(i), defaultModes.valueAt(i));
                }
            }
        }

        @Override
        public void onDisplayAdded(int displayId) {
            updateDisplayModes(displayId);
        }

        @Override
        public void onDisplayRemoved(int displayId) {
            synchronized (mLock) {
                mSupportedModesByDisplay.remove(displayId);
                mDefaultModeByDisplay.remove(displayId);
            }
        }

        @Override
        public void onDisplayChanged(int displayId) {
            updateDisplayModes(displayId);
        }

        private void updateDisplayModes(int displayId) {
            Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
            if (d == null) {
                // We can occasionally get a display added or changed event for a display that was
                // subsequently removed, which means this returns null. Check this case and bail
                // out early; if it gets re-attached we'll eventually get another call back for it.
                return;
            }
            DisplayInfo info = new DisplayInfo();
            d.getDisplayInfo(info);
            boolean changed = false;
            synchronized (mLock) {
                if (!Arrays.equals(mSupportedModesByDisplay.get(displayId), info.supportedModes)) {
                    mSupportedModesByDisplay.put(displayId, info.supportedModes);
                    changed = true;
                }
                if (!Objects.equals(mDefaultModeByDisplay.get(displayId), info.getDefaultMode())) {
                    changed = true;
                    mDefaultModeByDisplay.put(displayId, info.getDefaultMode());
                }
                if (changed) {
                    notifyAllowedModesChangedLocked();
                }
            }
        }
    }
}
