logcatコマンドを使用してlogdホワイトリストのブラックリストを追加


logdのホワイトリストとブラックリストは前のlogdで分析しましたが、ここのホワイトリストとブラックリストはlogdがlogを失ったときに使用されるだけです.logdがlogを失うと、ブラックリストのlogが削除され、通常のlogが削除されます.最後に足りなければホワイトリストのロゴを削除します.
このコマンドはデバッグに役立ちますが、本質的な原因はcpuスケジューリングが不十分でlogが多すぎて失われます.
コマンドの使用
まずlogcatのhelpを見て、下の-p(小文字)はホワイトリストとブラックリストを取得することを表し、-P(大文字)はホワイトリストとブラックリストを設定することを表します.注意-Pの後に引用符が付いている
  -p              print prune white and ~black list. Service is specified as
                  UID, UID/PID or /PID. Weighed for quicker pruning if prefix
                  with ~, otherwise weighed for longevity if unadorned. All
                  other pruning activity is oldest first. Special case ~!
                  represents an automatic quicker pruning for the noisiest
                  UID as determined by the current statistics.
  -P ' ...' set prune white and ~black list, using same format as
                  printed above. Must be quoted.
uid 1000をホワイトリストに設定2002をブラックリストに設定
logcat -P '1000 ~2002'

logcat-pクエリーの使用
root@lte26007:/ # logcat -p
1000 ~2002

もちろんpidも使えます
uid:logcat-P uidのみPid:logcat-P/pidのみuid+pid:logcat-P uid/pid
二、コード
2.1 logcat
logcat処理Pコマンドの場合、文字列をsetPruneListに配置し、android_を呼び出すlogger_set_prune_リスト関数
    case 'P':
        setPruneList = optarg;
    break;
    ......
    if (setPruneList) {
        size_t len = strlen(setPruneList);
        /*extra 32 bytes are needed by  android_logger_set_prune_list */
        size_t bLen = len + 32;
        char *buf = NULL;
        if (asprintf(&buf, "%-*s", (int)(bLen - 1), setPruneList) > 0) {
            buf[len] = '\0';
            if (android_logger_set_prune_list(logger_list, buf, bLen)) {
                logcat_panic(false, "failed to set the prune list");
            }
            free(buf);
        } else {
            logcat_panic(false, "failed to set the prune list (alloc)");
        }
    }

android_logger_set_prune_List関数とは、setPruneListコマンドをlogdに送信することです
int android_logger_set_prune_list(struct logger_list *logger_list __unused,
                                  char *buf, size_t len)
{
    const char cmd[] = "setPruneList ";
    const size_t cmdlen = sizeof(cmd) - 1;

    if (strlen(buf) > (len - cmdlen)) {
        return -ENOMEM; /* KISS */
    }
    memmove(buf + cmdlen, buf, len - cmdlen);
    buf[len - 1] = '\0';
    memcpy(buf, cmd, cmdlen);

    return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
}

send_log_msgはlogdのsocketを取得し,writeする.
static ssize_t send_log_msg(struct logger *logger,
                            const char *msg, char *buf, size_t buf_size)
{
    ssize_t ret;
    size_t len;
    char *cp;
    int errno_save = 0;
    int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
                                   SOCK_STREAM);
    if (sock < 0) {
        return sock;
    }

    if (msg) {
        snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
    }

    len = strlen(buf) + 1;
    ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
    if (ret <= 0) {
        goto done;
    }

    len = buf_size;
    cp = buf;
    while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
        struct pollfd p;

        if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
            break;
        }

        len -= ret;
        cp += ret;

        memset(&p, 0, sizeof(p));
        p.fd = sock;
        p.events = POLLIN;

        /* Give other side 20ms to refill pipe */
        ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));

        if (ret <= 0) {
            break;
        }

        if (!(p.revents & POLLIN)) {
            ret = 0;
            break;
        }
    }

    if (ret >= 0) {
        ret += buf_size - len;
    }

done:
    if ((ret == -1) && errno) {
        errno_save = errno;
    }
    close(sock);
    if (errno_save) {
        errno = errno_save;
    }
    return ret;
}

2.2 logd
logdのコード処理を見てみましょう
2.2.1ホワイトブラックリストの設定
int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
                                         int argc, char **argv) {
    setname();
    if (!clientHasLogCredentials(cli)) {
        cli->sendMsg("Permission Denied");
        return 0;
    }

    char *cp = NULL;
    for (int i = 1; i < argc; ++i) {
        char *p = cp;
        if (p) {
            cp = NULL;
            asprintf(&cp, "%s %s", p, argv[i]);
            free(p);
        } else {
            asprintf(&cp, "%s", argv[i]);
        }
    }

    int ret = mBuf.initPrune(cp);
    free(cp);

    if (ret) {
        cli->sendMsg("Invalid");
        return 0;
    }

    cli->sendMsg("success");

    return 0;
}

