Add new am option to profile the launching of an activity.
Change-Id: Ie71a8043eafe41f53a0b3dbb5170276d87acbc9b
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 929867b..1271ddd 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3353,7 +3353,8 @@
intent, intent.resolveTypeIfNeeded(
getContentResolver()),
null, 0,
- mToken, mEmbeddedID, requestCode, true, false);
+ mToken, mEmbeddedID, requestCode, true, false,
+ null, null, false);
} catch (RemoteException e) {
// Empty
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a73e10a..8901fc8 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -124,9 +124,13 @@
int requestCode = data.readInt();
boolean onlyIfNeeded = data.readInt() != 0;
boolean debug = data.readInt() != 0;
+ String profileFile = data.readString();
+ ParcelFileDescriptor profileFd = data.readInt() != 0
+ ? data.readFileDescriptor() : null;
+ boolean autoStopProfiler = data.readInt() != 0;
int result = startActivity(app, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded, debug);
+ requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler);
reply.writeNoException();
reply.writeInt(result);
return true;
@@ -146,9 +150,13 @@
int requestCode = data.readInt();
boolean onlyIfNeeded = data.readInt() != 0;
boolean debug = data.readInt() != 0;
+ String profileFile = data.readString();
+ ParcelFileDescriptor profileFd = data.readInt() != 0
+ ? data.readFileDescriptor() : null;
+ boolean autoStopProfiler = data.readInt() != 0;
WaitResult result = startActivityAndWait(app, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded, debug);
+ requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler);
reply.writeNoException();
result.writeToParcel(reply, 0);
return true;
@@ -349,8 +357,9 @@
if (data.readInt() != 0) {
config = Configuration.CREATOR.createFromParcel(data);
}
+ boolean stopProfiling = data.readInt() != 0;
if (token != null) {
- activityIdle(token, config);
+ activityIdle(token, config, stopProfiling);
}
reply.writeNoException();
return true;
@@ -1572,7 +1581,8 @@
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
- boolean debug) throws RemoteException {
+ boolean debug, String profileFile, ParcelFileDescriptor profileFd,
+ boolean autoStopProfiler) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1586,6 +1596,14 @@
data.writeInt(requestCode);
data.writeInt(onlyIfNeeded ? 1 : 0);
data.writeInt(debug ? 1 : 0);
+ data.writeString(profileFile);
+ if (profileFd != null) {
+ data.writeInt(1);
+ profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ data.writeInt(0);
+ }
+ data.writeInt(autoStopProfiler ? 1 : 0);
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
@@ -1597,7 +1615,8 @@
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
- boolean debug) throws RemoteException {
+ boolean debug, String profileFile, ParcelFileDescriptor profileFd,
+ boolean autoStopProfiler) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1611,6 +1630,14 @@
data.writeInt(requestCode);
data.writeInt(onlyIfNeeded ? 1 : 0);
data.writeInt(debug ? 1 : 0);
+ data.writeString(profileFile);
+ if (profileFd != null) {
+ data.writeInt(1);
+ profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ data.writeInt(0);
+ }
+ data.writeInt(autoStopProfiler ? 1 : 0);
mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
reply.readException();
WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
@@ -1829,7 +1856,8 @@
data.recycle();
reply.recycle();
}
- public void activityIdle(IBinder token, Configuration config) throws RemoteException
+ public void activityIdle(IBinder token, Configuration config, boolean stopProfiling)
+ throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -1841,6 +1869,7 @@
} else {
data.writeInt(0);
}
+ data.writeInt(stopProfiling ? 1 : 0);
mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
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()
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index bea057e..0a6fdd4 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -138,8 +138,12 @@
List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
boolean notResumed = data.readInt() != 0;
boolean isForward = data.readInt() != 0;
+ String profileName = data.readString();
+ ParcelFileDescriptor profileFd = data.readInt() != 0
+ ? data.readFileDescriptor() : null;
+ boolean autoStopProfiler = data.readInt() != 0;
scheduleLaunchActivity(intent, b, ident, info, compatInfo, state, ri, pi,
- notResumed, isForward);
+ notResumed, isForward, profileName, profileFd, autoStopProfiler);
return true;
}
@@ -255,6 +259,9 @@
ComponentName testName = (data.readInt() != 0)
? new ComponentName(data) : null;
String profileName = data.readString();
+ ParcelFileDescriptor profileFd = data.readInt() != 0
+ ? data.readFileDescriptor() : null;
+ boolean autoStopProfiler = data.readInt() != 0;
Bundle testArgs = data.readBundle();
IBinder binder = data.readStrongBinder();
IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder);
@@ -265,7 +272,7 @@
HashMap<String, IBinder> services = data.readHashMap(null);
Bundle coreSettings = data.readBundle();
bindApplication(packageName, info,
- providers, testName, profileName,
+ providers, testName, profileName, profileFd, autoStopProfiler,
testArgs, testWatcher, testMode, restrictedBackupMode,
config, compatInfo, services, coreSettings);
return true;
@@ -624,7 +631,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)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -638,6 +646,14 @@
data.writeTypedList(pendingNewIntents);
data.writeInt(notResumed ? 1 : 0);
data.writeInt(isForward ? 1 : 0);
+ data.writeString(profileName);
+ if (profileFd != null) {
+ data.writeInt(1);
+ profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ data.writeInt(0);
+ }
+ data.writeInt(autoStopProfiler ? 1 : 0);
mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
@@ -793,8 +809,9 @@
}
public final void bindApplication(String packageName, ApplicationInfo info,
- List<ProviderInfo> providers, ComponentName testName,
- String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
+ List<ProviderInfo> providers, ComponentName testName, String profileName,
+ ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle testArgs,
+ IInstrumentationWatcher testWatcher, int debugMode,
boolean restrictedBackupMode, Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -809,6 +826,13 @@
testName.writeToParcel(data, 0);
}
data.writeString(profileName);
+ if (profileFd != null) {
+ data.writeInt(1);
+ profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ data.writeInt(0);
+ }
+ data.writeInt(autoStopProfiler ? 1 : 0);
data.writeBundle(testArgs);
data.writeStrongInterface(testWatcher);
data.writeInt(debugMode);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b1b0583..49f8449 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -84,11 +84,13 @@
public int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo, String resultWho, int requestCode,
- boolean onlyIfNeeded, boolean debug) throws RemoteException;
+ boolean onlyIfNeeded, boolean debug, String profileFile,
+ ParcelFileDescriptor profileFd, boolean autoStopProfiler) throws RemoteException;
public WaitResult startActivityAndWait(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo, String resultWho, int requestCode,
- boolean onlyIfNeeded, boolean debug) throws RemoteException;
+ boolean onlyIfNeeded, boolean debug, String profileFile,
+ ParcelFileDescriptor profileFd, boolean autoStopProfiler) throws RemoteException;
public int startActivityWithConfig(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo, String resultWho, int requestCode,
@@ -118,7 +120,8 @@
public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException;
public void attachApplication(IApplicationThread app) throws RemoteException;
/* oneway */
- public void activityIdle(IBinder token, Configuration config) throws RemoteException;
+ public void activityIdle(IBinder token, Configuration config,
+ boolean stopProfiling) throws RemoteException;
public void activityPaused(IBinder token) throws RemoteException;
/* oneway */
public void activityStopped(IBinder token, Bundle state,
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 3a8eb28..9ae5ab1 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -55,7 +55,8 @@
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)
throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, int configChanges,
@@ -86,7 +87,8 @@
static final int DEBUG_ON = 1;
static final int DEBUG_WAIT = 2;
void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
- ComponentName testName, String profileName, Bundle testArguments,
+ ComponentName testName, String profileName, ParcelFileDescriptor profileFd,
+ boolean autoStopProfiler, Bundle testArguments,
IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) throws RemoteException;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index f99b420..f3bc495 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1379,7 +1379,7 @@
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mEmbeddedID : null,
- requestCode, false, false);
+ requestCode, false, false, null, null, false);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
@@ -1475,7 +1475,7 @@
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mWho : null,
- requestCode, false, false);
+ requestCode, false, false, null, null, false);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3ea3f56..ac15d9c 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -129,6 +129,16 @@
}
/**
+ * Create a new ParcelFileDescriptor that is a dup of the existing
+ * FileDescriptor. This obeys standard POSIX semantics, where the
+ * new file descriptor shared state such as file position with the
+ * original file descriptor.
+ */
+ public ParcelFileDescriptor dup() throws IOException {
+ return dup(getFileDescriptor());
+ }
+
+ /**
* Create a new ParcelFileDescriptor from a raw native fd. The new
* ParcelFileDescriptor holds a dup of the original fd passed in here,
* so you must still close that fd as well as the new ParcelFileDescriptor.