16235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski/*
26235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * Copyright (C) 2016 The Android Open Source Project
36235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski *
46235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * Licensed under the Apache License, Version 2.0 (the "License");
56235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * you may not use this file except in compliance with the License.
66235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * You may obtain a copy of the License at
76235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski *
86235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski *      http://www.apache.org/licenses/LICENSE-2.0
96235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski *
106235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * Unless required by applicable law or agreed to in writing, software
116235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * distributed under the License is distributed on an "AS IS" BASIS,
126235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * See the License for the specific language governing permissions and
146235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * limitations under the License.
156235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski */
166235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
176235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski#include <fcntl.h>
186235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
196235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski#include "JNIHelp.h"
206235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski#include "core_jni_helpers.h"
216235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski#include "jni.h"
22834763b2ab872bf31a5d6ad9dcb0f76a6aad82fcMark Salyzyn#include <private/android_logger.h>
236235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
246235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski// The size of the tag number comes out of the payload size.
256235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
266235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
276235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskinamespace android {
286235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
296235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jclass gCollectionClass;
306235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jmethodID gCollectionAddID;
316235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
326235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jclass gEventClass;
336235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jmethodID gEventInitID;
346235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
356235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jclass gIntegerClass;
366235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jfieldID gIntegerValueID;
376235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
386235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jclass gLongClass;
396235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jfieldID gLongValueID;
406235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
416235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jclass gFloatClass;
426235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jfieldID gFloatValueID;
436235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
446235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jclass gStringClass;
456235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
466235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
476235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jboolean android_app_admin_SecurityLog_isLoggingEnabled(JNIEnv* env,
486235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                                    jobject /* clazz */) {
496235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    return (bool)__android_log_security();
506235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
516235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
526235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jint android_app_admin_SecurityLog_writeEvent_String(JNIEnv* env,
536235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                                    jobject /* clazz */,
546235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                                    jint tag, jstring value) {
556235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    uint8_t buf[MAX_EVENT_PAYLOAD];
566235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
576235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    // Don't throw NPE -- I feel like it's sort of mean for a logging function
586235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    // to be all crashy if you pass in NULL -- but make the NULL value explicit.
596235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
606235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    uint32_t len = strlen(str);
616235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    size_t max = sizeof(buf) - sizeof(len) - 2;  // Type byte, final newline
626235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (len > max) len = max;
636235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
646235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    buf[0] = EVENT_TYPE_STRING;
656235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    memcpy(&buf[1], &len, sizeof(len));
666235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    memcpy(&buf[1 + sizeof(len)], str, len);
676235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    buf[1 + sizeof(len) + len] = '\n';
686235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
696235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (value != NULL) env->ReleaseStringUTFChars(value, str);
706235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    return __android_log_security_bwrite(tag, buf, 2 + sizeof(len) + len);
716235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
726235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
736235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic jint android_app_admin_SecurityLog_writeEvent_Array(JNIEnv* env, jobject clazz,
746235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                                   jint tag, jobjectArray value) {
756235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (value == NULL) {
766235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return android_app_admin_SecurityLog_writeEvent_String(env, clazz, tag, NULL);
776235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
786235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
796235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    uint8_t buf[MAX_EVENT_PAYLOAD];
806235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    const size_t max = sizeof(buf) - 1;  // leave room for final newline
816235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    size_t pos = 2;  // Save room for type tag & array count
826235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
836235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    jsize copied = 0, num = env->GetArrayLength(value);
846235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    for (; copied < num && copied < 255; ++copied) {
856235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jobject item = env->GetObjectArrayElement(value, copied);
866235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
876235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (pos + 1 + sizeof(jint) > max) break;
886235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
896235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            jint len = strlen(str);
906235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
916235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            buf[pos++] = EVENT_TYPE_STRING;
926235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            memcpy(&buf[pos], &len, sizeof(len));
936235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            memcpy(&buf[pos + sizeof(len)], str, len);
946235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            pos += sizeof(len) + len;
956235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
966235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        } else if (env->IsInstanceOf(item, gIntegerClass)) {
976235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            jint intVal = env->GetIntField(item, gIntegerValueID);
986235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (pos + 1 + sizeof(intVal) > max) break;
996235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            buf[pos++] = EVENT_TYPE_INT;
1006235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            memcpy(&buf[pos], &intVal, sizeof(intVal));
1016235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            pos += sizeof(intVal);
1026235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        } else if (env->IsInstanceOf(item, gLongClass)) {
1036235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            jlong longVal = env->GetLongField(item, gLongValueID);
1046235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (pos + 1 + sizeof(longVal) > max) break;
1056235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            buf[pos++] = EVENT_TYPE_LONG;
1066235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            memcpy(&buf[pos], &longVal, sizeof(longVal));
1076235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            pos += sizeof(longVal);
1086235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        } else if (env->IsInstanceOf(item, gFloatClass)) {
1096235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            jfloat floatVal = env->GetFloatField(item, gFloatValueID);
1106235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (pos + 1 + sizeof(floatVal) > max) break;
1116235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            buf[pos++] = EVENT_TYPE_FLOAT;
1126235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            memcpy(&buf[pos], &floatVal, sizeof(floatVal));
1136235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            pos += sizeof(floatVal);
1146235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        } else {
1156235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            jniThrowException(env,
1166235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                    "java/lang/IllegalArgumentException",
1176235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                    "Invalid payload item type");
1186235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            return -1;
1196235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        }
1206235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        env->DeleteLocalRef(item);
1216235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
1226235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1236235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    buf[0] = EVENT_TYPE_LIST;
1246235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    buf[1] = copied;
1256235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    buf[pos++] = '\n';
1266235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    return __android_log_security_bwrite(tag, buf, pos);
1276235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
1286235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1296235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) {
1306235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    struct logger_list *logger_list;
1316235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (startTime) {
1326235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        logger_list = android_logger_list_alloc_time(loggerMode,
1336235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
1346235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    } else {
1356235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        logger_list = android_logger_list_alloc(loggerMode, 0, 0);
1366235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
1376235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (!logger_list) {
1386235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jniThrowIOException(env, errno);
1396235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return;
1406235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
1416235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1426235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (!android_logger_open(logger_list, LOG_ID_SECURITY)) {
1436235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jniThrowIOException(env, errno);
1446235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        android_logger_list_free(logger_list);
1456235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return;
1466235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
1476235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1486235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    while (1) {
1496235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        log_msg log_msg;
1506235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        int ret = android_logger_list_read(logger_list, &log_msg);
1516235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1526235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        if (ret == 0) {
1536235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            break;
1546235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        }
1556235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        if (ret < 0) {
1566235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (ret == -EINTR) {
1576235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                continue;
1586235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            }
1596235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            if (ret == -EINVAL) {
1606235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                jniThrowException(env, "java/io/IOException", "Event too short");
1616235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            } else if (ret != -EAGAIN) {
1626235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                jniThrowIOException(env, -ret);  // Will throw on return
1636235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            }
1646235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            break;
1656235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        }
1666235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1676235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        if (log_msg.id() != LOG_ID_SECURITY) {
1686235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            continue;
1696235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        }
1706235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1716235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jsize len = ret;
1726235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jbyteArray array = env->NewByteArray(len);
1736235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        if (array == NULL) {
1746235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            break;
1756235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        }
1766235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1776235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jbyte *bytes = env->GetByteArrayElements(array, NULL);
1786235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        memcpy(bytes, log_msg.buf, len);
1796235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        env->ReleaseByteArrayElements(array, bytes, 0);
1806235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1816235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jobject event = env->NewObject(gEventClass, gEventInitID, array);
1826235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        if (event == NULL) {
1836235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            break;
1846235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        }
1856235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1866235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        env->CallBooleanMethod(out, gCollectionAddID, event);
1876235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        env->DeleteLocalRef(event);
1886235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        env->DeleteLocalRef(array);
1896235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
1906235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1916235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    android_logger_list_close(logger_list);
1926235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
1936235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1946235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* clazz */,
1956235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                             jobject out) {
1966235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
1976235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (out == NULL) {
1986235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jniThrowNullPointerException(env, NULL);
1996235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return;
2006235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
2016235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out);
2026235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
2036235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2046235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */,
2056235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                             jlong timestamp,
2066235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                             jobject out) {
2076235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2086235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (out == NULL) {
2096235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jniThrowNullPointerException(env, NULL);
2106235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return;
2116235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
2126235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out);
2136235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
2146235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2156235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */,
2166235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                             jobject out) {
2176235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2186235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (out == NULL) {
2196235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jniThrowNullPointerException(env, NULL);
2206235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return;
2216235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
2226235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out);
2236235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
2246235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2256235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */,
2266235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                             jlong timestamp,
2276235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                                             jobject out) {
2286235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    if (out == NULL) {
2296235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jniThrowNullPointerException(env, NULL);
2306235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        return;
2316235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
2326235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out);
2336235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
2346235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2356235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski/*
2366235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski * JNI registration.
2376235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski */
2386235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic const JNINativeMethod gRegisterMethods[] = {
2396235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    /* name, signature, funcPtr */
2406235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "isLoggingEnabled",
2416235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "()Z",
2426235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_isLoggingEnabled
2436235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2446235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "writeEvent",
2456235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "(ILjava/lang/String;)I",
2466235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_writeEvent_String
2476235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2486235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "writeEvent",
2496235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "(I[Ljava/lang/Object;)I",
2506235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_writeEvent_Array
2516235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2526235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "readEvents",
2536235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "(Ljava/util/Collection;)V",
2546235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_readEvents
2556235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2566235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "readEventsSince",
2576235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "(JLjava/util/Collection;)V",
2586235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_readEventsSince
2596235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2606235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "readPreviousEvents",
2616235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "(Ljava/util/Collection;)V",
2626235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_readPreviousEvents
2636235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2646235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "readEventsOnWrapping",
2656235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      "(JLjava/util/Collection;)V",
2666235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski      (void*) android_app_admin_SecurityLog_readEventsOnWrapping
2676235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    },
2686235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski};
2696235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2706235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic struct { const char *name; jclass *clazz; } gClasses[] = {
2716235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "android/app/admin/SecurityLog$SecurityEvent", &gEventClass },
2726235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "java/lang/Integer", &gIntegerClass },
2736235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "java/lang/Long", &gLongClass },
2746235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "java/lang/Float", &gFloatClass },
2756235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "java/lang/String", &gStringClass },
2766235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { "java/util/Collection", &gCollectionClass },
2776235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski};
2786235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2796235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
2806235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { &gIntegerClass, "value", "I", &gIntegerValueID },
2816235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { &gLongClass, "value", "J", &gLongValueID },
2826235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { &gFloatClass, "value", "F", &gFloatValueID },
2836235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski};
2846235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2856235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskistatic struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
2866235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { &gEventClass, "<init>", "([B)V", &gEventInitID },
2876235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
2886235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski};
2896235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2906235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinskiint register_android_app_admin_SecurityLog(JNIEnv* env) {
2916235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    for (int i = 0; i < NELEM(gClasses); ++i) {
2926235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        jclass clazz = FindClassOrDie(env, gClasses[i].name);
2936235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
2946235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
2956235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
2966235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    for (int i = 0; i < NELEM(gFields); ++i) {
2976235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        *gFields[i].id = GetFieldIDOrDie(env,
2986235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                *gFields[i].c, gFields[i].name, gFields[i].ft);
2996235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
3006235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
3016235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    for (int i = 0; i < NELEM(gMethods); ++i) {
3026235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski        *gMethods[i].id = GetMethodIDOrDie(env,
3036235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski                *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
3046235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    }
3056235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
3066235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski    return RegisterMethodsOrDie(
3076235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            env,
3086235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            "android/app/admin/SecurityLog",
3096235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski            gRegisterMethods, NELEM(gRegisterMethods));
3106235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}
3116235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski
3126235a94ffaed1d82cee2317481c18776f601da1bMichal Karpinski}; // namespace android
313