通过源码搞定ANR Log如何产生(三)

1,693 阅读2分钟

接上文

上文提到通过jni调用android_os_Debug_dumpJavaBacktraceToFileTimeout

文件位置在:frameworks/base/core/jni/android_os_Debug.cpp

3.1

      android_os_Debug_dumpJavaBacktraceToFileTimeout(),中又调用了dumpTraces()

      参数 pid = pid,fileName = "/data/anr/anr_Date",timeoutSecs = 20

static jboolean android_os_Debug_dumpJavaBacktraceToFileTimeout(JNIEnv* env, jobject clazz,
        jint pid, jstring fileName, jint timeoutSecs) {
    const bool ret = dumpTraces(env, pid, fileName, timeoutSecs, kDebuggerdJavaBacktrace);
    return ret ? JNI_TRUE : JNI_FALSE;
}

3.2

      dumpTraces(),通过c++的open方法,将fd的值设为了"/data/anr/anr_Date"的文件描述符,然后调用dump_backtrace_to_file_timeout()方法

    参数:pid = pid,fileName = "/data/anr/anr_Date",timeoutSecs = 20,dumpType = ”kDebuggerdJavaBacktrace“

static bool dumpTraces(JNIEnv* env, jint pid, jstring fileName, jint timeoutSecs, DebuggerdDumpType dumpType) {
    android::base::unique_fd fd(open(fileNameChars.c_str(),
                                     O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_APPEND,
                                     0666));
    int res = dump_backtrace_to_file_timeout(pid, dumpType, timeoutSecs, fd);
    return res == 0;
}

3.3

     dump_backtrace_to_file_timeout(),调用了debuggerd_trigger_dump()

     参数:pid_t tid = pid,dumpType = ”kDebuggerdJavaBacktrace“,fd = "/data/anr/anr_Date"的文件描述符

int dump_backtrace_to_file_timeout(pid_t tid, DebuggerdDumpType dump_type, int timeout_secs,int fd) {
  android::base::unique_fd copy(dup(fd));
  int timeout_ms = timeout_secs > 0 ? timeout_secs * 1000 : 0;
  return debuggerd_trigger_dump(tid, dump_type, timeout_ms, std::move(copy)) ? 0 : -1;
}

3.4

     debuggerd_trigger_dump(),这个方法会通过socket和别的进程进行通信,获取数据,是一个很重要的方法

        1,首先通过GetProcessInfo()获取ProcessInfo,包括pid

        2,通过socket_local_client_connect(),连接socket name = “kTombstonedInterceptSocketName” 的socket服务端
        3,初始化pipe管道
        4,给socket服务端发送数据
         socket name = “kTombstonedInterceptSocketName” 的socket服务端,在[system](http://axr.htc.com/source/xref/Q_Mainline/system/)/[core](http://axr.htc.com/source/xref/Q_Mainline/system/core/)/[debuggerd](http://axr.htc.com/source/xref/Q_Mainline/system/core/debuggerd/)/[tombstoned](http://axr.htc.com/source/xref/Q_Mainline/system/core/debuggerd/tombstoned/)/[tombstoned.cpp](http://axr.htc.com/source/xref/Q_Mainline/system/core/debuggerd/tombstoned/tombstoned.cpp)的main方法中初始化

        参数:pid_t tid = pid,dumpType = "kDebuggerdJavaBacktrace“,output_fd = "/data/anr/anr_Date"的文件描述符

bool debuggerd_trigger_dump(pid_t tid, DebuggerdDumpType dump_type, unsigned int timeout_ms,unique_fd output_fd) {
  pid_t pid = tid;
  if (dump_type == kDebuggerdJavaBacktrace) {
    // Java dumps always get sent to the tgid, so we need to resolve our tid to a tgid.
    android::procinfo::ProcessInfo procinfo;
    std::string error;
    //GetProcessInfo获取pid对应的procinfo
    if (!android::procinfo::GetProcessInfo(tid, &procinfo, &error)) {
      LOG(ERROR) << "libdebugged_client: failed to get process info: " << error;
      return false;
    }
    pid = procinfo.pid;
  }
  //通过socket_local_client_connect,连接socket name = kTombstonedInterceptSocketName 的socket服务端
  if (socket_local_client_connect(set_timeout(sockfd.get()), kTombstonedInterceptSocketName,
                                  ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET) == -1) {
    PLOG(ERROR) << "libdebuggerd_client: failed to connect to tombstoned";
    return false;
  }
  //初始化request
  InterceptRequest req = {.pid = pid, .dump_type = dump_type}
  // Create an intermediate pipe to pass to the other end.
  unique_fd pipe_read, pipe_write;
  //调用Pipe创建linux中的一种数据传输方式--管道,pipe_read为读出管道中的数据的fd,pipe_write为写入管道的数据的fd
  if (!Pipe(&pipe_read, &pipe_write)) {
    PLOG(ERROR) << "libdebuggerd_client: failed to create pipe";
    return false;
  }  
  //调用SendFileDescriptors()方法,,给sockfd代表的socket服务端发送数据
  //sockfd代表的服务端为socket name = kTombstonedInterceptSocketName 的socket服务端
  //req = {.pid = pid, .dump_type = dump_type = "kDebuggerdJavaBacktrace" }
  ssize_t rc = SendFileDescriptors(set_timeout(sockfd), &req, sizeof(req), pipe_write.get());
}

待续。。。