diff options
author | Romain Guy <romainguy@google.com> | 2011-07-27 18:51:50 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2011-07-27 18:51:50 -0700 |
commit | 65b345fa22b878e141b8fd8ece9c208df00fa40f (patch) | |
tree | 587ba028a74320da19f8eeddbd4a2fb377e68cb4 | |
parent | 6d7475d666baefaa3ba9f0dcee25238739454241 (diff) | |
download | frameworks_base-65b345fa22b878e141b8fd8ece9c208df00fa40f.zip frameworks_base-65b345fa22b878e141b8fd8ece9c208df00fa40f.tar.gz frameworks_base-65b345fa22b878e141b8fd8ece9c208df00fa40f.tar.bz2 |
Reclaim more memory, more often.
Yay.
Change-Id: I04557ad575c307a55088549f48f0e9ad994b7275
-rw-r--r-- | core/java/android/app/ActivityThread.java | 120 | ||||
-rw-r--r-- | core/java/android/view/DisplayList.java | 7 | ||||
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 6 | ||||
-rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 6 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 4 | ||||
-rw-r--r-- | core/java/android/view/View.java | 6 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 2 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 53 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 58 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 4 | ||||
-rw-r--r-- | libs/hwui/LayerCache.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 2 |
15 files changed, 224 insertions, 78 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9bbbd6c..1e93f88 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -123,7 +123,6 @@ public final class ActivityThread { /** @hide */ public static final String TAG = "ActivityThread"; private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565; - private static final boolean DEBUG = false; static final boolean localLOGV = false; static final boolean DEBUG_MESSAGES = false; /** @hide */ @@ -163,7 +162,7 @@ public final class ActivityThread { = new ArrayList<Application>(); // set of instantiated backup agents, keyed by package name final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>(); - static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal(); + static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>(); Instrumentation mInstrumentation; String mInstrumentationAppDir = null; String mInstrumentationAppPackage = null; @@ -410,9 +409,9 @@ public final class ActivityThread { CompatibilityInfo info; } - native private void dumpGraphicsInfo(FileDescriptor fd); + private native void dumpGraphicsInfo(FileDescriptor fd); - private final class ApplicationThread extends ApplicationThreadNative { + private class ApplicationThread extends ApplicationThreadNative { private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s"; private static final String ONE_COUNT_COLUMN = "%21s %8d"; private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d"; @@ -734,13 +733,13 @@ public final class ActivityThread { FileOutputStream fout = new FileOutputStream(fd); PrintWriter pw = new PrintWriter(fout); try { - return dumpMemInfo(fd, pw, args); + return dumpMemInfo(pw, args); } finally { pw.flush(); } } - private Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, PrintWriter pw, String[] args) { + private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, String[] args) { long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; @@ -754,7 +753,7 @@ public final class ActivityThread { long dalvikFree = runtime.freeMemory() / 1024; long dalvikAllocated = dalvikMax - dalvikFree; long viewInstanceCount = ViewDebug.getViewInstanceCount(); - long viewRootInstanceCount = ViewDebug.getViewAncestorInstanceCount(); + long viewRootInstanceCount = ViewDebug.getViewRootImplCount(); long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class); long activityInstanceCount = Debug.countInstancesOfClass(Activity.class); int globalAssetCount = AssetManager.getGlobalAssetCount(); @@ -868,7 +867,7 @@ public final class ActivityThread { int otherPrivateDirty = memInfo.otherPrivateDirty; for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { - printRow(pw, HEAP_COLUMN, memInfo.getOtherLabel(i), + printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i), memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i), memInfo.getOtherPrivateDirty(i), "", "", ""); otherPss -= memInfo.getOtherPss(i); @@ -885,7 +884,7 @@ public final class ActivityThread { pw.println(" "); pw.println(" Objects"); - printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewAncestors:", + printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:", viewRootInstanceCount); printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount, @@ -937,6 +936,7 @@ public final class ActivityThread { @Override public void dumpGfxInfo(FileDescriptor fd, String[] args) { dumpGraphicsInfo(fd); + WindowManagerImpl.getDefault().dumpGfxInfo(fd); } private void printRow(PrintWriter pw, String format, Object...objs) { @@ -959,7 +959,7 @@ public final class ActivityThread { } } - private final class H extends Handler { + private class H extends Handler { public static final int LAUNCH_ACTIVITY = 100; public static final int PAUSE_ACTIVITY = 101; public static final int PAUSE_ACTIVITY_FINISHING= 102; @@ -1220,7 +1220,7 @@ public final class ActivityThread { } } - private final class Idler implements MessageQueue.IdleHandler { + private class Idler implements MessageQueue.IdleHandler { public final boolean queueIdle() { ActivityClientRecord a = mNewActivities; if (a != null) { @@ -1231,12 +1231,13 @@ public final class ActivityThread { if (localLOGV) Slog.v( TAG, "Reporting idle of " + a + " finished=" + - (a.activity != null ? a.activity.mFinished : false)); + (a.activity != null && a.activity.mFinished)); if (a.activity != null && !a.activity.mFinished) { try { am.activityIdle(a.token, a.createdConfig); a.createdConfig = null; } catch (RemoteException ex) { + // Ignore } } prev = a; @@ -1256,7 +1257,7 @@ public final class ActivityThread { } } - private final static class ResourcesKey { + private static class ResourcesKey { final private String mResDir; final private float mScale; final private int mHash; @@ -1282,17 +1283,17 @@ public final class ActivityThread { } } - public static final ActivityThread currentActivityThread() { + public static ActivityThread currentActivityThread() { return sThreadLocal.get(); } - public static final String currentPackageName() { + public static String currentPackageName() { ActivityThread am = currentActivityThread(); return (am != null && am.mBoundApplication != null) ? am.mBoundApplication.processName : null; } - public static final Application currentApplication() { + public static Application currentApplication() { ActivityThread am = currentActivityThread(); return am != null ? am.mInitialApplication : null; } @@ -1337,7 +1338,7 @@ public final class ActivityThread { return config; } - private final Configuration mMainThreadConfig = new Configuration(); + private Configuration mMainThreadConfig = new Configuration(); Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) { if (config == null) { return null; @@ -1456,6 +1457,7 @@ public final class ActivityThread { ai = getPackageManager().getApplicationInfo(packageName, PackageManager.GET_SHARED_LIBRARY_FILES); } catch (RemoteException e) { + // Ignore } if (ai != null) { @@ -1505,7 +1507,7 @@ public final class ActivityThread { } } - private final LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, + private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode) { synchronized (mPackages) { WeakReference<LoadedApk> ref; @@ -1712,15 +1714,15 @@ public final class ActivityThread { // if the thread hasn't started yet, we don't have the handler, so just // save the messages until we're ready. - private final void queueOrSendMessage(int what, Object obj) { + private void queueOrSendMessage(int what, Object obj) { queueOrSendMessage(what, obj, 0, 0); } - private final void queueOrSendMessage(int what, Object obj, int arg1) { + private void queueOrSendMessage(int what, Object obj, int arg1) { queueOrSendMessage(what, obj, arg1, 0); } - private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { + private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { synchronized (this) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) @@ -1743,7 +1745,7 @@ public final class ActivityThread { queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci); } - private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { + private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); ActivityInfo aInfo = r.activityInfo; @@ -1861,7 +1863,7 @@ public final class ActivityThread { return activity; } - private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { + private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -1917,11 +1919,12 @@ public final class ActivityThread { ActivityManagerNative.getDefault() .finishActivity(r.token, Activity.RESULT_CANCELED, null); } catch (RemoteException ex) { + // Ignore } } } - private final void deliverNewIntents(ActivityClientRecord r, + private void deliverNewIntents(ActivityClientRecord r, List<Intent> intents) { final int N = intents.size(); for (int i=0; i<N; i++) { @@ -1949,7 +1952,7 @@ public final class ActivityThread { } } - private final void handleNewIntent(NewIntentData data) { + private void handleNewIntent(NewIntentData data) { performNewIntents(data.token, data.intents); } @@ -1964,7 +1967,7 @@ public final class ActivityThread { return sCurrentBroadcastIntent.get(); } - private final void handleReceiver(ReceiverData data) { + private void handleReceiver(ReceiverData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -1976,7 +1979,7 @@ public final class ActivityThread { IActivityManager mgr = ActivityManagerNative.getDefault(); - BroadcastReceiver receiver = null; + BroadcastReceiver receiver; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); data.intent.setExtrasClassLoader(cl); @@ -2026,7 +2029,7 @@ public final class ActivityThread { } // Instantiate a BackupAgent and tell it that it's alive - private final void handleCreateBackupAgent(CreateBackupAgentData data) { + private void handleCreateBackupAgent(CreateBackupAgentData data) { if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data); // no longer idle; we have backup work to do @@ -2091,7 +2094,7 @@ public final class ActivityThread { } // Tear down a BackupAgent - private final void handleDestroyBackupAgent(CreateBackupAgentData data) { + private void handleDestroyBackupAgent(CreateBackupAgentData data) { if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data); LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo); @@ -2110,7 +2113,7 @@ public final class ActivityThread { } } - private final void handleCreateService(CreateServiceData data) { + private void handleCreateService(CreateServiceData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -2156,7 +2159,7 @@ public final class ActivityThread { } } - private final void handleBindService(BindServiceData data) { + private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { try { @@ -2184,7 +2187,7 @@ public final class ActivityThread { } } - private final void handleUnbindService(BindServiceData data) { + private void handleUnbindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { try { @@ -2236,7 +2239,7 @@ public final class ActivityThread { } } - private final void handleServiceArgs(ServiceArgsData data) { + private void handleServiceArgs(ServiceArgsData data) { Service s = mServices.get(data.token); if (s != null) { try { @@ -2270,7 +2273,7 @@ public final class ActivityThread { } } - private final void handleStopService(IBinder token) { + private void handleStopService(IBinder token) { Service s = mServices.remove(token); if (s != null) { try { @@ -2465,7 +2468,7 @@ public final class ActivityThread { private Bitmap mAvailThumbnailBitmap = null; private Canvas mThumbnailCanvas = null; - private final Bitmap createThumbnailBitmap(ActivityClientRecord r) { + private Bitmap createThumbnailBitmap(ActivityClientRecord r) { Bitmap thumbnail = mAvailThumbnailBitmap; try { if (thumbnail == null) { @@ -2515,7 +2518,7 @@ public final class ActivityThread { return thumbnail; } - private final void handlePauseActivity(IBinder token, boolean finished, + private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) { ActivityClientRecord r = mActivities.get(token); if (r != null) { @@ -2621,7 +2624,7 @@ public final class ActivityThread { CharSequence description; } - private final class ProviderRefCount { + private class ProviderRefCount { public int count; ProviderRefCount(int pCount) { count = pCount; @@ -2636,7 +2639,7 @@ public final class ActivityThread { * For the client, we want to call onStop()/onStart() to indicate when * the activity's UI visibillity changes. */ - private final void performStopActivityInner(ActivityClientRecord r, + private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown, boolean saveState) { if (localLOGV) Slog.v(TAG, "Performing stop of " + r); Bundle state = null; @@ -2699,7 +2702,7 @@ public final class ActivityThread { } } - private final void updateVisibility(ActivityClientRecord r, boolean show) { + private void updateVisibility(ActivityClientRecord r, boolean show) { View v = r.activity.mDecor; if (v != null) { if (show) { @@ -2726,7 +2729,7 @@ public final class ActivityThread { } } - private final void handleStopActivity(IBinder token, boolean show, int configChanges) { + private void handleStopActivity(IBinder token, boolean show, int configChanges) { ActivityClientRecord r = mActivities.get(token); r.activity.mConfigChangeFlags |= configChanges; @@ -2760,7 +2763,7 @@ public final class ActivityThread { } } - private final void handleWindowVisibility(IBinder token, boolean show) { + private void handleWindowVisibility(IBinder token, boolean show) { ActivityClientRecord r = mActivities.get(token); if (r == null) { @@ -2785,7 +2788,7 @@ public final class ActivityThread { } } - private final void handleSleeping(IBinder token, boolean sleeping) { + private void handleSleeping(IBinder token, boolean sleeping) { ActivityClientRecord r = mActivities.get(token); if (r == null) { @@ -2846,7 +2849,7 @@ public final class ActivityThread { WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration); } - private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) { + private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) { final int N = results.size(); for (int i=0; i<N; i++) { ResultInfo ri = results.get(i); @@ -2869,7 +2872,7 @@ public final class ActivityThread { } } - private final void handleSendResult(ResultData res) { + private void handleSendResult(ResultData res) { ActivityClientRecord r = mActivities.get(res.token); if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r); if (r != null) { @@ -2915,7 +2918,7 @@ public final class ActivityThread { return performDestroyActivity(token, finishing, 0, false); } - private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, + private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityClientRecord r = mActivities.get(token); Class activityClass = null; @@ -3008,7 +3011,7 @@ public final class ActivityThread { return component == null ? "[Unknown]" : component.toShortString(); } - private final void handleDestroyActivity(IBinder token, boolean finishing, + private void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityClientRecord r = performDestroyActivity(token, finishing, configChanges, getNonConfigInstance); @@ -3123,7 +3126,7 @@ public final class ActivityThread { } } - private final void handleRelaunchActivity(ActivityClientRecord tmp) { + private void handleRelaunchActivity(ActivityClientRecord tmp) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -3233,7 +3236,7 @@ public final class ActivityThread { handleLaunchActivity(r, currentIntent); } - private final void handleRequestThumbnail(IBinder token) { + private void handleRequestThumbnail(IBinder token) { ActivityClientRecord r = mActivities.get(token); Bitmap thumbnail = createThumbnailBitmap(r); CharSequence description = null; @@ -3308,7 +3311,7 @@ public final class ActivityThread { return callbacks; } - private final void performConfigurationChanged( + private void performConfigurationChanged( ComponentCallbacks cb, Configuration config) { // Only for Activity objects, check that they actually call up to their // superclass implementation. ComponentCallbacks is an interface, so @@ -3451,6 +3454,9 @@ public final class ActivityThread { } callbacks = collectComponentCallbacksLocked(false, config); } + + // Cleanup hardware accelerated stuff + WindowManagerImpl.getDefault().trimLocalMemory(); if (callbacks != null) { final int N = callbacks.size(); @@ -3579,7 +3585,7 @@ public final class ActivityThread { WindowManagerImpl.getDefault().trimMemory(level); } - private final void handleBindApplication(AppBindData data) { + private void handleBindApplication(AppBindData data) { mBoundApplication = data; mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); @@ -3791,7 +3797,7 @@ public final class ActivityThread { } } - private final void installContentProviders( + private void installContentProviders( Context context, List<ProviderInfo> providers) { final ArrayList<IActivityManager.ContentProviderHolder> results = new ArrayList<IActivityManager.ContentProviderHolder>(); @@ -3825,7 +3831,7 @@ public final class ActivityThread { } } - private final IContentProvider getExistingProvider(Context context, String name) { + private IContentProvider getExistingProvider(Context context, String name) { synchronized(mProviderMap) { final ProviderClientRecord pr = mProviderMap.get(name); if (pr != null) { @@ -3835,7 +3841,7 @@ public final class ActivityThread { } } - private final IContentProvider getProvider(Context context, String name) { + private IContentProvider getProvider(Context context, String name) { IContentProvider existing = getExistingProvider(context, name); if (existing != null) { return existing; @@ -4007,7 +4013,7 @@ public final class ActivityThread { } } - private final IContentProvider installProvider(Context context, + private IContentProvider installProvider(Context context, IContentProvider provider, ProviderInfo info, boolean noisy) { ContentProvider localProvider = null; if (provider == null) { @@ -4027,6 +4033,7 @@ public final class ActivityThread { c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { + // Ignore } } if (c == null) { @@ -4086,7 +4093,7 @@ public final class ActivityThread { return provider; } - private final void attach(boolean system) { + private void attach(boolean system) { sThreadLocal.set(this); mSystemThread = system; if (!system) { @@ -4101,6 +4108,7 @@ public final class ActivityThread { try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { + // Ignore } } else { // Don't set application object here -- if the system crashes, @@ -4166,7 +4174,7 @@ public final class ActivityThread { } } - public static final void main(String[] args) { + public static void main(String[] args) { SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index f4c0249..8f4ece0 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -54,4 +54,11 @@ public abstract class DisplayList { * @return boolean true if the display list is able to be replayed, false otherwise. */ abstract boolean isValid(); + + /** + * Return the amount of memory used by this display list. + * + * @return The size of this display list in bytes + */ + abstract int getSize(); } diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index ac0abc3..a7fe95d 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -330,6 +330,12 @@ class GLES20Canvas extends HardwareCanvas { private static native void nDestroyDisplayList(int displayList); + static int getDisplayListSize(int displayList) { + return nGetDisplayListSize(displayList); + } + + private static native int nGetDisplayListSize(int displayList); + @Override public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) { return nDrawDisplayList(mRenderer, diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index 9e649ce..4ca5e98 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -82,6 +82,12 @@ class GLES20DisplayList extends DisplayList { } } + @Override + int getSize() { + if (mFinalizer == null) return 0; + return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList); + } + private static class DisplayListFinalizer { final int mNativeDisplayList; diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 5404e3a..4e4923b 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -934,7 +934,9 @@ public abstract class HardwareRenderer { } private void destroyHardwareLayer(View view) { - view.destroyLayer(); + if (view.destroyLayer()) { + view.invalidate(true); + } if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 5b8a201..bfa525c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2294,8 +2294,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit private Bitmap mDrawingCache; private Bitmap mUnscaledDrawingCache; - private DisplayList mDisplayList; private HardwareLayer mHardwareLayer; + DisplayList mDisplayList; /** * When this view has focus and the next focus is {@link #FOCUS_LEFT}, @@ -9727,11 +9727,13 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit return mHardwareLayer; } - void destroyLayer() { + boolean destroyLayer() { if (mHardwareLayer != null) { mHardwareLayer.destroy(); mHardwareLayer = null; + return true; } + return false; } /** diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 4acf48c..96e550e 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -420,7 +420,7 @@ public class ViewDebug { * * @hide */ - public static long getViewAncestorInstanceCount() { + public static long getViewRootImplCount() { return Debug.countInstancesOfClass(ViewRootImpl.class); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 57bf17f..cddf41e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -80,6 +80,7 @@ import com.android.internal.view.RootViewSurfaceTaker; import java.io.IOException; import java.io.OutputStream; +import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -235,7 +236,6 @@ public final class ViewRootImpl extends Handler implements ViewParent, final Configuration mLastConfiguration = new Configuration(); final Configuration mPendingConfiguration = new Configuration(); - class ResizedInfo { Rect coveredInsets; Rect visibleInsets; @@ -542,10 +542,26 @@ public final class ViewRootImpl extends Handler implements ViewParent, } private void destroyHardwareResources() { - if (mAttachInfo.mHardwareRenderer.isEnabled()) { - mAttachInfo.mHardwareRenderer.destroyLayers(mView); + if (mAttachInfo.mHardwareRenderer != null) { + if (mAttachInfo.mHardwareRenderer.isEnabled()) { + mAttachInfo.mHardwareRenderer.destroyLayers(mView); + } + mAttachInfo.mHardwareRenderer.destroy(false); + } + } + + void destroyHardwareLayers() { + if (mThread != Thread.currentThread()) { + if (mAttachInfo.mHardwareRenderer != null && + mAttachInfo.mHardwareRenderer.isEnabled()) { + HardwareRenderer.trimMemory(ComponentCallbacks.TRIM_MEMORY_MODERATE); + } + } else { + if (mAttachInfo.mHardwareRenderer != null && + mAttachInfo.mHardwareRenderer.isEnabled()) { + mAttachInfo.mHardwareRenderer.destroyLayers(mView); + } } - mAttachInfo.mHardwareRenderer.destroy(false); } private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) { @@ -876,9 +892,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, attachInfo.mWindowVisibility = viewVisibility; host.dispatchWindowVisibilityChanged(viewVisibility); if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { - if (mAttachInfo.mHardwareRenderer != null) { - destroyHardwareResources(); - } + destroyHardwareResources(); } if (viewVisibility == View.GONE) { // After making a window gone, we will count it as being @@ -3492,6 +3506,31 @@ public final class ViewRootImpl extends Handler implements ViewParent, public void debug() { mView.debug(); } + + public void dumpGfxInfo(PrintWriter pw, int[] info) { + if (mView != null) { + getGfxInfo(mView, info); + } else { + info[0] = info[1] = 0; + } + } + + private void getGfxInfo(View view, int[] info) { + DisplayList displayList = view.mDisplayList; + info[0]++; + if (displayList != null) { + info[1] += displayList.getSize(); + } + + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + + int count = group.getChildCount(); + for (int i = 0; i < count; i++) { + getGfxInfo(group.getChildAt(i), info); + } + } + } public void die(boolean immediate) { if (immediate) { diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index a451bb5..5ef4f3e 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -24,6 +24,9 @@ import android.util.AndroidRuntimeException; import android.util.Log; import android.view.inputmethod.InputMethodManager; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.PrintWriter; import java.util.HashMap; final class WindowLeaked extends AndroidRuntimeException { @@ -392,7 +395,7 @@ public class WindowManagerImpl implements WindowManager { leak.setStackTrace(root.getLocation().getStackTrace()); Log.e("WindowManager", leak.getMessage(), leak); } - + removeViewLocked(i); i--; count--; @@ -410,6 +413,59 @@ public class WindowManagerImpl implements WindowManager { } } + /** + * @hide + */ + public void trimLocalMemory() { + synchronized (this) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].destroyHardwareLayers(); + } + } + } + + /** + * @hide + */ + public void dumpGfxInfo(FileDescriptor fd) { + FileOutputStream fout = new FileOutputStream(fd); + PrintWriter pw = new PrintWriter(fout); + try { + synchronized (this) { + if (mViews != null) { + pw.println("View hierarchy:"); + + final int count = mViews.length; + + int viewsCount = 0; + int displayListsSize = 0; + int[] info = new int[2]; + + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + root.dumpGfxInfo(pw, info); + + String name = root.getClass().getName() + '@' + + Integer.toHexString(hashCode()); + pw.printf(" %s: %d views, %.2f kB (display lists)\n", + name, info[0], info[1] / 1024.0f); + + viewsCount += info[0]; + displayListsSize += info[1]; + } + + pw.printf("\nTotal ViewRootImpl: %d\n", count); + pw.printf("Total Views: %d\n", viewsCount); + pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f); + } + } + } finally { + pw.flush(); + } + } + public void setStoppedState(IBinder token, boolean stopped) { synchronized (this) { if (mViews == null) diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index b06de9d..b3f2d51 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -580,6 +580,11 @@ static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env, return renderer->getDisplayList(displayList); } +static jint android_view_GLES20Canvas_getDisplayListSize(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getSize(); +} + static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) { return new DisplayListRenderer; @@ -721,8 +726,7 @@ static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz // ---------------------------------------------------------------------------- static void -android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) -{ +android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) { #ifdef USE_OPENGL_RENDERER int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); android::uirenderer::DisplayList::outputLogBuffer(fd); @@ -814,6 +818,7 @@ static JNINativeMethod gMethods[] = { { "nGetDisplayList", "(II)I", (void*) android_view_GLES20Canvas_getDisplayList }, { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList }, + { "nGetDisplayListSize", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListSize }, { "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer }, { "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer }, { "nDrawDisplayList", "(IIIILandroid/graphics/Rect;)Z", diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 886c05c..88cfc5a 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -74,12 +74,17 @@ void DisplayList::outputLogBuffer(int fd) { if (logBuffer.isEmpty()) { return; } - String8 cachesLog; - Caches::getInstance().dumpMemoryUsage(cachesLog); + FILE *file = fdopen(fd, "a"); - fprintf(file, "\nCaches:\n%s", cachesLog.string()); + fprintf(file, "\nRecent DisplayList operations\n"); logBuffer.outputCommands(file, OP_NAMES); + + String8 cachesLog; + Caches::getInstance().dumpMemoryUsage(cachesLog); + fprintf(file, "\nCaches:\n%s", cachesLog.string()); + fprintf(file, "\n"); + fflush(file); } @@ -143,10 +148,10 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde clearResources(); } - size_t size = writer.size(); - void* buffer = sk_malloc_throw(size); + mSize = writer.size(); + void* buffer = sk_malloc_throw(mSize); writer.flatten(buffer); - mReader.setMemory(buffer, size); + mReader.setMemory(buffer, mSize); Caches& caches = Caches::getInstance(); @@ -188,6 +193,11 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde } void DisplayList::init() { + mSize = 0; +} + +size_t DisplayList::getSize() { + return mSize; } /** diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index a3d346d..69e72a4 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -105,6 +105,8 @@ public: void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); + size_t getSize(); + bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0); void output(OpenGLRenderer& renderer, uint32_t level = 0); @@ -203,6 +205,8 @@ private: Vector<SkiaShader*> mShaders; mutable SkFlattenableReadBuffer mReader; + + size_t mSize; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 89c35da..0af0177 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -68,6 +68,7 @@ void LayerCache::setMaxSize(uint32_t maxSize) { void LayerCache::deleteLayer(Layer* layer) { if (layer) { + LAYER_LOGD("Destroying layer %dx%d", layer->getWidth(), layer->getHeight()); mSize -= layer->getWidth() * layer->getHeight() * 4; layer->deleteFbo(); layer->deleteTexture(); diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 81816f6..7e8c7fd 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -301,7 +301,7 @@ void LayerRenderer::destroyLayer(Layer* layer) { delete layer; } else { LAYER_RENDERER_LOGD(" Cached!"); -#if DEBUG_LAYERS +#if DEBUG_LAYER_RENDERER Caches::getInstance().layerCache.dump(); #endif layer->region.clear(); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 47049e2..923978f 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -68,7 +68,7 @@ enum DebugLevel { #define MB(s) s * 1024 * 1024 #define DEFAULT_TEXTURE_CACHE_SIZE 24.0f -#define DEFAULT_LAYER_CACHE_SIZE 24.0f +#define DEFAULT_LAYER_CACHE_SIZE 16.0f #define DEFAULT_PATH_CACHE_SIZE 4.0f #define DEFAULT_SHAPE_CACHE_SIZE 1.0f #define DEFAULT_PATCH_CACHE_SIZE 512 |