Bug 811763 - Ensure crash reporter is invoked with the right android user serial number in Android 4.2 and above. r=blassey, snorp
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 15 Nov 2012 14:56:22 -0800
changeset 113426 dc61a415f3e907b85a562c47ce1bd985d6b44f23
parent 113425 2ed2255f26ada942ac7fd22608f804aacfb98bac
child 113427 045367d6644efb8e12759d96bdc6ae0608a513e4
push id23872
push useremorley@mozilla.com
push dateFri, 16 Nov 2012 17:06:27 +0000
treeherdermozilla-central@a7ed19f7d21a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey, snorp
bugs811763
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 811763 - Ensure crash reporter is invoked with the right android user serial number in Android 4.2 and above. r=blassey, snorp
mobile/android/base/GeckoAppShell.java
toolkit/crashreporter/nsExceptionHandler.cpp
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -443,16 +443,42 @@ public class GeckoAppShell
 
         // Enable fixed position layers
         GeckoAppShell.putenv("MOZ_ENABLE_FIXED_POSITION_LAYERS=1");
 
         // setup the app-specific cache path
         f = context.getCacheDir();
         GeckoAppShell.putenv("CACHE_DIRECTORY=" + f.getPath());
 
+        /* We really want to use this code, but it requires bumping up the SDK to 17 so for now
+           we will use reflection. See https://bugzilla.mozilla.org/show_bug.cgi?id=811763#c11
+        
+        if (Build.VERSION.SDK_INT >= 17) {
+            android.os.UserManager um = (android.os.UserManager)context.getSystemService(Context.USER_SERVICE);
+            if (um != null) {
+                GeckoAppShell.putenv("MOZ_ANDROID_USER_SERIAL_NUMBER=" + um.getSerialNumberForUser(android.os.Process.myUserHandle()));
+            } else {
+                Log.d(LOGTAG, "Unable to obtain user manager service on a device with SDK version " + Build.VERSION.SDK_INT);
+            }
+        }
+        */
+        try {
+            Object userManager = context.getSystemService("user");
+            if (userManager != null) {
+                // if userManager is non-null that means we're running on 4.2+ and so the rest of this
+                // should just work
+                Object userHandle = android.os.Process.class.getMethod("myUserHandle", (Class[])null).invoke(null);
+                Object userSerial = userManager.getClass().getMethod("getSerialNumberForUser", userHandle.getClass()).invoke(userManager, userHandle);
+                GeckoAppShell.putenv("MOZ_ANDROID_USER_SERIAL_NUMBER=" + userSerial.toString());
+            }
+        } catch (Exception e) {
+            // Guard against any unexpected failures
+            Log.d(LOGTAG, "Unable to set the user serial number", e);
+        }
+
         putLocaleEnv();
     }
 
     /* This method is referenced by Robocop via reflection. */
     public static void loadSQLiteLibs(Context context, String apkName) {
         if (sSQLiteLibsLoaded)
             return;
         synchronized(sSQLiteLibsLoaded) {
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -177,16 +177,23 @@ static XP_CHAR lastCrashTimeFilename[XP_
 // will be checked on startup.
 static XP_CHAR crashMarkerFilename[XP_PATH_MAX] = {0};
 
 // Whether we've already looked for the marker file.
 static bool lastRunCrashID_checked = false;
 // The minidump ID contained in the marker file.
 static nsString* lastRunCrashID = nullptr;
 
+#if defined(MOZ_WIDGET_ANDROID)
+// on Android 4.2 and above there is a user serial number associated
+// with the current process that gets lost when we fork so we need to
+// explicitly pass it to am
+static char* androidUserSerial = nullptr;
+#endif
+
 // these are just here for readability
 static const char kCrashTimeParameter[] = "CrashTime=";
 static const int kCrashTimeParameterLen = sizeof(kCrashTimeParameter)-1;
 
 static const char kTimeSinceLastCrashParameter[] = "SecondsSinceLastCrash=";
 static const int kTimeSinceLastCrashParameterLen =
                                      sizeof(kTimeSinceLastCrashParameter)-1;
 
@@ -690,30 +697,41 @@ bool MinidumpCallback(
 #if !defined(MOZ_WIDGET_ANDROID)
     // need to clobber this, as libcurl might load NSS,
     // and we want it to load the system NSS.
     unsetenv("LD_LIBRARY_PATH");
     (void) execl(crashReporterPath,
                  crashReporterPath, minidumpPath, (char*)0);
 #else
     // Invoke the reportCrash activity using am
-    (void) execlp("/system/bin/am",
-                 "/system/bin/am",
-                 "start",
-                 "-a", "org.mozilla.gecko.reportCrash",
-                 "-n", crashReporterPath,
-                 "--es", "minidumpPath", minidumpPath,
-                 (char*)0);
+    if (androidUserSerial) {
+      (void) execlp("/system/bin/am",
+                    "/system/bin/am",
+                    "start",
+                    "--user", androidUserSerial,
+                    "-a", "org.mozilla.gecko.reportCrash",
+                    "-n", crashReporterPath,
+                    "--es", "minidumpPath", minidumpPath,
+                    (char*)0);
+    } else {
+      (void) execlp("/system/bin/am",
+                    "/system/bin/am",
+                    "start",
+                    "-a", "org.mozilla.gecko.reportCrash",
+                    "-n", crashReporterPath,
+                    "--es", "minidumpPath", minidumpPath,
+                    (char*)0);
+    }
 #endif
     _exit(1);
   }
 #endif // XP_MACOSX
 #endif // XP_UNIX
 
- return returnValue;
+  return returnValue;
 }
 
 #ifdef XP_WIN
 /**
  * Filters out floating point exceptions which are handled by nsSigHandlers.cpp
  * and should not be handled as crashes.
  */
 static bool FPEFilter(void* context, EXCEPTION_POINTERS* exinfo,
@@ -911,16 +929,20 @@ nsresult SetExceptionHandler(nsIFile* aX
       if (major > 6 || (major == 6 && minor > 1) ||
           (major == 6 && minor == 1 && revision >= 7600)) {
         minidump_type = MiniDumpWithFullMemoryInfo;
       }
     }
   }
 #endif // XP_WIN32
 
+#ifdef MOZ_WIDGET_ANDROID
+  androidUserSerial = getenv("MOZ_ANDROID_USER_SERIAL_NUMBER");
+#endif
+
   // now set the exception handler
 #ifdef XP_LINUX
   MinidumpDescriptor descriptor(tempPath.get());
 #endif
 
   gExceptionHandler = new google_breakpad::
     ExceptionHandler(
 #ifdef XP_LINUX