[Desire HD Q&A, Help & Troubleshooting] DazzaL:
further to this.

in ProcessStats.java (im not sure if this is a kernel file or if it sits just outside the kernel).

mBuffer looks to me to be the main problem.

1. in apaches rom, which is overclocked he defines 23 CPU speeds..ProcessStats.java only allows 20

private long[] getCpuSpeedTimes(long[] out) {
long[] tempTimes = out;
long[] tempSpeeds = mCpuSpeeds;
final int MAX_SPEEDS = 20;
if (out == null) {
tempTimes = new long[MAX_SPEEDS]; // Hopefully no more than that
tempSpeeds = new long[MAX_SPEEDS];

this is a minor issue..as this overflow is trapped in the loop anyway:

if (speed == MAX_SPEEDS) break; // No more

however, the definition of mBuffer is too small:

private byte[] mBuffer = new byte[256];

my file at the moment is 300 bytes. the readFile reads only once instead of looping until end of file:

int len = is.read(mBuffer);
is.close();

so only the first 256 bytes are ever read.

My assumption is that IF the files first 256 bytes ends up cutting off the last read line (and that line lies in the first MAX_SPEEDS lines of the file) before the speed time element..this causes a NoSuchElementException to throw..as the last line will be like

921600 255

960000 750

998400 8042

10368

ie the line

1036800 3089

was cut off too soon and this code

long val = Long.parseLong(token);
tempSpeeds[speed] = val;
token = st.nextToken(); <-- here
val = Long.parseLong(token);.

in getCpuSpeedTimes() fails as it cant see the timing?

would then fail on the second nextToken().

the big question is who owns that code in our custom ROM? is it the same as the original android code so we are at the mercy of Google to fix it or is this something Mike / Apache will be able to patch up ..assuming i'm making sense :)

the only workaround is as i said before: to chmod this file to 700 and ensure it stays there (avoid using setcpu as it changes the permissions).

You can probably also reduce this by limiting the CPU frequency range your phone uses (ie keep the filesize smaller)..if you have profiles that span 200mhz to 1.2ghz then you will probably hit this sooner :)

i did a test.

1. rebooted my phone..ensured time_in_state had permissions -r--r--r--

2. manipulated CPU frequency using cpu tuner to make all frequencies have at least 5 bytes per line.

once the first 20 lines were > 256 bytes and the 256nd byte sat between <cpu speed> and <time spent at that speed> i get the loop.

eg just before the issue arose i saw:

# cat time_in_state
cat time_in_state
245000 200030
422400 12676
460800 11929
499200 10333
537600 37021
576000 10685
614400 13672
652800 10646
691200 14864
729600 13956
768000 12662
806400 15025
844800 22094
883200 26741
921600 10389
960000 9937
998400 17606
1036800 6864
1075200 1560
1113600 1296
1152000 2158
1190400 2540
1228800 2463

i had my cpu pinned to 960 mhz.

the 256 at this point lies here:

1075200 1560
1113600 1

ie line 20 is cut off after 1..this is still "valid" in terms of the data in mBuffer..but once 960 rolled into five digits

# cat time_in_state
cat time_in_state
245000 200030
422400 12676
460800 11929
499200 10333
537600 37021
576000 10685
614400 13672
652800 10646
691200 14864
729600 13956
768000 12662
806400 15025
844800 22094
883200 26741
921600 10389
960000 10288
998400 17606
1036800 6864
1075200 1560
1113600 1296
1152000 2158
1190400 2540
1228800 2463

the 256 byte now meant the last line shifts to:

1036800 6864
1075200

the 2nd word is now totally missing!

as soon as this happened..my logcat started issuing

Unexpected exception collecting process stats
java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:272)
at com.android.server.ProcessStats.getCpuSpeedTimes(ProcessStats.java:596)
at com.android.server.ProcessStats.getLastCpuSpeedTimes(ProcessStats.java:568)
at com.android.server.am.ActivityManagerService.updateCpuStatsNow(ActivityManagerService.java:1657)
at com.android.server.am.ActivityManagerService$4.run(ActivityManagerService.java:1583)

errors.

something later on then causes this behavior to go into a full tight loop (as once the issue starts..it just issues this every few seconds..so most uses wont notice it).