Loading core/java/android/app/ActivityThread.java +3 −0 Original line number Diff line number Diff line Loading @@ -6662,6 +6662,9 @@ public final class ActivityThread extends ClientTransactionHandler // Pass the current context to HardwareRenderer HardwareRenderer.setContextForInit(getSystemContext()); if (data.persistent) { HardwareRenderer.setIsSystemOrPersistent(); } // Instrumentation info affects the class loader, so load it before // setting up the app context. Loading core/java/android/view/ThreadedRenderer.java +3 −5 Original line number Diff line number Diff line Loading @@ -196,8 +196,6 @@ public final class ThreadedRenderer extends HardwareRenderer { */ public static boolean sRendererEnabled = true; public static boolean sTrimForeground = false; /** * Controls whether or not the renderer should aggressively trim * memory. Note that this must not be set for any process that uses Loading @@ -205,9 +203,10 @@ public final class ThreadedRenderer extends HardwareRenderer { * that do not go into the background. */ public static void enableForegroundTrimming() { sTrimForeground = true; // TODO: Remove } /** * Initialize HWUI for being in a system process like system_server * Should not be called in non-system processes Loading @@ -218,9 +217,8 @@ public final class ThreadedRenderer extends HardwareRenderer { // process. if (!ActivityManager.isHighEndGfx()) { sRendererEnabled = false; } else { enableForegroundTrimming(); } setIsSystemOrPersistent(); } /** Loading core/java/android/view/ViewRootImpl.java +0 −3 Original line number Diff line number Diff line Loading @@ -1766,9 +1766,6 @@ public final class ViewRootImpl implements ViewParent, mAppVisibilityChanged = true; scheduleTraversals(); } if (!mAppVisible) { WindowManagerGlobal.trimForeground(); } AnimationHandler.requestAnimatorsEnabled(mAppVisible, this); } } Loading core/java/android/view/WindowManagerGlobal.java +0 −61 Original line number Diff line number Diff line Loading @@ -19,9 +19,7 @@ package android.view; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; Loading Loading @@ -524,9 +522,6 @@ public final class WindowManagerGlobal { } allViewsRemoved = mRoots.isEmpty(); } if (ThreadedRenderer.sTrimForeground) { doTrimForeground(); } // If we don't have any views anymore in our process, we no longer need the // InsetsAnimationThread to save some resources. Loading @@ -543,65 +538,9 @@ public final class WindowManagerGlobal { return index; } public static boolean shouldDestroyEglContext(int trimLevel) { // On low-end gfx devices we trim when memory is moderate; // on high-end devices we do this when low. if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { return true; } if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_MODERATE && !ActivityManager.isHighEndGfx()) { return true; } return false; } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void trimMemory(int level) { if (shouldDestroyEglContext(level)) { // Destroy all hardware surfaces and resources associated to // known windows synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { mRoots.get(i).destroyHardwareResources(); } } // Force a full memory flush level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; } ThreadedRenderer.trimMemory(level); if (ThreadedRenderer.sTrimForeground) { doTrimForeground(); } } public static void trimForeground() { if (ThreadedRenderer.sTrimForeground) { WindowManagerGlobal wm = WindowManagerGlobal.getInstance(); wm.doTrimForeground(); } } private void doTrimForeground() { boolean hasVisibleWindows = false; synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { final ViewRootImpl root = mRoots.get(i); if (root.mView != null && root.getHostVisibility() == View.VISIBLE && root.mAttachInfo.mThreadedRenderer != null) { hasVisibleWindows = true; } else { root.destroyHardwareResources(); } } } if (!hasVisibleWindows) { ThreadedRenderer.trimMemory( ComponentCallbacks2.TRIM_MEMORY_COMPLETE); } } public void dumpGfxInfo(FileDescriptor fd, String[] args) { Loading graphics/java/android/graphics/HardwareRenderer.java +60 −42 Original line number Diff line number Diff line Loading @@ -47,9 +47,7 @@ import java.io.File; import java.io.FileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Optional; import java.util.concurrent.Executor; import java.util.stream.Stream; import sun.misc.Cleaner; Loading Loading @@ -1141,6 +1139,16 @@ public class HardwareRenderer { ProcessInitializer.sInstance.setContext(context); } /** * Sets whether or not the current process is a system or persistent process. Used to influence * the chosen memory usage policy. * * @hide **/ public static void setIsSystemOrPersistent() { nSetIsSystemOrPersistent(true); } /** * Returns true if HardwareRender will produce output. * Loading Loading @@ -1204,30 +1212,6 @@ public class HardwareRenderer { private static class ProcessInitializer { static ProcessInitializer sInstance = new ProcessInitializer(); // Magic values from android/data_space.h private static final int INTERNAL_DATASPACE_SRGB = 142671872; private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696; private static final int INTERNAL_DATASPACE_SCRGB = 411107328; private enum Dataspace { DISPLAY_P3(ColorSpace.Named.DISPLAY_P3, INTERNAL_DATASPACE_DISPLAY_P3), SCRGB(ColorSpace.Named.EXTENDED_SRGB, INTERNAL_DATASPACE_SCRGB), SRGB(ColorSpace.Named.SRGB, INTERNAL_DATASPACE_SRGB); private final ColorSpace.Named mColorSpace; private final int mNativeDataspace; Dataspace(ColorSpace.Named colorSpace, int nativeDataspace) { this.mColorSpace = colorSpace; this.mNativeDataspace = nativeDataspace; } static Optional<Dataspace> find(ColorSpace colorSpace) { return Stream.of(Dataspace.values()) .filter(d -> ColorSpace.get(d.mColorSpace).equals(colorSpace)) .findFirst(); } } private boolean mInitialized = false; private boolean mDisplayInitialized = false; Loading Loading @@ -1296,6 +1280,7 @@ public class HardwareRenderer { initDisplayInfo(); nSetIsHighEndGfx(ActivityManager.isHighEndGfx()); nSetIsLowRam(ActivityManager.isLowRamDeviceStatic()); // Defensively clear out the context in case we were passed a context that can leak // if we live longer than it, e.g. an activity context. mContext = null; Loading @@ -1314,26 +1299,55 @@ public class HardwareRenderer { return; } Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); if (display == null) { final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY); if (defaultDisplay == null) { Log.d(LOG_TAG, "Failed to find default display for display-based configuration"); return; } Dataspace wideColorDataspace = Optional.ofNullable(display.getPreferredWideGamutColorSpace()) .flatMap(Dataspace::find) // Default to SRGB if the display doesn't support wide color .orElse(Dataspace.SRGB); final Display[] allDisplays = dm.getDisplays(); if (allDisplays.length == 0) { Log.d(LOG_TAG, "Failed to query displays"); return; } final Mode activeMode = defaultDisplay.getMode(); final ColorSpace defaultWideColorSpace = defaultDisplay.getPreferredWideGamutColorSpace(); int wideColorDataspace = defaultWideColorSpace != null ? defaultWideColorSpace.getDataSpace() : 0; // largest width & height are used to size the default HWUI cache sizes. So find the // largest display resolution we could encounter & use that as the guidance. The actual // memory policy in play will interpret these values differently. int largestWidth = activeMode.getPhysicalWidth(); int largestHeight = activeMode.getPhysicalHeight(); for (int i = 0; i < allDisplays.length; i++) { final Display display = allDisplays[i]; // Take the first wide gamut dataspace as the source of truth // Possibly should do per-HardwareRenderer wide gamut dataspace so we can use the // target display's ideal instead if (wideColorDataspace == 0) { ColorSpace cs = display.getPreferredWideGamutColorSpace(); if (cs != null) { wideColorDataspace = cs.getDataSpace(); } } Mode[] modes = display.getSupportedModes(); for (int j = 0; j < modes.length; j++) { Mode mode = modes[j]; int width = mode.getPhysicalWidth(); int height = mode.getPhysicalHeight(); if ((width * height) > (largestWidth * largestHeight)) { largestWidth = width; largestHeight = height; } } } // Grab the physical screen dimensions from the active display mode // Strictly speaking the screen resolution may not always be constant - it is for // sizing the font cache for the underlying rendering thread. Since it's a // heuristic we don't need to be always 100% correct. Mode activeMode = display.getMode(); nInitDisplayInfo(activeMode.getPhysicalWidth(), activeMode.getPhysicalHeight(), display.getRefreshRate(), wideColorDataspace.mNativeDataspace, display.getAppVsyncOffsetNanos(), display.getPresentationDeadlineNanos()); nInitDisplayInfo(largestWidth, largestHeight, defaultDisplay.getRefreshRate(), wideColorDataspace, defaultDisplay.getAppVsyncOffsetNanos(), defaultDisplay.getPresentationDeadlineNanos()); mDisplayInitialized = true; } Loading Loading @@ -1418,6 +1432,10 @@ public class HardwareRenderer { private static native void nSetIsHighEndGfx(boolean isHighEndGfx); private static native void nSetIsLowRam(boolean isLowRam); private static native void nSetIsSystemOrPersistent(boolean isSystemOrPersistent); private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); private static native void nDestroy(long nativeProxy, long rootRenderNode); Loading Loading
core/java/android/app/ActivityThread.java +3 −0 Original line number Diff line number Diff line Loading @@ -6662,6 +6662,9 @@ public final class ActivityThread extends ClientTransactionHandler // Pass the current context to HardwareRenderer HardwareRenderer.setContextForInit(getSystemContext()); if (data.persistent) { HardwareRenderer.setIsSystemOrPersistent(); } // Instrumentation info affects the class loader, so load it before // setting up the app context. Loading
core/java/android/view/ThreadedRenderer.java +3 −5 Original line number Diff line number Diff line Loading @@ -196,8 +196,6 @@ public final class ThreadedRenderer extends HardwareRenderer { */ public static boolean sRendererEnabled = true; public static boolean sTrimForeground = false; /** * Controls whether or not the renderer should aggressively trim * memory. Note that this must not be set for any process that uses Loading @@ -205,9 +203,10 @@ public final class ThreadedRenderer extends HardwareRenderer { * that do not go into the background. */ public static void enableForegroundTrimming() { sTrimForeground = true; // TODO: Remove } /** * Initialize HWUI for being in a system process like system_server * Should not be called in non-system processes Loading @@ -218,9 +217,8 @@ public final class ThreadedRenderer extends HardwareRenderer { // process. if (!ActivityManager.isHighEndGfx()) { sRendererEnabled = false; } else { enableForegroundTrimming(); } setIsSystemOrPersistent(); } /** Loading
core/java/android/view/ViewRootImpl.java +0 −3 Original line number Diff line number Diff line Loading @@ -1766,9 +1766,6 @@ public final class ViewRootImpl implements ViewParent, mAppVisibilityChanged = true; scheduleTraversals(); } if (!mAppVisible) { WindowManagerGlobal.trimForeground(); } AnimationHandler.requestAnimatorsEnabled(mAppVisible, this); } } Loading
core/java/android/view/WindowManagerGlobal.java +0 −61 Original line number Diff line number Diff line Loading @@ -19,9 +19,7 @@ package android.view; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; Loading Loading @@ -524,9 +522,6 @@ public final class WindowManagerGlobal { } allViewsRemoved = mRoots.isEmpty(); } if (ThreadedRenderer.sTrimForeground) { doTrimForeground(); } // If we don't have any views anymore in our process, we no longer need the // InsetsAnimationThread to save some resources. Loading @@ -543,65 +538,9 @@ public final class WindowManagerGlobal { return index; } public static boolean shouldDestroyEglContext(int trimLevel) { // On low-end gfx devices we trim when memory is moderate; // on high-end devices we do this when low. if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { return true; } if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_MODERATE && !ActivityManager.isHighEndGfx()) { return true; } return false; } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void trimMemory(int level) { if (shouldDestroyEglContext(level)) { // Destroy all hardware surfaces and resources associated to // known windows synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { mRoots.get(i).destroyHardwareResources(); } } // Force a full memory flush level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; } ThreadedRenderer.trimMemory(level); if (ThreadedRenderer.sTrimForeground) { doTrimForeground(); } } public static void trimForeground() { if (ThreadedRenderer.sTrimForeground) { WindowManagerGlobal wm = WindowManagerGlobal.getInstance(); wm.doTrimForeground(); } } private void doTrimForeground() { boolean hasVisibleWindows = false; synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { final ViewRootImpl root = mRoots.get(i); if (root.mView != null && root.getHostVisibility() == View.VISIBLE && root.mAttachInfo.mThreadedRenderer != null) { hasVisibleWindows = true; } else { root.destroyHardwareResources(); } } } if (!hasVisibleWindows) { ThreadedRenderer.trimMemory( ComponentCallbacks2.TRIM_MEMORY_COMPLETE); } } public void dumpGfxInfo(FileDescriptor fd, String[] args) { Loading
graphics/java/android/graphics/HardwareRenderer.java +60 −42 Original line number Diff line number Diff line Loading @@ -47,9 +47,7 @@ import java.io.File; import java.io.FileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Optional; import java.util.concurrent.Executor; import java.util.stream.Stream; import sun.misc.Cleaner; Loading Loading @@ -1141,6 +1139,16 @@ public class HardwareRenderer { ProcessInitializer.sInstance.setContext(context); } /** * Sets whether or not the current process is a system or persistent process. Used to influence * the chosen memory usage policy. * * @hide **/ public static void setIsSystemOrPersistent() { nSetIsSystemOrPersistent(true); } /** * Returns true if HardwareRender will produce output. * Loading Loading @@ -1204,30 +1212,6 @@ public class HardwareRenderer { private static class ProcessInitializer { static ProcessInitializer sInstance = new ProcessInitializer(); // Magic values from android/data_space.h private static final int INTERNAL_DATASPACE_SRGB = 142671872; private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696; private static final int INTERNAL_DATASPACE_SCRGB = 411107328; private enum Dataspace { DISPLAY_P3(ColorSpace.Named.DISPLAY_P3, INTERNAL_DATASPACE_DISPLAY_P3), SCRGB(ColorSpace.Named.EXTENDED_SRGB, INTERNAL_DATASPACE_SCRGB), SRGB(ColorSpace.Named.SRGB, INTERNAL_DATASPACE_SRGB); private final ColorSpace.Named mColorSpace; private final int mNativeDataspace; Dataspace(ColorSpace.Named colorSpace, int nativeDataspace) { this.mColorSpace = colorSpace; this.mNativeDataspace = nativeDataspace; } static Optional<Dataspace> find(ColorSpace colorSpace) { return Stream.of(Dataspace.values()) .filter(d -> ColorSpace.get(d.mColorSpace).equals(colorSpace)) .findFirst(); } } private boolean mInitialized = false; private boolean mDisplayInitialized = false; Loading Loading @@ -1296,6 +1280,7 @@ public class HardwareRenderer { initDisplayInfo(); nSetIsHighEndGfx(ActivityManager.isHighEndGfx()); nSetIsLowRam(ActivityManager.isLowRamDeviceStatic()); // Defensively clear out the context in case we were passed a context that can leak // if we live longer than it, e.g. an activity context. mContext = null; Loading @@ -1314,26 +1299,55 @@ public class HardwareRenderer { return; } Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); if (display == null) { final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY); if (defaultDisplay == null) { Log.d(LOG_TAG, "Failed to find default display for display-based configuration"); return; } Dataspace wideColorDataspace = Optional.ofNullable(display.getPreferredWideGamutColorSpace()) .flatMap(Dataspace::find) // Default to SRGB if the display doesn't support wide color .orElse(Dataspace.SRGB); final Display[] allDisplays = dm.getDisplays(); if (allDisplays.length == 0) { Log.d(LOG_TAG, "Failed to query displays"); return; } final Mode activeMode = defaultDisplay.getMode(); final ColorSpace defaultWideColorSpace = defaultDisplay.getPreferredWideGamutColorSpace(); int wideColorDataspace = defaultWideColorSpace != null ? defaultWideColorSpace.getDataSpace() : 0; // largest width & height are used to size the default HWUI cache sizes. So find the // largest display resolution we could encounter & use that as the guidance. The actual // memory policy in play will interpret these values differently. int largestWidth = activeMode.getPhysicalWidth(); int largestHeight = activeMode.getPhysicalHeight(); for (int i = 0; i < allDisplays.length; i++) { final Display display = allDisplays[i]; // Take the first wide gamut dataspace as the source of truth // Possibly should do per-HardwareRenderer wide gamut dataspace so we can use the // target display's ideal instead if (wideColorDataspace == 0) { ColorSpace cs = display.getPreferredWideGamutColorSpace(); if (cs != null) { wideColorDataspace = cs.getDataSpace(); } } Mode[] modes = display.getSupportedModes(); for (int j = 0; j < modes.length; j++) { Mode mode = modes[j]; int width = mode.getPhysicalWidth(); int height = mode.getPhysicalHeight(); if ((width * height) > (largestWidth * largestHeight)) { largestWidth = width; largestHeight = height; } } } // Grab the physical screen dimensions from the active display mode // Strictly speaking the screen resolution may not always be constant - it is for // sizing the font cache for the underlying rendering thread. Since it's a // heuristic we don't need to be always 100% correct. Mode activeMode = display.getMode(); nInitDisplayInfo(activeMode.getPhysicalWidth(), activeMode.getPhysicalHeight(), display.getRefreshRate(), wideColorDataspace.mNativeDataspace, display.getAppVsyncOffsetNanos(), display.getPresentationDeadlineNanos()); nInitDisplayInfo(largestWidth, largestHeight, defaultDisplay.getRefreshRate(), wideColorDataspace, defaultDisplay.getAppVsyncOffsetNanos(), defaultDisplay.getPresentationDeadlineNanos()); mDisplayInitialized = true; } Loading Loading @@ -1418,6 +1432,10 @@ public class HardwareRenderer { private static native void nSetIsHighEndGfx(boolean isHighEndGfx); private static native void nSetIsLowRam(boolean isLowRam); private static native void nSetIsSystemOrPersistent(boolean isSystemOrPersistent); private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); private static native void nDestroy(long nativeProxy, long rootRenderNode); Loading