ここでは主にLogBufferのinitPrune関数を呼び出します
    int initPrune(char *cp) { return mPrune.init(cp); }

この関数はまたPruneListのinit関数を呼び出し,この関数を見てみよう.まず、白と黒のリストをクリアし、入力された文字列の最初のアルファベットに基づいて~または!この部分はブラックリストです.そうしないとホワイトリストです.その後、uid、pidを処理してリストに追加する(ここでリストはmNaughtyかmNiceか)
int PruneList::init(char *str) {
    mWorstUidEnabled = true;
    PruneCollection::iterator it;
    for (it = mNice.begin(); it != mNice.end();) {//     
        it = mNice.erase(it);
    }
    for (it = mNaughty.begin(); it != mNaughty.end();) {//     
        it = mNaughty.erase(it);
    }

    if (!str) {
        return 0;
    }

    mWorstUidEnabled = false;

    for(; *str; ++str) {
        if (isspace(*str)) {
            continue;
        }

        PruneCollection *list;
        if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
            ++str;
            // special case, translates to worst UID at priority in blacklist
            if (*str == '!') {
                mWorstUidEnabled = true;
                ++str;
                if (!*str) {
                    break;
                }
                if (!isspace(*str)) {
                    return 1;
                }
                continue;
            }
            if (!*str) {
                return 1;
            }
            list = &mNaughty;// ~  !           
        } else {
            list = &mNice;//       
        }

        uid_t uid = Prune::uid_all;
        if (isdigit(*str)) {//uid
            uid = 0;
            do {
                uid = uid * 10 + *str++ - '0';
            } while (isdigit(*str));
        }

        pid_t pid = Prune::pid_all;
        if (*str == '/') {// /  pid
            ++str;
            if (isdigit(*str)) {
                pid = 0;
                do {
                    pid = pid * 10 + *str++ - '0';
                } while (isdigit(*str));
            }
        }

        if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
            return 1;
        }

        if (*str && !isspace(*str)) {
            return 1;
        }

        // insert sequentially into list
        PruneCollection::iterator it = list->begin();
        while (it != list->end()) {
            Prune &p = *it;
            int m = uid - p.mUid;
            if (m == 0) {
                if (p.mPid == p.pid_all) {
                    break;
                }
                if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
                    it = list->erase(it);
                    continue;
                }
                m = pid - p.mPid;
            }
            if (m <= 0) {
                if (m < 0) {
                    list->insert(it, Prune(uid,pid));
                }
                break;
            }
            ++it;
        }
        if (it == list->end()) {
            list->push_back(Prune(uid,pid));//  list,   list            
        }
        if (!*str) {
            break;
        }
    }

    return 0;
}

最後にホワイトリストかブラックリストかを判断するのは以下の関数で、最終的にはmNaughtyとmNiceリストが一致しているかどうかを見ます.
bool PruneList::naughty(LogBufferElement *element) {
    PruneCollection::iterator it;
    for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
        if (!(*it).cmp(element)) {
            return true;
        }
    }
    return false;
}

bool PruneList::nice(LogBufferElement *element) {
    PruneCollection::iterator it;
    for (it = mNice.begin(); it != mNice.end(); ++it) {
        if (!(*it).cmp(element)) {
            return true;
        }
    }
    return false;
}

2.2ホワイト・ブラックリストの取得
ホワイトブラックリストのロゴを取得するコードは見ませんが、最終的にはmNiceとmNaughtyの取得をロゴに渡して表示する関数です.
void PruneList::format(char **strp) {
    if (*strp) {
        free(*strp);
        *strp = NULL;
    }

    static const char nice_format[] = " %s";
    const char *fmt = nice_format + 1;

    android::String8 string;

    if (mWorstUidEnabled) {
        string.setTo("~!");
        fmt = nice_format;
    }

    PruneCollection::iterator it;

    for (it = mNice.begin(); it != mNice.end(); ++it) {
        char *a = NULL;
        (*it).format(&a);

        string.appendFormat(fmt, a);
        fmt = nice_format;

        free(a);
    }

    static const char naughty_format[] = " ~%s";
    fmt = naughty_format + (*fmt != ' ');
    for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
        char *a = NULL;
        (*it).format(&a);

        string.appendFormat(fmt, a);
        fmt = naughty_format;

        free(a);
    }

    *strp = strdup(string.string());
}