summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt5
-rw-r--r--core/java/android/app/ActivityManager.java33
-rw-r--r--core/java/android/app/ActivityManagerNative.java25
-rw-r--r--core/java/android/app/IActivityManager.java10
-rw-r--r--core/java/android/content/ComponentCallbacks2.java38
-rw-r--r--core/java/android/view/HardwareRenderer.java13
-rw-r--r--core/java/android/view/WindowManagerImpl.java36
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java84
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;
}
}