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

Commit 7c72668f authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Adjust activity display metrics based on stack configuration.

Apps normally use context.getResources().getDisplayMetrics()
or getWindowManager().getDefaultDisplay() to get information
about the screen dimensions. Not all the screen space is available
for apps in a multi-window environment, so we limit the dimensions
of the display object exposed to the app to that of the containing
stack.

Bug: 19225079
Bug: 19354838
Change-Id: I8dc3a6c9b99ecedcca28fc4ddaba9f31feb4f871
parent 80955e10
Loading
Loading
Loading
Loading
+13 −16
Original line number Diff line number Diff line
@@ -2372,35 +2372,32 @@ public final class ActivityThread {
        return activity;
    }

    private Context createBaseContextForActivity(ActivityClientRecord r,
            final Activity activity) {
        ContextImpl appContext =
                ContextImpl.createActivityContext(this, r.packageInfo, r.overrideConfig);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        int displayId = Display.DEFAULT_DISPLAY;
        try {
            IActivityContainer container =
                    ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token);
            final int displayId =
                    container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId();
            if (displayId > Display.DEFAULT_DISPLAY) {
                Display display = dm.getRealDisplay(displayId, r.token);
                baseContext = appContext.createDisplayContext(display);
            if (container != null) {
                displayId = container.getDisplayId();
            }
        } catch (RemoteException e) {
        }

        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, displayId, r.overrideConfig);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
        // For debugging purposes, if the activity's package name contains the value of
        // the "debug.use-second-display" system property as a substring, then show
        // its content on a secondary display if there is one.
        String pkgName = SystemProperties.get("debug.second-display.pkg");
        if (pkgName != null && !pkgName.isEmpty()
                && r.packageInfo.mPackageName.contains(pkgName)) {
            for (int displayId : dm.getDisplayIds()) {
                if (displayId != Display.DEFAULT_DISPLAY) {
                    Display display = dm.getRealDisplay(displayId, r.token);
            for (int id : dm.getDisplayIds()) {
                if (id != Display.DEFAULT_DISPLAY) {
                    Display display = dm.getRealDisplay(id, r.overrideConfig);
                    baseContext = appContext.createDisplayContext(display);
                    break;
                }
+6 −4
Original line number Diff line number Diff line
@@ -2252,7 +2252,7 @@ class ContextImpl extends Context {
        ContextImpl context = new ContextImpl(null, mainThread,
                packageInfo, null, null, false, null, null);
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
                context.mResourcesManager.getDisplayMetricsLocked());
        return context;
    }

@@ -2263,9 +2263,11 @@ class ContextImpl extends Context {
    }

    static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, Configuration overrideConfiguration) {
            LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        return new ContextImpl(null, mainThread, packageInfo, null, null, false, null,
        final Display display = ResourcesManager.getInstance().getAdjustedDisplay(
                displayId, overrideConfiguration);
        return new ContextImpl(null, mainThread, packageInfo, null, null, false, display,
                overrideConfiguration);
    }

@@ -2296,7 +2298,7 @@ class ContextImpl extends Context {
            compatInfo = packageInfo.getCompatibilityInfo();
        }
        mDisplayAdjustments.setCompatibilityInfo(compatInfo);
        mDisplayAdjustments.setActivityToken(activityToken);
        mDisplayAdjustments.setConfiguration(overrideConfiguration);

        Resources resources = packageInfo.getResources(mainThread);
        if (resources != null) {
+49 −45
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.res.ResourcesKey;
import android.hardware.display.DisplayManagerGlobal;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayAdjustments;
@@ -40,11 +41,10 @@ public class ResourcesManager {
    private static final boolean DEBUG = false;

    private static ResourcesManager sResourcesManager;
    final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources
            = new ArrayMap<ResourcesKey, WeakReference<Resources> >();

    final ArrayMap<DisplayAdjustments, DisplayMetrics> mDefaultDisplayMetrics
            = new ArrayMap<DisplayAdjustments, DisplayMetrics>();
    private final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources =
            new ArrayMap<>();
    private final ArrayMap<Pair<Integer, Configuration>, WeakReference<Display>> mDisplays =
            new ArrayMap<>();

    CompatibilityInfo mResCompatibilityInfo;

@@ -63,46 +63,18 @@ public class ResourcesManager {
        return mResConfiguration;
    }

    public void flushDisplayMetricsLocked() {
        mDefaultDisplayMetrics.clear();
    }

    public DisplayMetrics getDisplayMetricsLocked(int displayId) {
        return getDisplayMetricsLocked(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
    }

    public DisplayMetrics getDisplayMetricsLocked(int displayId, DisplayAdjustments daj) {
        boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
        DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(daj) : null;
        if (dm != null) {
            return dm;
    DisplayMetrics getDisplayMetricsLocked() {
        return getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
    }
        dm = new DisplayMetrics();

        DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
        if (displayManager == null) {
            // may be null early in system startup
            dm.setToDefaults();
            return dm;
        }

        if (isDefaultDisplay) {
            mDefaultDisplayMetrics.put(daj, dm);
        }

        Display d = displayManager.getCompatibleDisplay(displayId, daj);
        if (d != null) {
            d.getMetrics(dm);
    DisplayMetrics getDisplayMetricsLocked(int displayId) {
        DisplayMetrics dm = new DisplayMetrics();
        final Display display = getAdjustedDisplay(displayId, Configuration.EMPTY);
        if (display != null) {
            display.getMetrics(dm);
        } else {
            // Display no longer exists
            // FIXME: This would not be a problem if we kept the Display object around
            // instead of using the raw display id everywhere.  The Display object caches
            // its information even after the display has been removed.
            dm.setToDefaults();
        }
        //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
        //        + metrics.heightPixels + " den=" + metrics.density
        //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
        return dm;
    }

@@ -137,6 +109,37 @@ public class ResourcesManager {
        return false;
    }

    /**
     * Returns an adjusted {@link Display} object based on the inputs or null if display isn't
     * available.
     *
     * @param displayId display Id.
     * @param overrideConfiguration override configurations.
     */
    public Display getAdjustedDisplay(final int displayId, Configuration overrideConfiguration) {
        final Pair<Integer, Configuration> key =
                Pair.create(displayId, new Configuration(overrideConfiguration));
        synchronized (this) {
            WeakReference<Display> wd = mDisplays.get(key);
            if (wd != null) {
                final Display display = wd.get();
                if (display != null) {
                    return display;
                }
            }
            final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
            if (dm == null) {
                // may be null early in system startup
                return null;
            }
            final Display display = dm.getRealDisplay(displayId, key.second);
            if (display != null) {
                mDisplays.put(key, new WeakReference<>(display));
            }
            return display;
        }
    }

    /**
     * Creates the top level Resources for applications with the given compatibility info.
     *
@@ -148,7 +151,7 @@ public class ResourcesManager {
     * @param overrideConfiguration override configurations.
     * @param compatInfo the compatibility info. Must not be null.
     */
    public Resources getTopLevelResources(String resDir, String[] splitResDirs,
    Resources getTopLevelResources(String resDir, String[] splitResDirs,
            String[] overlayDirs, String[] libDirs, int displayId,
            Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
        final float scale = compatInfo.applicationScale;
@@ -247,7 +250,7 @@ public class ResourcesManager {
        }
    }

    public final boolean applyConfigurationToResourcesLocked(Configuration config,
    final boolean applyConfigurationToResourcesLocked(Configuration config,
            CompatibilityInfo compat) {
        if (mResConfiguration == null) {
            mResConfiguration = new Configuration();
@@ -258,8 +261,9 @@ public class ResourcesManager {
            return false;
        }
        int changes = mResConfiguration.updateFrom(config);
        flushDisplayMetricsLocked();
        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
        // Things might have changed in display manager, so clear the cached displays.
        mDisplays.clear();
        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked();

        if (compat != null && (mResCompatibilityInfo == null ||
                !mResCompatibilityInfo.equals(compat))) {
+4 −4
Original line number Diff line number Diff line
@@ -17,10 +17,10 @@
package android.hardware.display;

import android.content.Context;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager.DisplayListener;
import android.media.projection.MediaProjection;
import android.media.projection.IMediaProjection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -196,11 +196,11 @@ public final class DisplayManagerGlobal {
     * Gets information about a logical display without applying any compatibility metrics.
     *
     * @param displayId The logical display id.
     * @param IBinder the activity token for this display.
     * @param configuration the configuration.
     * @return The display object, or null if there is no display with the given id.
     */
    public Display getRealDisplay(int displayId, IBinder token) {
        return getCompatibleDisplay(displayId, new DisplayAdjustments(token));
    public Display getRealDisplay(int displayId, Configuration configuration) {
        return getCompatibleDisplay(displayId, new DisplayAdjustments(configuration));
    }

    public void registerDisplayListener(DisplayListener listener, Handler handler) {
+1 −1
Original line number Diff line number Diff line
@@ -716,7 +716,7 @@ public final class Display {
            updateDisplayInfoLocked();
            mDisplayInfo.getLogicalMetrics(outMetrics,
                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
                    mDisplayAdjustments.getActivityToken());
                    mDisplayAdjustments.getConfiguration());
        }
    }

Loading