Skip to content

Commit baad5d5

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "resolved conflicts for merge of 354e034 to master"
2 parents b070521 + 29ba7e6 commit baad5d5

File tree

4 files changed

+168
-11
lines changed

4 files changed

+168
-11
lines changed

cmds/dumpstate/dumpstate.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,24 @@ static void dumpstate() {
124124
dump_file("VM TRACES AT LAST ANR", anr_traces_path);
125125
}
126126

127+
/* slow traces for slow operations */
128+
if (anr_traces_path[0] != 0) {
129+
int tail = strlen(anr_traces_path)-1;
130+
while (tail > 0 && anr_traces_path[tail] != '/') {
131+
tail--;
132+
}
133+
int i = 0;
134+
while (1) {
135+
sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
136+
if (stat(anr_traces_path, &st)) {
137+
// No traces file at this index, done with the files.
138+
break;
139+
}
140+
dump_file("VM TRACES WHEN SLOW", anr_traces_path);
141+
i++;
142+
}
143+
}
144+
127145
dump_file("NETWORK DEV INFO", "/proc/net/dev");
128146
dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
129147
dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
import android.os.SystemProperties;
111111
import android.os.UserId;
112112
import android.provider.Settings;
113+
import android.text.format.Time;
113114
import android.util.EventLog;
114115
import android.util.Pair;
115116
import android.util.Slog;
@@ -197,6 +198,8 @@ public final class ActivityManagerService extends ActivityManagerNative
197198

198199
private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
199200

201+
static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
202+
200203
// Maximum number of recent tasks that we can remember.
201204
static final int MAX_RECENT_TASKS = 20;
202205

@@ -2962,6 +2965,12 @@ public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> first
29622965
return null;
29632966
}
29642967

2968+
dumpStackTraces(tracesPath, firstPids, processStats, lastPids);
2969+
return tracesFile;
2970+
}
2971+
2972+
private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
2973+
ProcessStats processStats, SparseArray<Boolean> lastPids) {
29652974
// Use a FileObserver to detect when traces finish writing.
29662975
// The order of traces is considered important to maintain for legibility.
29672976
FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
@@ -2972,16 +2981,18 @@ public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> first
29722981
observer.startWatching();
29732982

29742983
// First collect all of the stacks of the most important pids.
2975-
try {
2976-
int num = firstPids.size();
2977-
for (int i = 0; i < num; i++) {
2978-
synchronized (observer) {
2979-
Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2980-
observer.wait(200); // Wait for write-close, give up after 200msec
2984+
if (firstPids != null) {
2985+
try {
2986+
int num = firstPids.size();
2987+
for (int i = 0; i < num; i++) {
2988+
synchronized (observer) {
2989+
Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2990+
observer.wait(200); // Wait for write-close, give up after 200msec
2991+
}
29812992
}
2993+
} catch (InterruptedException e) {
2994+
Log.wtf(TAG, e);
29822995
}
2983-
} catch (InterruptedException e) {
2984-
Log.wtf(TAG, e);
29852996
}
29862997

29872998
// Next measure CPU usage.
@@ -3017,13 +3028,83 @@ public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> first
30173028
}
30183029
}
30193030

3020-
return tracesFile;
3021-
30223031
} finally {
30233032
observer.stopWatching();
30243033
}
30253034
}
30263035

3036+
final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
3037+
if (IS_USER_BUILD) {
3038+
return;
3039+
}
3040+
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
3041+
if (tracesPath == null || tracesPath.length() == 0) {
3042+
return;
3043+
}
3044+
3045+
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
3046+
StrictMode.allowThreadDiskWrites();
3047+
try {
3048+
final File tracesFile = new File(tracesPath);
3049+
final File tracesDir = tracesFile.getParentFile();
3050+
final File tracesTmp = new File(tracesDir, "__tmp__");
3051+
try {
3052+
if (!tracesDir.exists()) tracesFile.mkdirs();
3053+
FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
3054+
3055+
if (tracesFile.exists()) {
3056+
tracesTmp.delete();
3057+
tracesFile.renameTo(tracesTmp);
3058+
}
3059+
StringBuilder sb = new StringBuilder();
3060+
Time tobj = new Time();
3061+
tobj.set(System.currentTimeMillis());
3062+
sb.append(tobj.format("%Y-%m-%d %H:%M:%S"));
3063+
sb.append(": ");
3064+
TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
3065+
sb.append(" since ");
3066+
sb.append(msg);
3067+
FileOutputStream fos = new FileOutputStream(tracesFile);
3068+
fos.write(sb.toString().getBytes());
3069+
if (app == null) {
3070+
fos.write("\n*** No application process!".getBytes());
3071+
}
3072+
fos.close();
3073+
FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
3074+
} catch (IOException e) {
3075+
Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesPath, e);
3076+
return;
3077+
}
3078+
3079+
if (app != null) {
3080+
ArrayList<Integer> firstPids = new ArrayList<Integer>();
3081+
firstPids.add(app.pid);
3082+
dumpStackTraces(tracesPath, firstPids, null, null);
3083+
}
3084+
3085+
File lastTracesFile = null;
3086+
File curTracesFile = null;
3087+
for (int i=9; i>=0; i--) {
3088+
String name = String.format("slow%02d.txt", i);
3089+
curTracesFile = new File(tracesDir, name);
3090+
if (curTracesFile.exists()) {
3091+
if (lastTracesFile != null) {
3092+
curTracesFile.renameTo(lastTracesFile);
3093+
} else {
3094+
curTracesFile.delete();
3095+
}
3096+
}
3097+
lastTracesFile = curTracesFile;
3098+
}
3099+
tracesFile.renameTo(curTracesFile);
3100+
if (tracesTmp.exists()) {
3101+
tracesTmp.renameTo(tracesFile);
3102+
}
3103+
} finally {
3104+
StrictMode.setThreadPolicy(oldPolicy);
3105+
}
3106+
}
3107+
30273108
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
30283109
ActivityRecord parent, final String annotation) {
30293110
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);

