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

Commit 34c78809 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

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

parents 612cb6ee 62f20ecf
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