Enable logwrapper functionality on user builds
When an app is debuggable, check whether a script called "wrap.sh" exists
in the app's native library directory. If so, start the app using the
invoke-with functionality over the script. Weaken the invoke-with check
on the zygote side to allow the functionality for debuggable apps.
The goal of the functionality is to make malloc debug, strace and other
similar tools available for NDK based application developers.
Bug: 33668201
Test: manual - debug malloc can be enabled using the new feature
Change-Id: Ia4bec0854cf4dc08446f1671494200f54ef366ee
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 8cd4273..9cd1a42 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -399,7 +399,8 @@
* <var>processClass</var> to start them.
*
* When invokeWith is not null, the process will be started as a fresh app
- * and not a zygote fork. Note that this is only allowed for uid 0.
+ * and not a zygote fork. Note that this is only allowed for uid 0 or when
+ * debugFlags contains DEBUG_ENABLE_DEBUGGER.
*
* @param processClass The class to use as the process's main entry
* point.
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index cd8163c..5ac33a1 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -171,7 +171,8 @@
* <var>processClass</var> to start them.
*
* When invokeWith is not null, the process will be started as a fresh app
- * and not a zygote fork. Note that this is only allowed for uid 0.
+ * and not a zygote fork. Note that this is only allowed for uid 0 or when
+ * debugFlags contains DEBUG_ENABLE_DEBUGGER.
*
* @param processClass The class to use as the process's main entry
* point.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 66b294d..44c6e85 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -697,9 +697,11 @@
throws ZygoteSecurityException {
int peerUid = peer.getUid();
- if (args.invokeWith != null && peerUid != 0) {
- throw new ZygoteSecurityException("Peer is not permitted to specify "
- + "an explicit invoke-with wrapper command");
+ if (args.invokeWith != null && peerUid != 0 &&
+ (args.debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) == 0) {
+ throw new ZygoteSecurityException("Peer is permitted to specify an"
+ + "explicit invoke-with wrapper command only for debuggable"
+ + "applications.");
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 44601b6..5b02c79 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3783,6 +3783,15 @@
mNativeDebuggingApp = null;
}
+ String invokeWith = null;
+ if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ // Debuggable apps may include a wrapper script with their library directory.
+ String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
+ if (new File(wrapperFileName).exists()) {
+ invokeWith = "/system/bin/logwrapper " + wrapperFileName;
+ }
+ }
+
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
if (requiredAbi == null) {
requiredAbi = Build.SUPPORTED_ABIS[0];
@@ -3814,7 +3823,7 @@
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
- app.info.dataDir, null, entryPointArgs);
+ app.info.dataDir, invokeWith, entryPointArgs);
}
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);