blob: f788a901a8e9bfaf0088c9086da2bb0740f858a4 [file] [log] [blame]
Preeti Nagar473a35c2018-04-03 16:34:25 +05301/*
2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2007-2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#include <errno.h>
21#include <fcntl.h>
22#include <stdarg.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/un.h>
30#include <unistd.h>
31#include <assert.h>
32#include <cutils/properties.h>
33#include <utils/String8.h>
34#include <android_runtime/Log.h>
35#include <utils/Log.h>
36#ifdef __BIONIC__
37#include <android/set_abort_message.h>
38#endif
39#include <utils/Log.h>
40
41
42#include "jni.h"
43#include <nativehelper/JNIHelp.h>
44#include "utils/misc.h"
45#include "android_runtime/AndroidRuntime.h"
46
47#define LOG_BUF_SIZE 1024
48#define SEEMP_SOCK_NAME "/dev/socket/seempdw"
49#define ZYGOTE_PARENT_PID 1
50#ifndef __unused
51#define __unused __attribute__((__unused__))
52#endif
53
54static int __write_to_log_init(struct iovec *vec, size_t nr);
55static int (*write_to_log)(struct iovec *vec, size_t nr) = __write_to_log_init;
56static int logd_fd = -1;
57
58/* give up, resources too limited */
59static int __write_to_log_null(struct iovec *vec __unused,
60 size_t nr __unused)
61{
62 return -1;
63}
64
65/* log_init_lock assumed */
66static int __write_to_log_initialize()
67{
68 int i, ret = 0;
69 if (logd_fd >= 0) {
70 i = logd_fd;
71 logd_fd = -1;
72 close(i);
73 }
74
75 i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
76 if (i < 0) {
77 ret = -errno;
78 write_to_log = __write_to_log_null;
79 } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) {
80 ret = -errno;
81 close(i);
82 i = -1;
83 write_to_log = __write_to_log_null;
84 } else {
85 struct sockaddr_un un;
86 memset(&un, 0, sizeof(struct sockaddr_un));
87 un.sun_family = AF_UNIX;
88 strlcpy(un.sun_path, SEEMP_SOCK_NAME, sizeof(un.sun_path));
89 if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) {
90 ret = -errno;
91 close(i);
92 i = -1;
93 }
94 }
95 logd_fd = i;
96 return ret;
97}
98
99static int __write_to_log_socket(struct iovec *vec, size_t nr)
100{
101 ssize_t ret;
102 if (logd_fd < 0) {
103 return -EBADF;
104 }
105
106 /*
107 * The write below could be lost, but will never block.
108 *
109 * ENOTCONN occurs if logd dies.
110 * EAGAIN occurs if logd is overloaded.
111 */
112 ret = writev(logd_fd, vec, nr);
113 if (ret < 0) {
114 ret = -errno;
115 if (ret == -ENOTCONN) {
116 ret = __write_to_log_initialize();
117 if (ret < 0) {
118 return ret;
119 }
120
121 ret = writev(logd_fd, vec, nr);
122 if (ret < 0) {
123 ret = -errno;
124 }
125 }
126 }
127
128 return ret;
129}
130
131static int __write_to_log_init(struct iovec *vec, size_t nr)
132{
133 if (write_to_log == __write_to_log_init) {
134
135 if (getppid() == ZYGOTE_PARENT_PID) {
136 return 0;
137 }
138
139 int ret;
140
141 ret = __write_to_log_initialize();
142 if (ret < 0) {
143 return ret;
144 }
145
146 write_to_log = __write_to_log_socket;
147 }
148 return write_to_log(vec, nr);
149}
150
151int __android_seemp_socket_write(int len, const char *msg)
152{
153 struct iovec vec;
154 vec.iov_base = (void *) msg;
155 vec.iov_len = len;
156
157 return write_to_log(&vec, 1);
158}
159
160namespace android {
161
162/*
163 * In class android.util.Log:
164 * public static native int println_native(int buffer, int priority, String tag, String msg)
165 */
166static jint android_util_SeempLog_println_native(JNIEnv* env, jobject clazz,
167 jint api, jstring msgObj)
168{
169 if (msgObj == NULL) {
170 jniThrowNullPointerException(env, "seemp_println needs a message");
171 return -1;
172 }
173
174 int apiId = (int)api;
175 int apiIdLen = sizeof(apiId);
176 int utf8MsgLen = env->GetStringUTFLength(msgObj);
177 int len = apiIdLen + 1 + utf8MsgLen + 1;
178 char *msg = (char*)malloc(len);
179 if ( NULL == msg )
180 {
181 return -1;
182 }
183 char *params = msg + apiIdLen + 1; // api_id + encoding byte + params
184
185 *((int*)msg) = apiId; // copy api id
186 // // skip encoding byte
187 env->GetStringUTFRegion(msgObj, 0, env->GetStringLength(msgObj), params); // copy message
188 msg[len - 1] = 0; // copy terminating zero
189
190 int res = __android_seemp_socket_write(len, msg); // send message
191
192 free(msg);
193
194 return res;
195}
196
197/*
198 * JNI registration.
199 */
200static JNINativeMethod gMethods[] = {
201 /* name, signature, funcPtr */
202 { "seemp_println_native", "(ILjava/lang/String;)I",
203 (void*) android_util_SeempLog_println_native },
204};
205
206int register_android_util_SeempLog(JNIEnv* env)
207{
208 jclass clazz = env->FindClass("android/util/SeempLog");
209 if (clazz == NULL) {
210 return -1;
211 }
212
213 return AndroidRuntime::registerNativeMethods(env, "android/util/SeempLog", gMethods,
214 NELEM(gMethods));
215}
216
217}; // namespace android