diff options
7 files changed, 56 insertions, 1 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index ba93b2a2cafe..8187468805c3 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -121,7 +121,7 @@ public class Am extends BaseCommand { PrintWriter pw = new PrintWriter(out); pw.println( "usage: am [subcommand] [options]\n" + - "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + + "usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + " [--sampling INTERVAL] [-R COUNT] [-S]\n" + " [--track-allocation] [--user <USER_ID> | current] <INTENT>\n" + " am startservice [--user <USER_ID> | current] <INTENT>\n" + @@ -180,6 +180,7 @@ public class Am extends BaseCommand { "\n" + "am start: start an Activity. Options are:\n" + " -D: enable debugging\n" + + " -N: enable native debugging\n" + " -W: wait for launch to complete\n" + " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + " --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" + @@ -473,6 +474,8 @@ public class Am extends BaseCommand { public boolean handleOption(String opt, ShellCommand cmd) { if (opt.equals("-D")) { mStartFlags |= ActivityManager.START_FLAG_DEBUG; + } else if (opt.equals("-N")) { + mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING; } else if (opt.equals("-W")) { mWaitOption = true; } else if (opt.equals("-P")) { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 82170d1ac60f..dc37a573d5c6 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -245,6 +245,13 @@ public class ActivityManager { public static final int START_FLAG_TRACK_ALLOCATION = 1<<2; /** + * Flag for IActivityManaqer.startActivity: launch the app with + * native debugging support. + * @hide + */ + public static final int START_FLAG_NATIVE_DEBUGGING = 1<<3; + + /** * Result for IActivityManaqer.broadcastIntent: success! * @hide */ diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 1e4ee4bc2ef5..fe2dfdfc8e40 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -647,6 +647,12 @@ public class Process { if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) { argsForZygote.add("--generate-debug-info"); } + if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) { + argsForZygote.add("--always-jit"); + } + if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) { + argsForZygote.add("--native-debuggable"); + } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index d23f26d675c4..919254a36a76 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -41,6 +41,10 @@ public final class Zygote { public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4; /** Force generation of native debugging information. */ public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 5; + /** Always use JIT-ed code. */ + public static final int DEBUG_ALWAYS_JIT = 1 << 6; + /** Make the code debuggable with turning off some optimizations. */ + public static final int DEBUG_NATIVE_DEBUGGABLE = 1 << 7; /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = 0; diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index a40f9a82ace7..85d84bb3f986 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -434,6 +434,10 @@ class ZygoteConnection { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } else if (arg.equals("--generate-debug-info")) { debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; + } else if (arg.equals("--always-jit")) { + debugFlags |= Zygote.DEBUG_ALWAYS_JIT; + } else if (arg.equals("--native-debuggable")) { + debugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; } else if (arg.equals("--enable-jni-logging")) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } else if (arg.equals("--enable-assert")) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 978e69c9140a..c55e713b7f7a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1299,6 +1299,7 @@ public final class ActivityManagerService extends ActivityManagerNative int mMemWatchDumpPid; int mMemWatchDumpUid; String mTrackAllocationApp = null; + String mNativeDebuggingApp = null; final long[] mTmpLong = new long[2]; @@ -3468,6 +3469,13 @@ public final class ActivityManagerService extends ActivityManagerNative if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } + if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) { + // Enable all debug flags required by the native debugger. + debugFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anything + debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info + debugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizations + mNativeDebuggingApp = null; + } String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; if (requiredAbi == null) { @@ -11240,6 +11248,16 @@ public final class ActivityManagerService extends ActivityManagerNative } } + void setNativeDebuggingAppLocked(ApplicationInfo app, String processName) { + boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); + if (!isDebuggable) { + if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) { + throw new SecurityException("Process not debuggable: " + app.packageName); + } + } + mNativeDebuggingApp = processName; + } + @Override public void setAlwaysFinish(boolean enabled) { enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH, @@ -13934,6 +13952,15 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println(" mProfileType=" + mProfileType); } } + if (mNativeDebuggingApp != null) { + if (dumpPackage == null || dumpPackage.equals(mNativeDebuggingApp)) { + if (needSep) { + pw.println(); + needSep = false; + } + pw.println(" mNativeDebuggingApp=" + mNativeDebuggingApp); + } + } if (dumpPackage == null) { if (mAlwaysFinishActivities || mController != null) { pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 31712d9233a0..5f65b3da7f48 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1018,6 +1018,10 @@ public final class ActivityStackSupervisor implements DisplayListener { mService.setDebugApp(aInfo.processName, true, false); } + if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) { + mService.setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName); + } + if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) { mService.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName); } |