services/java/com/android/server/am/ActivityRecord.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ final class ActivityRecord {
8585
long startTime; // last time this activity was started
8686
long lastVisibleTime; // last time this activity became visible
8787
long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
88+
long pauseTime; // last time we started pausing the activity
89+
long launchTickTime; // base time for launch tick messages
8890
Configuration configuration; // configuration activity was last running in
8991
CompatibilityInfo compat;// last used compatibility mode
9092
ActivityRecord resultTo; // who started this entry, so will get our reply
@@ -576,6 +578,32 @@ void clearThumbnail() {
576578
}
577579
}
578580

581+
void startLaunchTickingLocked() {
582+
if (ActivityManagerService.IS_USER_BUILD) {
583+
return;
584+
}
585+
if (launchTickTime == 0) {
586+
launchTickTime = SystemClock.uptimeMillis();
587+
continueLaunchTickingLocked();
588+
}
589+
}
590+
591+
boolean continueLaunchTickingLocked() {
592+
if (launchTickTime != 0) {
593+
Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG);
594+
msg.obj = this;
595+
stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
596+
stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
597+
return true;
598+
}
599+
return false;
600+
}
601+
602+
void finishLaunchTickingLocked() {
603+
launchTickTime = 0;
604+
stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
605+
}
606+
579607
// IApplicationToken
580608

581609
public boolean mayFreezeScreenLocked(ProcessRecord app) {
@@ -631,6 +659,7 @@ public void windowsDrawn() {
631659
stack.mInitialStartTime = 0;
632660
}
633661
startTime = 0;
662+
finishLaunchTickingLocked();
634663
}
635664
}
636665

services/java/com/android/server/am/ActivityStack.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ final class ActivityStack {
8787
// How long we wait until giving up on the last activity telling us it
8888
// is idle.
8989
static final int IDLE_TIMEOUT = 10*1000;
90-
90+
91+
// Ticks during which we check progress while waiting for an app to launch.
92+
static final int LAUNCH_TICK = 500;
93+
9194
// How long we wait until giving up on the last activity to pause. This
9295
// is short because it directly impacts the responsiveness of starting the
9396
// next activity.
@@ -275,6 +278,7 @@ enum ActivityState {
275278
static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
276279
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
277280
static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
281+
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
278282

279283
final Handler mHandler = new Handler() {
280284
//public Handler() {
@@ -297,6 +301,13 @@ public void handleMessage(Message msg) {
297301
// We don't at this point know if the activity is fullscreen,
298302
// so we need to be conservative and assume it isn't.
299303
Slog.w(TAG, "Activity pause timeout for " + r);
304+
synchronized (mService) {
305+
if (r.app != null) {
306+
mService.logAppTooSlow(r.app, r.pauseTime,
307+
"pausing " + r);
308+
}
309+
}
310+
300311
activityPaused(r != null ? r.appToken : null, true);
301312
} break;
302313
case IDLE_TIMEOUT_MSG: {
@@ -313,6 +324,15 @@ public void handleMessage(Message msg) {
313324
Slog.w(TAG, "Activity idle timeout for " + r);
314325
activityIdleInternal(r != null ? r.appToken : null, true, null);
315326
} break;
327+
case LAUNCH_TICK_MSG: {
328+
ActivityRecord r = (ActivityRecord)msg.obj;
329+
synchronized (mService) {
330+
if (r.continueLaunchTickingLocked()) {
331+
mService.logAppTooSlow(r.app, r.launchTickTime,
332+
"launching " + r);
333+
}
334+
}
335+
} break;
316336
case DESTROY_TIMEOUT_MSG: {
317337
ActivityRecord r = (ActivityRecord)msg.obj;
318338
// We don't at this point know if the activity is fullscreen,
@@ -554,6 +574,9 @@ final boolean realStartActivityLocked(ActivityRecord r,
554574
r.startFreezingScreenLocked(app, 0);
555575
mService.mWindowManager.setAppVisibility(r.appToken, true);
556576

577+
// schedule launch ticks to collect information about slow apps.
578+
r.startLaunchTickingLocked();
579+
557580
// Have the window manager re-evaluate the orientation of
558581
// the screen based on the new activity order. Note that
559582
// as a result of this, it can call back into the activity
@@ -936,6 +959,7 @@ private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
936959
// responsiveness seen by the user.
937960
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
938961
msg.obj = prev;
962+
prev.pauseTime = SystemClock.uptimeMillis();
939963
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
940964
if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
941965
} else {
@@ -1480,6 +1504,9 @@ final boolean resumeTopActivityLocked(ActivityRecord prev) {
14801504
// This activity is now becoming visible.
14811505
mService.mWindowManager.setAppVisibility(next.appToken, true);
14821506

1507+
// schedule launch ticks to collect information about slow apps.
1508+
next.startLaunchTickingLocked();
1509+
14831510
ActivityRecord lastResumedActivity = mResumedActivity;
14841511
ActivityState lastState = next.state;
14851512

@@ -3257,6 +3284,7 @@ final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
32573284
ActivityRecord r = ActivityRecord.forToken(token);
32583285
if (r != null) {
32593286
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3287+
r.finishLaunchTickingLocked();
32603288
}
32613289

32623290
// Get the activity record.
@@ -3627,6 +3655,7 @@ final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
36273655
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
36283656
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
36293657
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
3658+
r.finishLaunchTickingLocked();
36303659
}
36313660

36323661
final void removeActivityFromHistoryLocked(ActivityRecord r) {

0 commit comments

Comments
 (0)