[Android Software/Hacking General [Developers Only]] pikachu01:
Let me just reply to each one of your queries. Seems like you don't understand the code enough when you're making this comment.

The *_MEM values are calculated here:

// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
private final long[] mOomMinFreeLow = new long[] {
8192, 12288, 16384,
24576, 28672, 32768
};
// These are the high-end OOM level limits. This is appropriate for a
// 1280x800 or larger screen with around 1GB RAM. Values are in KB.
private final long[] mOomMinFreeHigh = new long[] {
32768, 40960, 49152,
57344, 65536, 81920
};

Then they are calculated here:

for (int i=0; i<mOomAdj.length; i++) {
long low = mOomMinFreeLow[i];
long high = mOomMinFreeHigh[i];
mOomMinFree[i] = (long)(low + ((high-low)*scale));

if (i > 0) {
adjString.append(',');
memString.append(',');
}
adjString.append(mOomAdj[i]);
memString.append((mOomMinFree[i]*1024)/PAGE_SIZE);
}

Note that scale is calculated by the screen size/total available memory here:

// Scale buckets from avail memory: at 300MB we use the lowest values to
// 700MB or more for the top values.
float scaleMem = ((float)(mTotalMemMb-300))/(700-300);

// Scale buckets from screen size.
int minSize = 320*480; // 153600
int maxSize = 1280*800; // 1024000 230400 870400 .264
float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);

StringBuilder adjString = new StringBuilder();
StringBuilder memString = new StringBuilder();

float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;

The array of memory thresholds are then echoed into the lowmemorykiller's minfree here:

writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString());

They are also written to the outInfo (an object passed to every app that is created) here:

public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
outInfo.availMem = Process.getFreeMemory();
outInfo.totalMem = Process.getTotalMemory();
outInfo.threshold = homeAppMem;
outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
outInfo.hiddenAppThreshold = hiddenAppMem;
outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
ProcessList.SERVICE_ADJ);
outInfo.visibleAppThreshold = mProcessList.getMemLevel(
ProcessList.VISIBLE_APP_ADJ);
outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
ProcessList.FOREGROUND_APP_ADJ);
}

The outInfo is then used here as the general information of the system memory state:

/**
* Return general information about the memory state of the system. This
* can be used to help decide how to manage your own memory, though note
* that polling is not recommended and
* {@link android.content.ComponentCallbacks2#onTrimMemory(int)
* ComponentCallbacks2.onTrimMemory(int)} is the preferred way to do this.
* Also see {@link #getMyMemoryState} for how to retrieve the current trim
* level of your process as needed, which gives a better hint for how to
* manage its memory.
*/
public void getMemoryInfo(MemoryInfo outInfo) {
try {
ActivityManagerNative.getDefault().getMemoryInfo(outInfo);
} catch (RemoteException e) {
}
}

This is then used in ActivityManager.java here:

public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(availMem);
dest.writeLong(totalMem);
dest.writeLong(threshold);
dest.writeInt(lowMemory ? 1 : 0);
dest.writeLong(hiddenAppThreshold);
dest.writeLong(secondaryServerThreshold);
dest.writeLong(visibleAppThreshold);
dest.writeLong(foregroundAppThreshold);
}

public void readFromParcel(Parcel source) {
availMem = source.readLong();
totalMem = source.readLong();
threshold = source.readLong();
lowMemory = source.readInt() != 0;
hiddenAppThreshold = source.readLong();
secondaryServerThreshold = source.readLong();
visibleAppThreshold = source.readLong();
foregroundAppThreshold = source.readLong();
}

The code above provides APIs to each app on the memory thresholds that it can consume as well as the lowMemory boolean that triggers if the system is running low on memory.

Some apps like the browser implements it here:

private static boolean canSatisfyMemoryAllocation(long bytesRequested) {
checkInitialized();
ActivityManager manager = (ActivityManager) sContext.getSystemService(
Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
manager.getMemoryInfo(memInfo);
long leftToAllocate = memInfo.availMem - memInfo.threshold;
return !memInfo.lowMemory && bytesRequested < leftToAllocate;
}

I don't get it when you say that I didn't know about it. I knew about it when someone asked me whether LMK is compatible with Jelly Bean. I recently installed Cyanogenmod on my Galaxy S (which is Jelly Bean) and I noticed that the minfree values are weird values and that it's init.rc didn't have any prop values. This lead me to dig up the actual code that processes the prop values and what was changed.

Do note that the ActivityManager.java code is basically unchanged (save for the new APIs for the MEM changes) for the build.prop -> memory calculated on the fly commit. This commit:

https://github.com/CyanogenMod/andr...608423b721e0153f37bfd5eba78fcd2489562d#L3R126

lowMemory is still used in some parts like this code:

private static boolean canSatisfyMemoryAllocation(long bytesRequested) {
checkInitialized();
ActivityManager manager = (ActivityManager) sContext.getSystemService(
Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
manager.getMemoryInfo(memInfo);
long leftToAllocate = memInfo.availMem - memInfo.threshold;
return !memInfo.lowMemory && bytesRequested < leftToAllocate;
}

I don't get why you pointed this out. I mentioned that I knew Samsung stock ICS was using the old methods because:

1. Init.rc still has the prop values for *_MEM, *_ADJ.

2. /sys/module/lowmemorykiller gets the default init.rc values

3. Testing the *_MEM values, I get the correct behaviour for each of the apps to maintain a memory > 100MB if the prop values are set as such.

4. Forgot to mention one last thing. The services.jar launches after init.rc launches. If services.jar contains the code to calculate LMK/OOM on the fly, it would've overridden init.rc.

I mentioned 15 apps right. You do know the default limit is 15 apps right? Did you intentionally miss that or did you hit yourself on the head when you read that?

Doing Zenonia4 + Dead Trigger + all the Angry Birds games + Opera browser and (which is below the 15 app limit) and still getting > 100MB free even when /sys/module/lowmemorykiller minfree values are about 40MB just proves it doesn't it?

Good to hear that. I fail to see the practice behind the preach though.

Launchers are supposed to die if apps need the memory. I would rather have my launcher die than having my Dead Trigger stutter and then ragequit just because my launcher is hogging 30-40MB of RAM.

I'm not saying it's great. I'm saying that it's better than mismatching the Android LMK and Linux LMK. The same thing that you were saying before the whole services.jar fiasco. This was the point you were making and putting into everyone's thread. The ultimate manifesto that you brought up and I supported it because it was the truth.

Now you're going behind yourself saying, nah *_MEM doesn't need to be tweaked and added more to it by saying *_MEM isn't even used when I have proven otherwise with the code I gave above.

Yeah, I still appreciate your efforts in maintaining Supercharger. What I dislike about all this is your backtracking. I idolized the way that you preached about maintaining a in-synced OOM/LMK back then. I am disgusted when you backtrack yourself by saying it doesn't matter anymore. Do you now know my stand?