Add new am option to profile the launching of an activity.
Change-Id: Ie71a8043eafe41f53a0b3dbb5170276d87acbc9b
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d5f630a..e376220 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -225,6 +225,10 @@
Configuration createdConfig;
ActivityClientRecord nextIdle;
+ String profileFile;
+ ParcelFileDescriptor profileFd;
+ boolean autoStopProfiler;
+
ActivityInfo activityInfo;
CompatibilityInfo compatInfo;
LoadedApk packageInfo;
@@ -361,6 +365,9 @@
List<ProviderInfo> providers;
ComponentName instrumentationName;
String profileFile;
+ ParcelFileDescriptor profileFd;
+ boolean autoStopProfiler;
+ boolean profiling;
Bundle instrumentationArgs;
IInstrumentationWatcher instrumentationWatcher;
int debugMode;
@@ -371,6 +378,57 @@
public String toString() {
return "AppBindData{appInfo=" + appInfo + "}";
}
+ public void setProfiler(String file, ParcelFileDescriptor fd) {
+ if (profiling) {
+ if (fd != null) {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ }
+ return;
+ }
+ if (profileFd != null) {
+ try {
+ profileFd.close();
+ } catch (IOException e) {
+ }
+ }
+ profileFile = file;
+ profileFd = fd;
+ }
+ public void startProfiling() {
+ if (profileFd == null || profiling) {
+ return;
+ }
+ try {
+ Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
+ 8 * 1024 * 1024, 0);
+ profiling = true;
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Profiling failed on path " + profileFile);
+ try {
+ profileFd.close();
+ profileFd = null;
+ } catch (IOException e2) {
+ Slog.w(TAG, "Failure closing profile fd", e2);
+ }
+ }
+ }
+ public void stopProfiling() {
+ if (profiling) {
+ profiling = false;
+ Debug.stopMethodTracing();
+ if (profileFd != null) {
+ try {
+ profileFd.close();
+ } catch (IOException e) {
+ }
+ }
+ profileFd = null;
+ profileFile = null;
+ }
+ }
}
static final class DumpComponentInfo {
@@ -463,7 +521,8 @@
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
+ List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
+ String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
@@ -479,6 +538,10 @@
r.startsNotResumed = notResumed;
r.isForward = isForward;
+ r.profileFile = profileName;
+ r.profileFd = profileFd;
+ r.autoStopProfiler = autoStopProfiler;
+
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
@@ -579,6 +642,7 @@
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
+ ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
int debugMode, boolean isRestrictedBackupMode, Configuration config,
CompatibilityInfo compatInfo, Map<String, IBinder> services,
@@ -596,7 +660,8 @@
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
- data.profileFile = profileFile;
+ data.setProfiler(profileFile, profileFd);
+ data.autoStopProfiler = false;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.debugMode = debugMode;
@@ -1225,6 +1290,10 @@
private class Idler implements MessageQueue.IdleHandler {
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
+ boolean stopProfiling = false;
+ if (mBoundApplication.profileFd != null && mBoundApplication.autoStopProfiler) {
+ stopProfiling = true;
+ }
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManagerNative.getDefault();
@@ -1236,7 +1305,7 @@
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
- am.activityIdle(a.token, a.createdConfig);
+ am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
// Ignore
@@ -1247,6 +1316,9 @@
prev.nextIdle = null;
} while (a != null);
}
+ if (stopProfiling) {
+ mBoundApplication.stopProfiling();
+ }
ensureJitEnabled();
return false;
}
@@ -1560,7 +1632,8 @@
}
public boolean isProfiling() {
- return mBoundApplication != null && mBoundApplication.profileFile != null;
+ return mBoundApplication != null && mBoundApplication.profileFile != null
+ && mBoundApplication.profileFd == null;
}
public String getProfileFilePath() {
@@ -1870,6 +1943,13 @@
// we are back active so skip it.
unscheduleGcIdler();
+ Slog.i(TAG, "Launch: profileFd=" + r.profileFile + " stop=" + r.autoStopProfiler);
+ if (r.profileFd != null) {
+ mBoundApplication.setProfiler(r.profileFile, r.profileFd);
+ mBoundApplication.startProfiling();
+ mBoundApplication.autoStopProfiler = r.autoStopProfiler;
+ }
+
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
Activity a = performLaunchActivity(r, customIntent);
@@ -3489,8 +3569,9 @@
ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor());
break;
default:
- Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
- 8 * 1024 * 1024, 0);
+ mBoundApplication.setProfiler(pcd.path, pcd.fd);
+ mBoundApplication.autoStopProfiler = false;
+ mBoundApplication.startProfiling();
break;
}
} catch (RuntimeException e) {
@@ -3509,9 +3590,8 @@
ViewDebug.stopLooperProfiling();
break;
default:
- Debug.stopMethodTracing();
+ mBoundApplication.stopProfiling();
break;
-
}
}
}
@@ -3607,6 +3687,10 @@
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName);
+ if (data.profileFd != null) {
+ data.startProfiling();
+ }
+
// If the app is Honeycomb MR1 or earlier, switch its AsyncTask
// implementation to use the pool executor. Normally, we use the
// serialized executor as the default. This has to happen in the
@@ -3745,7 +3829,8 @@
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
- if (data.profileFile != null && !ii.handleProfiling) {
+ if (data.profileFile != null && !ii.handleProfiling
+ && data.profileFd == null) {
data.handlingProfiling = true;
File file = new File(data.profileFile);
file.getParentFile().mkdirs();
@@ -3799,7 +3884,8 @@
/*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
IActivityManager am = ActivityManagerNative.getDefault();
- if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
+ if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling
+ && mBoundApplication.profileFd == null) {
Debug.stopMethodTracing();
}
//Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()