diff options
-rw-r--r-- | api/current.txt | 5 | ||||
-rw-r--r-- | core/java/android/app/ActivityManager.java | 33 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 25 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 10 | ||||
-rw-r--r-- | core/java/android/content/ComponentCallbacks2.java | 38 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 13 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 36 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 84 |
8 files changed, 181 insertions, 63 deletions
diff --git a/api/current.txt b/api/current.txt index c9be4cd..261d9ab 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2722,6 +2722,7 @@ package android.app { method public int getLauncherLargeIconSize(); method public int getMemoryClass(); method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo); + method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo); method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]); method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState(); method public java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException; @@ -2804,6 +2805,7 @@ package android.app { field public int importanceReasonCode; field public android.content.ComponentName importanceReasonComponent; field public int importanceReasonPid; + field public int lastTrimLevel; field public int lru; field public int pid; field public java.lang.String[] pkgList; @@ -4826,6 +4828,9 @@ package android.content { field public static final int TRIM_MEMORY_BACKGROUND = 40; // 0x28 field public static final int TRIM_MEMORY_COMPLETE = 80; // 0x50 field public static final int TRIM_MEMORY_MODERATE = 60; // 0x3c + field public static final int TRIM_MEMORY_RUNNING_CRITICAL = 15; // 0xf + field public static final int TRIM_MEMORY_RUNNING_LOW = 10; // 0xa + field public static final int TRIM_MEMORY_RUNNING_MODERATE = 5; // 0x5 field public static final int TRIM_MEMORY_UI_HIDDEN = 20; // 0x14 } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index d98d87b..59c803e 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1145,7 +1145,14 @@ public class ActivityManager { * @hide */ public int flags; - + + /** + * Last memory trim level reported to the process: corresponds to + * the values supplied to {@link android.content.ComponentCallbacks2#onTrimMemory(int) + * ComponentCallbacks2.onTrimMemory(int)}. + */ + public int lastTrimLevel; + /** * Constant for {@link #importance}: this process is running the * foreground UI. @@ -1212,7 +1219,7 @@ public class ActivityManager { * be maintained in the future. */ public int lru; - + /** * Constant for {@link #importanceReasonCode}: nothing special has * been specified for the reason for this level. @@ -1282,6 +1289,7 @@ public class ActivityManager { dest.writeInt(uid); dest.writeStringArray(pkgList); dest.writeInt(this.flags); + dest.writeInt(lastTrimLevel); dest.writeInt(importance); dest.writeInt(lru); dest.writeInt(importanceReasonCode); @@ -1296,6 +1304,7 @@ public class ActivityManager { uid = source.readInt(); pkgList = source.readStringArray(); flags = source.readInt(); + lastTrimLevel = source.readInt(); importance = source.readInt(); lru = source.readInt(); importanceReasonCode = source.readInt(); @@ -1349,7 +1358,25 @@ public class ActivityManager { return null; } } - + + /** + * Return global memory state information for the calling process. This + * does not fill in all fields of the {@link RunningAppProcessInfo}. The + * only fields that will be filled in are + * {@link RunningAppProcessInfo#pid}, + * {@link RunningAppProcessInfo#uid}, + * {@link RunningAppProcessInfo#lastTrimLevel}, + * {@link RunningAppProcessInfo#importance}, + * {@link RunningAppProcessInfo#lru}, and + * {@link RunningAppProcessInfo#importanceReasonCode}. + */ + static public void getMyMemoryState(RunningAppProcessInfo outState) { + try { + ActivityManagerNative.getDefault().getMyMemoryState(outState); + } catch (RemoteException e) { + } + } + /** * Return information about the memory usage of one or more processes. * diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 24079a5..b952649 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1126,7 +1126,17 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } - + + case GET_MY_MEMORY_STATE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + ActivityManager.RunningAppProcessInfo info = + new ActivityManager.RunningAppProcessInfo(); + getMyMemoryState(info); + reply.writeNoException(); + info.writeToParcel(reply, 0); + return true; + } + case GET_DEVICE_CONFIGURATION_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); ConfigurationInfo config = getDeviceConfigurationInfo(); @@ -2973,6 +2983,19 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) + throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(GET_MY_MEMORY_STATE_TRANSACTION, data, reply, 0); + reply.readException(); + outInfo.readFromParcel(reply); + reply.recycle(); + data.recycle(); + } + public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 53a71db..ea2545f 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -278,13 +278,16 @@ public interface IActivityManager extends IInterface { * SIGUSR1 is delivered. All others are ignored. */ public void signalPersistentProcesses(int signal) throws RemoteException; - // Retrieve info of applications installed on external media that are currently - // running. + // Retrieve running application processes in the system public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() throws RemoteException; - // Retrieve running application processes in the system + // Retrieve info of applications installed on external media that are currently + // running. public List<ApplicationInfo> getRunningExternalApplications() throws RemoteException; + // Get memory information about the calling process. + public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) + throws RemoteException; // Get device configuration public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException; @@ -606,4 +609,5 @@ public interface IActivityManager extends IInterface { int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139; int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140; int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141; + int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142; } diff --git a/core/java/android/content/ComponentCallbacks2.java b/core/java/android/content/ComponentCallbacks2.java index 8b9f97c..85294dd 100644 --- a/core/java/android/content/ComponentCallbacks2.java +++ b/core/java/android/content/ComponentCallbacks2.java @@ -52,15 +52,49 @@ public interface ComponentCallbacks2 extends ComponentCallbacks { static final int TRIM_MEMORY_UI_HIDDEN = 20; /** + * Level for {@link #onTrimMemory(int)}: the process is not an expendable + * background process, but the device is running extremely low on memory + * and is about to not be able to keep any background processes running. + * Your running process should free up as many non-critical resources as it + * can to allow that memory to be used elsewhere. The next thing that + * will happen after this is {@link #onLowMemory()} called to report that + * nothing at all can be kept in the background, a situation that can start + * to notably impact the user. + */ + static final int TRIM_MEMORY_RUNNING_CRITICAL = 15; + + /** + * Level for {@link #onTrimMemory(int)}: the process is not an expendable + * background process, but the device is running low on memory. + * Your running process should free up unneeded resources to allow that + * memory to be used elsewhere. + */ + static final int TRIM_MEMORY_RUNNING_LOW = 10; + + + /** + * Level for {@link #onTrimMemory(int)}: the process is not an expendable + * background process, but the device is running moderately low on memory. + * Your running process may want to release some unneeded resources for + * use elsewhere. + */ + static final int TRIM_MEMORY_RUNNING_MODERATE = 5; + + /** * Called when the operating system has determined that it is a good * time for a process to trim unneeded memory from its process. This will * happen for example when it goes in the background and there is not enough - * memory to keep as many background processes running as desired. + * memory to keep as many background processes running as desired. You + * should never compare to exact values of the level, since new intermediate + * values may be added -- you will typically want to compare if the value + * is greater or equal to a level you are interested in. * * @param level The context of the trim, giving a hint of the amount of * trimming the application may like to perform. May be * {@link #TRIM_MEMORY_COMPLETE}, {@link #TRIM_MEMORY_MODERATE}, - * {@link #TRIM_MEMORY_BACKGROUND}, or {@link #TRIM_MEMORY_UI_HIDDEN}. + * {@link #TRIM_MEMORY_BACKGROUND}, {@link #TRIM_MEMORY_UI_HIDDEN}, + * {@link #TRIM_MEMORY_RUNNING_CRITICAL}, {@link #TRIM_MEMORY_RUNNING_LOW}, + * or {@link #TRIM_MEMORY_RUNNING_MODERATE}. */ void onTrimMemory(int level); } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index ec95863..bf91700 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -1284,15 +1284,10 @@ public abstract class HardwareRenderer { usePbufferSurface(managedContext.getContext()); } - switch (level) { - case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: - case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: - case ComponentCallbacks2.TRIM_MEMORY_MODERATE: - GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE); - break; - case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: - GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL); - break; + if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL); + } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE); } } diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index d482b35..0e4a30f 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -432,29 +432,25 @@ public class WindowManagerImpl implements WindowManager { */ public void trimMemory(int level) { if (HardwareRenderer.isAvailable()) { - switch (level) { - case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: - case ComponentCallbacks2.TRIM_MEMORY_MODERATE: - // On low and medium end gfx devices - if (!ActivityManager.isHighEndGfx(getDefaultDisplay())) { - // Destroy all hardware surfaces and resources associated to - // known windows - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; - for (int i = 0; i < count; i++) { - mRoots[i].terminateHardwareResources(); - } + // On low and medium end gfx devices + if (!ActivityManager.isHighEndGfx(getDefaultDisplay())) { + if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { + // Destroy all hardware surfaces and resources associated to + // known windows + synchronized (this) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].terminateHardwareResources(); } - // Force a full memory flush - HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); - mNeedsEglTerminate = true; - break; } - // high end gfx devices fall through to next case - default: - HardwareRenderer.trimMemory(level); + // Force a full memory flush + HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); + mNeedsEglTerminate = true; + return; + } } + HardwareRenderer.trimMemory(level); } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 3ac446c..4ea2f04 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7952,6 +7952,22 @@ public final class ActivityManagerService extends ActivityManagerNative } } + private void fillInProcMemInfo(ProcessRecord app, + ActivityManager.RunningAppProcessInfo outInfo) { + outInfo.pid = app.pid; + outInfo.uid = app.info.uid; + if (mHeavyWeightProcess == app) { + outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE; + } + if (app.persistent) { + outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT; + } + outInfo.lastTrimLevel = app.trimMemoryLevel; + int adj = app.curAdj; + outInfo.importance = oomAdjToImportance(adj, outInfo); + outInfo.importanceReasonCode = app.adjTypeCode; + } + public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() { enforceNotIsolatedCaller("getRunningAppProcesses"); // Lazy instantiation of list @@ -7965,16 +7981,7 @@ public final class ActivityManagerService extends ActivityManagerNative ActivityManager.RunningAppProcessInfo currApp = new ActivityManager.RunningAppProcessInfo(app.processName, app.pid, app.getPackageList()); - currApp.uid = app.info.uid; - if (mHeavyWeightProcess == app) { - currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE; - } - if (app.persistent) { - currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT; - } - int adj = app.curAdj; - currApp.importance = oomAdjToImportance(adj, currApp); - currApp.importanceReasonCode = app.adjTypeCode; + fillInProcMemInfo(app, currApp); if (app.adjSource instanceof ProcessRecord) { currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid; currApp.importanceReasonImportance = oomAdjToImportance( @@ -8026,6 +8033,18 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override + public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) { + enforceNotIsolatedCaller("getMyMemoryState"); + synchronized (this) { + ProcessRecord proc; + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(Binder.getCallingPid()); + } + fillInProcMemInfo(proc, outInfo); + } + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (checkCallingPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { @@ -8479,8 +8498,8 @@ public final class ActivityManagerService extends ActivityManagerNative pw.print(" Process "); pw.print(pname); pw.print(" uid "); pw.print(puid); pw.print(": last crashed "); - pw.print((now-uids.valueAt(i))); - pw.println(" ms ago"); + TimeUtils.formatDuration(now-uids.valueAt(i), pw); + pw.println(" ago"); } } } @@ -13982,6 +14001,14 @@ public final class ActivityManagerService extends ActivityManagerNative if (mPreviousProcess != null) minFactor++; if (factor < minFactor) factor = minFactor; step = 0; + int fgTrimLevel; + if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/5)) { + fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; + } else if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/3)) { + fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; + } else { + fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; + } int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; for (i=0; i<N; i++) { ProcessRecord app = mLruProcesses.get(i); @@ -14008,6 +14035,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.trimMemoryLevel = curLevel; step++; if (step >= factor) { + step = 0; switch (curLevel) { case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE; @@ -14027,20 +14055,28 @@ public final class ActivityManagerService extends ActivityManagerNative } } app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; - } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi) - && app.pendingUiClean) { - if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN - && app.thread != null) { + } else { + if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi) + && app.pendingUiClean) { + // If this application is now in the background and it + // had done UI, then give it the special trim level to + // have it free UI resources. + final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; + if (app.trimMemoryLevel < level && app.thread != null) { + try { + app.thread.scheduleTrimMemory(level); + } catch (RemoteException e) { + } + } + app.pendingUiClean = false; + } + if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) { try { - app.thread.scheduleTrimMemory( - ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); + app.thread.scheduleTrimMemory(fgTrimLevel); } catch (RemoteException e) { } } - app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; - app.pendingUiClean = false; - } else { - app.trimMemoryLevel = 0; + app.trimMemoryLevel = fgTrimLevel; } } } else { @@ -14057,11 +14093,9 @@ public final class ActivityManagerService extends ActivityManagerNative } catch (RemoteException e) { } } - app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; app.pendingUiClean = false; - } else { - app.trimMemoryLevel = 0; } + app.trimMemoryLevel = 0; } } |