Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4753576d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add caching for getDisplayInfo" into rvc-dev

parents 035a0710 890ceb5e
Loading
Loading
Loading
Loading
+54 −23
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.hardware.display;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -99,6 +100,20 @@ public final class DisplayManagerGlobal {
        }
    }

    private PropertyInvalidatedCache<Integer, DisplayInfo> mDisplayCache =
            new PropertyInvalidatedCache<Integer, DisplayInfo>(
                8, // size of display cache
                CACHE_KEY_DISPLAY_INFO_PROPERTY) {
                @Override
                protected DisplayInfo recompute(Integer id) {
                    try {
                        return mDm.getDisplayInfo(id);
                    } catch (RemoteException ex) {
                        throw ex.rethrowFromSystemServer();
                    }
                }
            };

    /**
     * Gets an instance of the display manager global singleton.
     *
@@ -127,24 +142,21 @@ public final class DisplayManagerGlobal {
     */
    @UnsupportedAppUsage
    public DisplayInfo getDisplayInfo(int displayId) {
        try {
        synchronized (mLock) {
                DisplayInfo info;
                if (USE_CACHE) {
                    info = mDisplayInfoCache.get(displayId);
                    if (info != null) {
                        return info;
            DisplayInfo info = null;
            if (mDisplayCache != null) {
                info = mDisplayCache.query(displayId);
            } else {
                try {
                    info = mDm.getDisplayInfo(displayId);
                } catch (RemoteException ex) {
                    ex.rethrowFromSystemServer();
                }
            }

                info = mDm.getDisplayInfo(displayId);
            if (info == null) {
                return null;
            }

                if (USE_CACHE) {
                    mDisplayInfoCache.put(displayId, info);
                }
            registerCallbackIfNeededLocked();

            if (DEBUG) {
@@ -152,9 +164,6 @@ public final class DisplayManagerGlobal {
            }
            return info;
        }
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    /**
@@ -777,4 +786,26 @@ public final class DisplayManagerGlobal {
            }
        }
    }

    /**
     * Name of the property containing a unique token which changes every time we update the
     * system's display configuration.
     */
    public static final String CACHE_KEY_DISPLAY_INFO_PROPERTY =
            "cache_key.display_info";

    /**
     * Invalidates the contents of the display info cache for all applications. Can only
     * be called by system_server.
     */
    public static void invalidateLocalDisplayInfoCaches() {
        PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DISPLAY_INFO_PROPERTY);
    }

    /**
     * Disables the binder call cache.
     */
    public void disableLocalDisplayInfoCaches() {
        mDisplayCache = null;
    }
}
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.Nullable;
import android.hardware.display.DisplayManagerGlobal;
import android.view.DisplayInfo;

/**
 * Class for wrapping access of DisplayInfo objects by LogicalDisplay so that we can appropriately
 * invalidate caches when they change.
 */
public class DisplayInfoProxy {
    private DisplayInfo mInfo;

    public DisplayInfoProxy(@Nullable DisplayInfo info) {
        mInfo = info;
    }

    /**
     * Set the current {@link DisplayInfo}.
     *
     * The also automatically invalidates the display info caches across the entire system.
     * @param info the new {@link DisplayInfo}.
     */
    public void set(@Nullable DisplayInfo info) {
        mInfo = info;
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
    }

    /**
     * Returns the current {@link DisplayInfo}.
     *
     * This info <b>must</b> be treated as immutable. Modifying the returned object is undefined
     * behavior that <b>will</b> result in inconsistent states across the system.
     *
     * @return the current {@link DisplayInfo}
     */
    @Nullable
    public DisplayInfo get() {
        return mInfo;
    }
}
+15 −1
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ public final class DisplayManagerService extends SystemService {
    private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();

    // List of all logical displays indexed by logical display id.
    // Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache.
    private final SparseArray<LogicalDisplay> mLogicalDisplays =
            new SparseArray<LogicalDisplay>();
    private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
@@ -373,6 +374,10 @@ public final class DisplayManagerService extends SystemService {
        }
        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);

        // If there was a runtime restart then we may have stale caches left around, so we need to
        // make sure to invalidate them upon every start.
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();

        publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
                true /*allowIsolated*/);
        publishLocalService(DisplayManagerInternal.class, new LocalService());
@@ -1005,9 +1010,17 @@ public final class DisplayManagerService extends SystemService {
        if (displayId == Display.DEFAULT_DISPLAY) {
            recordTopInsetLocked(display);
        }
        // We don't bother invalidating the display info caches here because any changes to the
        // display info will trigger a cache invalidation inside of LogicalDisplay before we hit
        // this point.
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
    }

    private void handleLogicalDisplayRemoved(int displayId) {
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
    }

    private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
        final int count = mDisplayDevices.size();
        for (int i = 0; i < count; i++) {
@@ -1066,6 +1079,7 @@ public final class DisplayManagerService extends SystemService {
        }

        mLogicalDisplays.put(displayId, display);
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();

        // Wake up waitForDefaultDisplay.
        if (isDefault) {
@@ -1206,7 +1220,7 @@ public final class DisplayManagerService extends SystemService {
            display.updateLocked(mDisplayDevices);
            if (!display.isValidLocked()) {
                mLogicalDisplays.removeAt(i);
                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
                handleLogicalDisplayRemoved(displayId);
                changed = true;
            } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
                handleLogicalDisplayChanged(displayId, display);
+25 −24
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ final class LogicalDisplay {
     * needs to be updated.
     * @see #getDisplayInfoLocked()
     */
    private DisplayInfo mInfo;
    private final DisplayInfoProxy mInfo = new DisplayInfoProxy(null);

    // The display device that this logical display is based on and which
    // determines the base metrics that it uses.
@@ -141,26 +141,27 @@ final class LogicalDisplay {
     * the data changes.
     */
    public DisplayInfo getDisplayInfoLocked() {
        if (mInfo == null) {
            mInfo = new DisplayInfo();
            mInfo.copyFrom(mBaseDisplayInfo);
        if (mInfo.get() == null) {
            DisplayInfo info = new DisplayInfo();
            info.copyFrom(mBaseDisplayInfo);
            if (mOverrideDisplayInfo != null) {
                mInfo.appWidth = mOverrideDisplayInfo.appWidth;
                mInfo.appHeight = mOverrideDisplayInfo.appHeight;
                mInfo.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;
                mInfo.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;
                mInfo.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;
                mInfo.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;
                mInfo.logicalWidth = mOverrideDisplayInfo.logicalWidth;
                mInfo.logicalHeight = mOverrideDisplayInfo.logicalHeight;
                mInfo.rotation = mOverrideDisplayInfo.rotation;
                mInfo.displayCutout = mOverrideDisplayInfo.displayCutout;
                mInfo.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
                mInfo.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
                mInfo.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
                info.appWidth = mOverrideDisplayInfo.appWidth;
                info.appHeight = mOverrideDisplayInfo.appHeight;
                info.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;
                info.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;
                info.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;
                info.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;
                info.logicalWidth = mOverrideDisplayInfo.logicalWidth;
                info.logicalHeight = mOverrideDisplayInfo.logicalHeight;
                info.rotation = mOverrideDisplayInfo.rotation;
                info.displayCutout = mOverrideDisplayInfo.displayCutout;
                info.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
                info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
                info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
            }
            mInfo.set(info);
        }
        return mInfo;
        return mInfo.get();
    }

    /**
@@ -181,17 +182,16 @@ final class LogicalDisplay {
        if (info != null) {
            if (mOverrideDisplayInfo == null) {
                mOverrideDisplayInfo = new DisplayInfo(info);
                mInfo = null;
                mInfo.set(null);
                return true;
            }
            if (!mOverrideDisplayInfo.equals(info)) {
            } else if (!mOverrideDisplayInfo.equals(info)) {
                mOverrideDisplayInfo.copyFrom(info);
                mInfo = null;
                mInfo.set(null);
                return true;
            }
        } else if (mOverrideDisplayInfo != null) {
            mOverrideDisplayInfo = null;
            mInfo = null;
            mInfo.set(null);
            return true;
        }
        return false;
@@ -306,7 +306,7 @@ final class LogicalDisplay {
            mBaseDisplayInfo.displayId = mDisplayId;

            mPrimaryDisplayDeviceInfo = deviceInfo;
            mInfo = null;
            mInfo.set(null);
        }
    }

@@ -327,6 +327,7 @@ final class LogicalDisplay {
    private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) {
        boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
        if (maskCutout && deviceInfo.displayCutout != null) {
            // getSafeInsets is fixed at creation time and cannot change
            return deviceInfo.displayCutout.getSafeInsets();
        } else {
            return new Rect();