Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62f20ecf authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add new am option to profile the launching of an activity.

Change-Id: Ie71a8043eafe41f53a0b3dbb5170276d87acbc9b
parent 0f2da17a
Loading
Loading
Loading
Loading
+35 −6
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ public class Am {
    private boolean mDebugOption = false;
    private boolean mWaitOption = false;

    private String mProfileFile;
    private boolean mProfileAutoStop;

    // These are magic strings understood by the Eclipse plugin.
    private static final String FATAL_ERROR_CODE = "Error type 1";
    private static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
@@ -249,6 +252,12 @@ public class Am {
                mDebugOption = true;
            } else if (opt.equals("-W")) {
                mWaitOption = true;
            } else if (opt.equals("-P")) {
                mProfileFile = nextArgRequired();
                mProfileAutoStop = true;
            } else if (opt.equals("--start-profiler")) {
                mProfileFile = nextArgRequired();
                mProfileAutoStop = false;
            } else {
                System.err.println("Error: Unknown option: " + opt);
                showUsage();
@@ -294,16 +303,34 @@ public class Am {
        Intent intent = makeIntent();
        System.out.println("Starting: " + intent);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        ParcelFileDescriptor fd = null;

        if (mProfileFile != null) {
            try {
                fd = ParcelFileDescriptor.open(
                        new File(mProfileFile),
                        ParcelFileDescriptor.MODE_CREATE |
                        ParcelFileDescriptor.MODE_TRUNCATE |
                        ParcelFileDescriptor.MODE_READ_WRITE);
            } catch (FileNotFoundException e) {
                System.err.println("Error: Unable to open file: " + mProfileFile);
                return;
            }
        }

        // XXX should do something to determine the MIME type.
        IActivityManager.WaitResult result = null;
        int res;
        if (mWaitOption) {
            result = mAm.startActivityAndWait(null, intent, intent.getType(),
                        null, 0, null, null, 0, false, mDebugOption);
                        null, 0, null, null, 0, false, mDebugOption,
                        mProfileFile, fd, mProfileAutoStop);
            res = result.result;
        } else {
            res = mAm.startActivity(null, intent, intent.getType(),
                    null, 0, null, null, 0, false, mDebugOption);
                    null, 0, null, null, 0, false, mDebugOption,
                    mProfileFile, fd, mProfileAutoStop);
        }
        PrintStream out = mWaitOption ? System.out : System.err;
        boolean launched = false;
@@ -483,7 +510,7 @@ public class Am {
            wall = "--wall".equals(nextOption());
            process = nextArgRequired();
        } else if ("stop".equals(cmd)) {
            process = nextArgRequired();
            process = nextArg();
        } else {
            // Compatibility with old syntax: process is specified first.
            process = cmd;
@@ -1076,14 +1103,14 @@ public class Am {
    private static void showUsage() {
        System.err.println(
                "usage: am [subcommand] [options]\n" +
                "usage: am start [-D] [-W] <INTENT>\n" +
                "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>] <INTENT>\n" +
                "       am startservice <INTENT>\n" +
                "       am force-stop <PACKAGE>\n" +
                "       am broadcast <INTENT>\n" +
                "       am instrument [-r] [-e <NAME> <VALUE>] [-p] [-w]\n" +
                "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
                "               [--no-window-animation] <COMPONENT>\n" +
                "       am profile [looper] start <PROCESS> <FILE>\n" +
                "       am profile [looper] stop <PROCESS>\n" +
                "       am profile [looper] stop [<PROCESS>]\n" +
                "       am dumpheap [flags] <PROCESS> <FILE>\n" +
                "       am monitor [--gdb <port>]\n" +
                "       am screen-compat [on|off] <PACKAGE>\n" +
@@ -1092,6 +1119,8 @@ public class Am {
                "am start: start an Activity.  Options are:\n" +
                "    -D: enable debugging\n" +
                "    -W: wait for launch to complete\n" +
                "    --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
                "    -P <FILE>: like above, but profiling stops when app goes idle\n" +
                "\n" +
                "am startservice: start a Service.\n" +
                "\n" +
+2 −1
Original line number Diff line number Diff line
@@ -3353,7 +3353,8 @@ public class Activity extends ContextThemeWrapper
                            intent, intent.resolveTypeIfNeeded(
                                    getContentResolver()),
                            null, 0,
                            mToken, mEmbeddedID, requestCode, true, false);
                            mToken, mEmbeddedID, requestCode, true, false,
                            null, null, false);
            } catch (RemoteException e) {
                // Empty
            }
+35 −6
Original line number Diff line number Diff line
@@ -124,9 +124,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            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 @@ class ActivityManagerProxy implements IActivityManager
            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 @@ class ActivityManagerProxy implements IActivityManager
        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 @@ class ActivityManagerProxy implements IActivityManager
            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 @@ class ActivityManagerProxy implements IActivityManager
        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 @@ class ActivityManagerProxy implements IActivityManager
        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 @@ class ActivityManagerProxy implements IActivityManager
        } else {
            data.writeInt(0);
        }
        data.writeInt(stopProfiling ? 1 : 0);
        mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
        reply.readException();
        data.recycle();
+96 −10
Original line number Diff line number Diff line
@@ -225,6 +225,10 @@ public final class ActivityThread {
        Configuration createdConfig;
        ActivityClientRecord nextIdle;

        String profileFile;
        ParcelFileDescriptor profileFd;
        boolean autoStopProfiler;

        ActivityInfo activityInfo;
        CompatibilityInfo compatInfo;
        LoadedApk packageInfo;
@@ -361,6 +365,9 @@ public final class ActivityThread {
        List<ProviderInfo> providers;
        ComponentName instrumentationName;
        String profileFile;
        ParcelFileDescriptor profileFd;
        boolean autoStopProfiler;
        boolean profiling;
        Bundle instrumentationArgs;
        IInstrumentationWatcher instrumentationWatcher;
        int debugMode;
@@ -371,6 +378,57 @@ public final class ActivityThread {
        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 class ActivityThread {
        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 @@ public final class ActivityThread {
            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 class ActivityThread {
        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 @@ public final class ActivityThread {
            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 @@ public final class ActivityThread {
    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 @@ public final class ActivityThread {
                        (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 @@ public final class ActivityThread {
                    prev.nextIdle = null;
                } while (a != null);
            }
            if (stopProfiling) {
                mBoundApplication.stopProfiling();
            }
            ensureJitEnabled();
            return false;
        }
@@ -1560,7 +1632,8 @@ public final class ActivityThread {
    }

    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 @@ public final class ActivityThread {
        // 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 @@ public final class ActivityThread {
                        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 @@ public final class ActivityThread {
                    ViewDebug.stopLooperProfiling();
                    break;
                default:
                    Debug.stopMethodTracing();
                    mBoundApplication.stopProfiling();
                    break;
                    
            }
        }
    }
@@ -3607,6 +3687,10 @@ public final class ActivityThread {
        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 @@ public final class ActivityThread {
            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 @@ public final class ActivityThread {

    /*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()
+29 −5
Original line number Diff line number Diff line
@@ -138,8 +138,12 @@ public abstract class ApplicationThreadNative extends Binder
            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 @@ public abstract class ApplicationThreadNative extends Binder
            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 @@ public abstract class ApplicationThreadNative extends Binder
            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 @@ class ApplicationThreadProxy implements IApplicationThread {
    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 @@ class ApplicationThreadProxy implements IApplicationThread {
        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 @@ class ApplicationThreadProxy implements IApplicationThread {
    }

    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 @@ class ApplicationThreadProxy implements IApplicationThread {
            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);
Loading