158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate/* 258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Copyright (C) 2013 The Android Open Source Project 358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * 458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License"); 558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * you may not use this file except in compliance with the License. 658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * You may obtain a copy of the License at 758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * 858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * http://www.apache.org/licenses/LICENSE-2.0 958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * 1058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Unless required by applicable law or agreed to in writing, software 1158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS, 1258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * See the License for the specific language governing permissions and 1458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * limitations under the License. 1558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate */ 1658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 1758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tatepackage com.android.server.am; 1858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 1958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tateimport android.app.ApplicationErrorReport.CrashInfo; 20cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughesimport android.system.ErrnoException; 21cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughesimport android.system.Os; 22cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughesimport android.system.StructTimeval; 23e9d537506bf19375fb932ac7d25ac9a9e3aef61dNeil Fullerimport android.system.UnixSocketAddress; 2458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tateimport android.util.Slog; 2558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 26cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughesimport static android.system.OsConstants.*; 2758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 2858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tateimport java.io.ByteArrayOutputStream; 2958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tateimport java.io.File; 3058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tateimport java.io.FileDescriptor; 3143582df3dbcad1b1734b570c74246f5ff2f58027Neil Fullerimport java.io.InterruptedIOException; 3258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tateimport java.net.InetSocketAddress; 3358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 3458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate/** 3558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Set up a Unix domain socket that debuggerd will connect() to in 3658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * order to write a description of a native crash. The crash info is 3758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * then parsed and forwarded to the ActivityManagerService's normal 3858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * crash handling code. 3958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * 4058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Note that this component runs in a separate thread. 4158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate */ 42be4e6aaa0252dd7da28b7aa85beba982538efa46Dianne Hackbornfinal class NativeCrashListener extends Thread { 4358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate static final String TAG = "NativeCrashListener"; 4458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate static final boolean DEBUG = false; 451b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate static final boolean MORE_DEBUG = DEBUG && false; 4658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 4758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // Must match the path defined in debuggerd.c. 4858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate static final String DEBUGGERD_SOCKET_PATH = "/data/system/ndebugsocket"; 4958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 5058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // Use a short timeout on socket operations and abandon the connection 51404fd65e436df7600bbb1b495720f8d1288b0d9dChristopher Tate // on hard errors, just in case debuggerd goes out to lunch. 52404fd65e436df7600bbb1b495720f8d1288b0d9dChristopher Tate static final long SOCKET_TIMEOUT_MILLIS = 10000; // 10 seconds 5358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 5458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate final ActivityManagerService mAm; 5558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 5658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate /* 5758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Spin the actual work of handling a debuggerd crash report into a 5858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * separate thread so that the listener can go immediately back to 5958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * accepting incoming connections. 6058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate */ 6158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate class NativeCrashReporter extends Thread { 6258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate ProcessRecord mApp; 6358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int mSignal; 6458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate String mCrashReport; 6558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 6658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate NativeCrashReporter(ProcessRecord app, int signal, String report) { 6758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate super("NativeCrashReport"); 6858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate mApp = app; 6958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate mSignal = signal; 7058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate mCrashReport = report; 7158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 7258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 7358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate @Override 7458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate public void run() { 7558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate try { 7658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate CrashInfo ci = new CrashInfo(); 7758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate ci.exceptionClassName = "Native crash"; 78cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes ci.exceptionMessage = Os.strsignal(mSignal); 7958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate ci.throwFileName = "unknown"; 8058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate ci.throwClassName = "unknown"; 8158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate ci.throwMethodName = "unknown"; 8258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate ci.stackTrace = mCrashReport; 8358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 8458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (DEBUG) Slog.v(TAG, "Calling handleApplicationCrash()"); 8588d842cf8a3adcae5cd2d243dcc182c96f40db29Eric Rowe mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci); 8658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (DEBUG) Slog.v(TAG, "<-- handleApplicationCrash() returned"); 8758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } catch (Exception e) { 8858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.e(TAG, "Unable to report native crash", e); 8958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 9058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 9158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 9258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 9358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate /* 9458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * Daemon thread that accept()s incoming domain socket connections from debuggerd 9558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate * and processes the crash dump that is passed through. 9658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate */ 974ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown NativeCrashListener(ActivityManagerService am) { 984ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown mAm = am; 9958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 10058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 10158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate @Override 10258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate public void run() { 10358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate final byte[] ackSignal = new byte[1]; 10458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 10558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (DEBUG) Slog.i(TAG, "Starting up"); 10658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 107b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // The file system entity for this socket is created with 0777 perms, owned 108b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // by system:system. selinux restricts things so that only crash_dump can 109b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // access it. 11058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate { 11158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate File socketFile = new File(DEBUGGERD_SOCKET_PATH); 11258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (socketFile.exists()) { 11358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate socketFile.delete(); 11458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 11558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 11658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 11758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate try { 118cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes FileDescriptor serverFd = Os.socket(AF_UNIX, SOCK_STREAM, 0); 119e9d537506bf19375fb932ac7d25ac9a9e3aef61dNeil Fuller final UnixSocketAddress sockAddr = UnixSocketAddress.createFileSystem( 120e9d537506bf19375fb932ac7d25ac9a9e3aef61dNeil Fuller DEBUGGERD_SOCKET_PATH); 121e9d537506bf19375fb932ac7d25ac9a9e3aef61dNeil Fuller Os.bind(serverFd, sockAddr); 122cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes Os.listen(serverFd, 1); 123b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao Os.chmod(DEBUGGERD_SOCKET_PATH, 0777); 12458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 12558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate while (true) { 12658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate FileDescriptor peerFd = null; 12758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate try { 1281b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate if (MORE_DEBUG) Slog.v(TAG, "Waiting for debuggerd connection"); 129e64f3e3fee8933f2703f616f656583b3923d1b8fNeil Fuller peerFd = Os.accept(serverFd, null /* peerAddress */); 1301b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate if (MORE_DEBUG) Slog.v(TAG, "Got debuggerd socket " + peerFd); 13158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (peerFd != null) { 132b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // the reporting thread may take responsibility for 133b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // acking the debugger; make sure we play along. 134b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao consumeNativeCrashData(peerFd); 13558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 13658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } catch (Exception e) { 13758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.w(TAG, "Error handling connection", e); 13858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } finally { 139b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // Always ack crash_dump's connection to us. The actual 14058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // byte written is irrelevant. 14158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (peerFd != null) { 14258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate try { 143cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes Os.write(peerFd, ackSignal, 0, 1); 1441b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate } catch (Exception e) { 1451b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate /* we don't care about failures here */ 1461b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate if (MORE_DEBUG) { 1471b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate Slog.d(TAG, "Exception writing ack: " + e.getMessage()); 1481b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate } 1491b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate } 1501b2d59500a8c066dec413f906c480ee46f004df5Nick Kralevich try { 151cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes Os.close(peerFd); 1521b2d59500a8c066dec413f906c480ee46f004df5Nick Kralevich } catch (ErrnoException e) { 1531b2d59500a8c066dec413f906c480ee46f004df5Nick Kralevich if (MORE_DEBUG) { 1541b2d59500a8c066dec413f906c480ee46f004df5Nick Kralevich Slog.d(TAG, "Exception closing socket: " + e.getMessage()); 1551b2d59500a8c066dec413f906c480ee46f004df5Nick Kralevich } 1561b2d59500a8c066dec413f906c480ee46f004df5Nick Kralevich } 15758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 15858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 15958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 16058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } catch (Exception e) { 16158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.e(TAG, "Unable to init native debug socket!", e); 16258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 16358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 16458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 16558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate static int unpackInt(byte[] buf, int offset) { 16658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int b0, b1, b2, b3; 16758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 16858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate b0 = ((int) buf[offset]) & 0xFF; // mask against sign extension 16958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate b1 = ((int) buf[offset+1]) & 0xFF; 17058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate b2 = ((int) buf[offset+2]) & 0xFF; 17158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate b3 = ((int) buf[offset+3]) & 0xFF; 17258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; 17358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 17458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 17558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate static int readExactly(FileDescriptor fd, byte[] buffer, int offset, int numBytes) 17643582df3dbcad1b1734b570c74246f5ff2f58027Neil Fuller throws ErrnoException, InterruptedIOException { 17758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int totalRead = 0; 17858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate while (numBytes > 0) { 179cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes int n = Os.read(fd, buffer, offset + totalRead, numBytes); 18058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (n <= 0) { 18158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (DEBUG) { 18258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.w(TAG, "Needed " + numBytes + " but saw " + n); 18358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 18458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate return -1; // premature EOF or timeout 18558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 18658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate numBytes -= n; 18758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate totalRead += n; 18858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 18958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate return totalRead; 19058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 19158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 192b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // Read a crash report from the connection 19358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate void consumeNativeCrashData(FileDescriptor fd) { 1941b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate if (MORE_DEBUG) Slog.i(TAG, "debuggerd connected"); 19558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate final byte[] buf = new byte[4096]; 19658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate final ByteArrayOutputStream os = new ByteArrayOutputStream(4096); 19758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 19858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate try { 19958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate StructTimeval timeout = StructTimeval.fromMillis(SOCKET_TIMEOUT_MILLIS); 200cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout); 201cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout); 20258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 203b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // The socket is guarded by an selinux neverallow rule that only 204b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // permits crash_dump to connect to it. This allows us to trust the 205b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao // received values. 206b9eb093c3cb49c3ac44823d5a0d818e66b9bbcd3Josh Gao 20758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // first, the pid and signal number 20858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int headerBytes = readExactly(fd, buf, 0, 8); 20958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (headerBytes != 8) { 21058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // protocol failure; give up 21158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.e(TAG, "Unable to read from debuggerd"); 21258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate return; 21358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 21458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 21558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int pid = unpackInt(buf, 0); 21658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int signal = unpackInt(buf, 4); 21758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (DEBUG) { 21858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.v(TAG, "Read pid=" + pid + " signal=" + signal); 21958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 22058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 22158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // now the text of the dump 22258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (pid > 0) { 22358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate final ProcessRecord pr; 22458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate synchronized (mAm.mPidsSelfLocked) { 22558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate pr = mAm.mPidsSelfLocked.get(pid); 22658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 22758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (pr != null) { 228b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate // Don't attempt crash reporting for persistent apps 229b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate if (pr.persistent) { 230b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate if (DEBUG) { 231b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate Slog.v(TAG, "Skipping report for persistent app " + pr); 232b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate } 233b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate return; 234b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate } 235b86d81d3ff1beb46b18795edbbb8850e9cde4c98Christopher Tate 23658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate int bytes; 23758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate do { 23858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // get some data 239cacbe1b1ef01aff8726726edaf43d0b449319afeElliott Hughes bytes = Os.read(fd, buf, 0, buf.length); 24058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (bytes > 0) { 2411b645986020a5bd66f6783fa87b9f084c809d801Christopher Tate if (MORE_DEBUG) { 24258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate String s = new String(buf, 0, bytes, "UTF-8"); 24358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.v(TAG, "READ=" + bytes + "> " + s); 24458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 24558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // did we just get the EOD null byte? 24658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (buf[bytes-1] == 0) { 24758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate os.write(buf, 0, bytes-1); // exclude the EOD token 24858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate break; 24958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 25058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // no EOD, so collect it and read more 25158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate os.write(buf, 0, bytes); 25258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 25358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } while (bytes > 0); 25458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 25558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // Okay, we've got the report. 25658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate if (DEBUG) Slog.v(TAG, "processing"); 25758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 25858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // Mark the process record as being a native crash so that the 25958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // cleanup mechanism knows we're still submitting the report 26058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // even though the process will vanish as soon as we let 26158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // debuggerd proceed. 26258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate synchronized (mAm) { 26358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate pr.crashing = true; 26458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate pr.forceCrashReport = true; 26558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 26658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 26758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // Crash reporting is synchronous but we want to let debuggerd 26858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // go about it business right away, so we spin off the actual 26958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // reporting logic on a thread and let it take it's time. 27058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate final String reportString = new String(os.toByteArray(), "UTF-8"); 27158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate (new NativeCrashReporter(pr, signal, reportString)).start(); 27258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } else { 27358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid); 27458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 27558d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } else { 27658d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.e(TAG, "Bogus pid!"); 27758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 27858d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } catch (Exception e) { 27958d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate Slog.e(TAG, "Exception dealing with report", e); 28058d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate // ugh, fail. 28158d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 28258d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate } 28358d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate 28458d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate} 285