Merge "Clarify ownership for NativeHandle::mHandle"
diff --git a/adb/SYNC.TXT b/adb/SYNC.TXT
new file mode 100644
index 0000000..e74d217
--- /dev/null
+++ b/adb/SYNC.TXT
@@ -0,0 +1,84 @@
+This file tries to document file related requests a client can make
+to the ADB server of an adbd daemon. See the OVERVIEW.TXT document
+to understand what's going on here. See the SERVICES.TXT to learn more
+about the other requests that are possible.
+
+SYNC SERVICES:
+
+
+Requesting the sync service ("sync:") using the protocol as described in
+SERVICES.TXT sets the connection in sync mode. This mode is a binary mode that
+differ from the regular adb protocol. The connection stays in sync mode until
+explicitly terminated (see below).
+
+After the initial "sync:" command is sent the server must respond with either
+"OKAY" or "FAIL" as per usual.
+
+In sync mode both the server and the client will frequently use eight-byte
+packets to communicate in this document called sync request and sync
+responses. The first four bytes is an id and specifies sync request is
+represented by four utf-8 characters. The last four bytes is a Little-Endian
+integer, with various uses. This number will be called "length" below. In fact
+all binary integers are Little-Endian in the sync mode. Sync mode is
+implicitly exited after each sync request, and normal adb communication
+follows as described in SERVICES.TXT.
+
+The following sync requests are accepted:
+LIST - List the files in a folder
+SEND - Send a file to device
+RECV - Retreive a file from device
+
+Not yet documented:
+STAT - Stat a file
+ULNK - Unlink (remove) a file. (Not currently supported)
+
+For all of the sync request above the must be followed by length number of
+bytes containing an utf-8 string with a remote filename.
+
+LIST:
+Lists files in the directory specified by the remote filename. The server will
+respond with zero or more directory entries or "dents".
+
+The directory entries will be returned in the following form
+1. A four-byte sync response id beeing "DENT"
+2. A four-byte integer representing file mode.
+3. A four-byte integer representing file size.
+4. A four-byte integer representing last modified time.
+5. A four-byte integer representing file name length.
+6. length number of bytes containing an utf-8 string representing the file
+ name.
+
+When an sync response "DONE" is received the listing is done.
+
+SEND:
+The remote file name is split into two parts separated by the last
+comma (","). The first part is the actual path, while the second is a decimal
+encoded file mode containing the permissions of the file on device.
+
+Note that some file types will be deleted before the copying starts, and if
+the transfer fails. Some file types will not be deleted, which allows
+ adb push disk_image /some_block_device
+to work.
+
+After this the actual file is sent in chunks. Each chucks has the following
+format.
+A sync request with id "DATA" and length equal to the chunk size. After
+follows chunk size number of bytes. This is repeated until the file is
+transfered. Each chunk must not be larger than 64k.
+
+When the file is tranfered a sync request "DONE" is sent, where length is set
+to the last modified time for the file. The server responds to this last
+request (but not to chuck requests) with an "OKAY" sync response (length can
+be ignored).
+
+
+RECV:
+Retrieves a file from device to a local file. The remote path is the path to
+the file that will be returned. Just as for the SEND sync request the file
+received is split up into chunks. The sync response id is "DATA" and length is
+the chuck size. After follows chunk size number of bytes. This is repeated
+until the file is transfered. Each chuck will not be larger than 64k.
+
+When the file is transfered a sync resopnse "DONE" is retrieved where the
+length can be ignored.
+
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index cd5885e..6fc55df 100755
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -90,6 +90,8 @@
#define VENDOR_ID_INQ_MOBILE 0x2314
// Intel's USB Vendor ID
#define VENDOR_ID_INTEL 0x8087
+// Intermec's USB Vendor ID
+#define VENDOR_ID_INTERMEC 0x067e
// IRiver's USB Vendor ID
#define VENDOR_ID_IRIVER 0x2420
// K-Touch's USB Vendor ID
@@ -210,6 +212,7 @@
VENDOR_ID_HUAWEI,
VENDOR_ID_INQ_MOBILE,
VENDOR_ID_INTEL,
+ VENDOR_ID_INTERMEC,
VENDOR_ID_IRIVER,
VENDOR_ID_KOBO,
VENDOR_ID_K_TOUCH,
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 77fcbe0..f6d8f0c 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -1,35 +1,93 @@
LOCAL_PATH:= $(call my-dir)
-debuggerd_2nd_arch_var_prefix :=
-include $(LOCAL_PATH)/debuggerd.mk
-
-ifdef TARGET_2ND_ARCH
-debuggerd_2nd_arch_var_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-include $(LOCAL_PATH)/debuggerd.mk
-endif
-
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
include $(CLEAR_VARS)
-LOCAL_CFLAGS += -DWITH_VFP
+LOCAL_SRC_FILES:= \
+ backtrace.cpp \
+ debuggerd.cpp \
+ getevent.cpp \
+ tombstone.cpp \
+ utility.cpp \
+
+LOCAL_SRC_FILES_arm := arm/machine.cpp
+LOCAL_SRC_FILES_arm64 := arm64/machine.cpp
+LOCAL_SRC_FILES_mips := mips/machine.cpp
+LOCAL_SRC_FILES_x86 := x86/machine.cpp
+LOCAL_SRC_FILES_x86_64 := x86_64/machine.cpp
+
+LOCAL_CONLYFLAGS := -std=gnu99
+LOCAL_CPPFLAGS := -std=gnu++11
+LOCAL_CFLAGS := \
+ -Wall \
+ -Wno-array-bounds \
+ -Werror \
+ -Wno-unused-parameter \
+
+ifeq ($(ARCH_ARM_HAVE_VFP),true)
+LOCAL_CFLAGS_arm += -DWITH_VFP
+endif # ARCH_ARM_HAVE_VFP
ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS += -DWITH_VFP_D32
+LOCAL_CFLAGS_arm += -DWITH_VFP_D32
endif # ARCH_ARM_HAVE_VFP_D32
-LOCAL_SRC_FILES := vfp-crasher.c arm/vfp.S
+LOCAL_SHARED_LIBRARIES := \
+ libbacktrace \
+ libc \
+ libcutils \
+ liblog \
+ libselinux \
+
+include external/stlport/libstlport.mk
+
+LOCAL_MODULE := debuggerd
+LOCAL_MODULE_STEM_32 := debuggerd
+LOCAL_MODULE_STEM_64 := debuggerd64
+LOCAL_MULTILIB := both
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := crasher.c
+LOCAL_SRC_FILES_arm := arm/crashglue.S
+LOCAL_SRC_FILES_arm64 := arm64/crashglue.S
+LOCAL_SRC_FILES_mips := mips/crashglue.S
+LOCAL_SRC_FILES_x86 := x86/crashglue.S
+LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -fstack-protector-all -Wno-unused-parameter -Wno-free-nonheap-object
+#LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+
+LOCAL_MODULE := crasher
+LOCAL_MODULE_STEM_32 := crasher
+LOCAL_MODULE_STEM_64 := crasher64
+LOCAL_MULTILIB := both
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+ifeq ($(ARCH_ARM_HAVE_VFP),true)
+LOCAL_MODULE_TARGET_ARCH += arm
+LOCAL_SRC_FILES_arm := arm/vfp.S
+LOCAL_CFLAGS_arm += -DWITH_VFP
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_CFLAGS_arm += -DWITH_VFP_D32
+endif # ARCH_ARM_HAVE_VFP_D32
+endif # ARCH_ARM_HAVE_VFP == true
+
+LOCAL_SRC_FILES_arm64 := arm64/vfp.S
+LOCAL_MODULE_TARGET_ARCH += arm64
+
+LOCAL_SRC_FILES := vfp-crasher.c
LOCAL_MODULE := vfp-crasher
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libcutils liblog libc
-LOCAL_MODULE_TARGET_ARCH := arm
-include $(BUILD_EXECUTABLE)
-endif # ARCH_ARM_HAVE_VFP == true
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := vfp-crasher.c arm64/vfp.S
-LOCAL_MODULE := vfp-crasher64
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcutils liblog libc
-LOCAL_MODULE_TARGET_ARCH := arm64
+LOCAL_MODULE_STEM_32 := vfp-crasher
+LOCAL_MODULE_STEM_64 := vfp-crasher64
+LOCAL_MULTILIB := both
+
include $(BUILD_EXECUTABLE)
diff --git a/debuggerd/debuggerd.mk b/debuggerd/debuggerd.mk
deleted file mode 100644
index a3982c1..0000000
--- a/debuggerd/debuggerd.mk
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- backtrace.cpp \
- debuggerd.cpp \
- getevent.cpp \
- tombstone.cpp \
- utility.cpp \
-
-LOCAL_SRC_FILES_arm := arm/machine.cpp
-LOCAL_SRC_FILES_arm64 := arm64/machine.cpp
-LOCAL_SRC_FILES_mips := mips/machine.cpp
-LOCAL_SRC_FILES_x86 := x86/machine.cpp
-LOCAL_SRC_FILES_x86_64 := x86_64/machine.cpp
-
-LOCAL_CONLYFLAGS := -std=gnu99
-LOCAL_CPPFLAGS := -std=gnu++11
-LOCAL_CFLAGS := \
- -Wall \
- -Wno-array-bounds \
- -Werror \
- -Wno-unused-parameter \
-
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP
-endif # ARCH_ARM_HAVE_VFP
-ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS_arm += -DWITH_VFP_D32
-endif # ARCH_ARM_HAVE_VFP_D32
-
-LOCAL_SHARED_LIBRARIES := \
- libbacktrace \
- libc \
- libcutils \
- liblog \
- libselinux \
-
-include external/stlport/libstlport.mk
-
-ifeq ($(TARGET_IS_64_BIT)|$(debuggerd_2nd_arch_var_prefix),true|)
-LOCAL_MODULE := debuggerd64
-LOCAL_NO_2ND_ARCH := true
-else
-LOCAL_MODULE := debuggerd
-LOCAL_32_BIT_ONLY := true
-endif
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := crasher.c
-LOCAL_SRC_FILES_arm := arm/crashglue.S
-LOCAL_SRC_FILES_arm64 := arm64/crashglue.S
-LOCAL_SRC_FILES_mips := mips/crashglue.S
-LOCAL_SRC_FILES_x86 := x86/crashglue.S
-LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -fstack-protector-all -Wno-unused-parameter -Wno-free-nonheap-object
-#LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_SHARED_LIBRARIES := libcutils liblog libc
-
-LOCAL_2ND_ARCH_VAR_PREFIX := $(debuggerd_2nd_arch_var_prefix)
-
-ifeq ($(TARGET_IS_64_BIT)|$(debuggerd_2nd_arch_var_prefix),true|)
-LOCAL_MODULE := crasher64
-LOCAL_NO_2ND_ARCH := true
-else
-LOCAL_MODULE := crasher
-LOCAL_32_BIT_ONLY := true
-endif
-include $(BUILD_EXECUTABLE)
diff --git a/fastbootd/Android.mk b/fastbootd/Android.mk
index 0f32dbf..6aa7400 100644
--- a/fastbootd/Android.mk
+++ b/fastbootd/Android.mk
@@ -45,19 +45,17 @@
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -DFLASH_CERT
LOCAL_LDFLAGS := -ldl
-LOCAL_SHARED_LIBRARIES := \
- libhardware \
- libcrypto \
- libhardware_legacy \
- libmdnssd
-
LOCAL_STATIC_LIBRARIES := \
- libsparse_static \
libc \
+ libcrypto_static \
libcutils \
+ libmdnssd \
+ libsparse_static \
libz
-#LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_HAL_STATIC_LIBRARIES := libvendortrigger
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)
@@ -84,21 +82,11 @@
include $(BUILD_EXECUTABLE)
+# vendor trigger HAL
include $(CLEAR_VARS)
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/include \
-
-LOCAL_STATIC_LIBRARIES := \
- $(EXTRA_STATIC_LIBS) \
- libcutils
-
-LOCAL_SRC_FILES := \
- other/vendor_trigger.c
-
+LOCAL_CFLAGS := -Wall -Werror
LOCAL_MODULE := libvendortrigger.default
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
-
-
-include $(BUILD_SHARED_LIBRARY)
+LOCAL_SRC_FILES := vendor_trigger_default.c
+LOCAL_STATIC_LIBRARIES := libcutils
+include $(BUILD_STATIC_LIBRARY)
diff --git a/fastbootd/other/vendor_trigger.c b/fastbootd/other/vendor_trigger.c
deleted file mode 100644
index 101959b..0000000
--- a/fastbootd/other/vendor_trigger.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2009-2013, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-
-#include "vendor_trigger.h"
-#include "debug.h"
-
-unsigned int debug_level = DEBUG;
-
-static const int version = 1;
-
-int check_version(const int fastboot_version, int *libversion) {
- *libversion = version;
- return !(fastboot_version == version);
-}
-
-int gpt_layout(struct GPT_content *table) {
- D(DEBUG, "message from libvendor");
- return 0;
-}
-
-int oem_cmd(const char *arg, const char **response) {
- D(DEBUG, "message from libvendor, oem catched request %s", arg);
- return 0;
-}
-
-static int close_triggers(struct vendor_trigger_t *dev)
-{
- if (dev)
- free(dev);
-
- return 0;
-}
-
-static int open_triggers(const struct hw_module_t *module, char const *name,
- struct hw_device_t **device) {
- struct vendor_trigger_t *dev = malloc(sizeof(struct vendor_trigger_t));
- klog_init();
- klog_set_level(6);
-
- memset(dev, 0, sizeof(*dev));
- dev->common.module = (struct hw_module_t *) module;
- dev->common.close = (int (*)(struct hw_device_t *)) close_triggers;
-
- dev->gpt_layout = gpt_layout;
- dev->oem_cmd = oem_cmd;
-
- *device = (struct hw_device_t *) dev;
-
- return 0;
-}
-
-
-static struct hw_module_methods_t trigger_module_methods = {
- .open = open_triggers,
-};
-
-struct hw_module_t HAL_MODULE_INFO_SYM = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
- .id = TRIGGER_MODULE_ID,
- .name = "vendor trigger library for fastbootd",
- .author = "Google, Inc.",
- .methods = &trigger_module_methods,
-};
-
diff --git a/fastbootd/trigger.c b/fastbootd/trigger.c
index e63e64d..df0f895 100644
--- a/fastbootd/trigger.c
+++ b/fastbootd/trigger.c
@@ -39,52 +39,19 @@
static const int version = 1;
-static struct vendor_trigger_t *triggers = NULL;
-
int load_trigger() {
- int err;
- hw_module_t* module;
- hw_device_t* device;
int libversion;
- err = hw_get_module(TRIGGER_MODULE_ID, (hw_module_t const**)&module);
-
- if (err == 0) {
- err = module->methods->open(module, NULL, &device);
-
- if (err == 0) {
- triggers = (struct vendor_trigger_t *) device;
- } else {
- D(WARN, "Libvendor load error");
- return 1;
- }
- }
- else {
- D(WARN, "Libvendor not load: %s", strerror(-err));
- return 0;
+ if (trigger_init() != 0) {
+ D(ERR, "libvendortrigger failed to initialize");
+ return 1;
}
- if (triggers->check_version != NULL &&
- triggers->check_version(version, &libversion)) {
-
- triggers = NULL;
+ if (trigger_check_version(version, &libversion)) {
D(ERR, "Library report incompability");
return 1;
}
+
D(INFO, "libvendortrigger loaded");
-
return 0;
}
-
-int trigger_oem_cmd(const char *arg, const char **response) {
- if (triggers != NULL && triggers->oem_cmd != NULL)
- return triggers->oem_cmd(arg, response);
- return 0;
-}
-
-int trigger_gpt_layout(struct GPT_content *table) {
- if (triggers != NULL && triggers->gpt_layout != NULL)
- return triggers->gpt_layout(table);
- return 0;
-}
-
diff --git a/fastbootd/trigger.h b/fastbootd/trigger.h
index 404acb4..d2d9573 100644
--- a/fastbootd/trigger.h
+++ b/fastbootd/trigger.h
@@ -37,9 +37,4 @@
int load_trigger();
-/* same as in struct triggers */
-
-int trigger_gpt_layout(struct GPT_content *table);
-int trigger_oem_cmd(const char *arg, const char **response);
-
#endif
diff --git a/fastbootd/include/vendor_trigger.h b/fastbootd/vendor_trigger.h
similarity index 68%
rename from fastbootd/include/vendor_trigger.h
rename to fastbootd/vendor_trigger.h
index 51204fa..0c83be6 100644
--- a/fastbootd/include/vendor_trigger.h
+++ b/fastbootd/vendor_trigger.h
@@ -32,38 +32,37 @@
#ifndef __VENDOR_TRIGGER_H_
#define __VENDOR_TRIGGER_H_
-#define TRIGGER_MODULE_ID "fastbootd"
-#include <hardware/hardware.h>
-
__BEGIN_DECLS
struct GPT_entry_raw;
struct GPT_content;
/*
- * Structer with function pointers may become longer in the future
+ * Implemented in libvendortrigger to handle platform-specific behavior.
*/
-struct vendor_trigger_t {
- struct hw_device_t common;
+/*
+ * trigger_init() is called once at startup time before calling any other method
+ *
+ * returns 0 on success and nonzero on error
+ */
+int trigger_init(void);
- /*
- * This function runs at the beggining and shoud never be changed
- *
- * version is number parameter indicating version on the fastbootd side
- * libversion is version indicateing version of the library version
- *
- * returns 0 if it can cooperate with the current version and 1 in opposite
- */
- int (*check_version)(const int version, int *libversion);
+/*
+ * This function runs once after trigger_init completes.
+ *
+ * version is number parameter indicating version on the fastbootd side
+ * libversion is version indicateing version of the library version
+ *
+ * returns 0 if it can cooperate with the current version and 1 in opposite
+ */
+int trigger_check_version(const int version, int *libversion);
-
- /*
- * Return value -1 forbid the action from the vendor site and sets errno
- */
- int (* gpt_layout)(struct GPT_content *);
- int (* oem_cmd)(const char *arg, const char **response);
-};
+/*
+ * Return value -1 forbid the action from the vendor site and sets errno
+ */
+int trigger_gpt_layout(struct GPT_content *);
+int trigger_oem_cmd(const char *arg, const char **response);
__END_DECLS
diff --git a/fastbootd/include/vendor_trigger.h b/fastbootd/vendor_trigger_default.c
similarity index 62%
copy from fastbootd/include/vendor_trigger.h
copy to fastbootd/vendor_trigger_default.c
index 51204fa..3627024 100644
--- a/fastbootd/include/vendor_trigger.h
+++ b/fastbootd/vendor_trigger_default.c
@@ -29,42 +29,30 @@
* SUCH DAMAGE.
*/
-#ifndef __VENDOR_TRIGGER_H_
-#define __VENDOR_TRIGGER_H_
+#include <stdlib.h>
+#include <cutils/klog.h>
+#include <vendor_trigger.h>
-#define TRIGGER_MODULE_ID "fastbootd"
-#include <hardware/hardware.h>
+static const int version = 1;
-__BEGIN_DECLS
+int trigger_init(void) {
+ klog_init();
+ klog_set_level(7);
+ return 0;
+}
-struct GPT_entry_raw;
-struct GPT_content;
+int trigger_check_version(const int fastboot_version, int *libversion) {
+ KLOG_DEBUG("fastbootd", "%s: %d (%d)", __func__, fastboot_version, version);
+ *libversion = version;
+ return !(fastboot_version == version);
+}
-/*
- * Structer with function pointers may become longer in the future
- */
+int trigger_gpt_layout(struct GPT_content *table) {
+ KLOG_DEBUG("fastbootd", "%s: %p", __func__, table);
+ return 0;
+}
-struct vendor_trigger_t {
- struct hw_device_t common;
-
- /*
- * This function runs at the beggining and shoud never be changed
- *
- * version is number parameter indicating version on the fastbootd side
- * libversion is version indicateing version of the library version
- *
- * returns 0 if it can cooperate with the current version and 1 in opposite
- */
- int (*check_version)(const int version, int *libversion);
-
-
- /*
- * Return value -1 forbid the action from the vendor site and sets errno
- */
- int (* gpt_layout)(struct GPT_content *);
- int (* oem_cmd)(const char *arg, const char **response);
-};
-
-__END_DECLS
-
-#endif
+int trigger_oem_cmd(const char *arg, const char **response) {
+ KLOG_DEBUG("fastbootd", "%s: %s", __func__, arg);
+ return 0;
+}
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index c4f27a0..9ac68cd 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -54,6 +54,32 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+/**
+ * TODO - Remove to enable always on encryption for all devices
+ * This limits the machines on which this feature is enabled
+ * Remove call from fs_mgr_mount_all as well
+ */
+static const char* serial_numbers[] = {
+ "039b83b8437e9637",
+ 0
+};
+
+static int serial_matches()
+{
+ char tmp[PROP_VALUE_MAX];
+ *tmp = 0;
+ __system_property_get("ro.serialno", tmp);
+
+ const char** i;
+ for (i = serial_numbers; *i; ++i) {
+ if (!strcmp(*i, tmp)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/*
* gettime() - returns the time in seconds of the system's monotonic clock or
* zero on error.
@@ -254,6 +280,22 @@
fstab->recs[i].fs_options);
if (!mret) {
+ /* If this is encryptable, need to trigger encryption */
+ if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT)) {
+ if (serial_matches() && umount(fstab->recs[i].mount_point) == 0) {
+ if (!encryptable) {
+ encryptable = 2;
+ } else {
+ ERROR("Only one encryptable/encrypted partition supported");
+ encryptable = 1;
+ }
+ } else {
+ INFO("Could not umount %s - allow continue unencrypted",
+ fstab->recs[i].mount_point);
+ continue;
+ }
+ }
+
/* Success! Go get the next one */
continue;
}
@@ -287,12 +329,8 @@
if (error_count) {
return -1;
- }
-
- if (encryptable) {
- return 1;
} else {
- return 0;
+ return encryptable;
}
}
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 3e6a4b1..9368225 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -302,6 +302,16 @@
}
break;
+ case BATTERY_PROP_CAPACITY:
+ if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
+ val->valueInt =
+ getIntField(mHealthdConfig->batteryCapacityPath);
+ ret = NO_ERROR;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
default:
break;
}
diff --git a/include/cutils/str_parms.h b/include/cutils/str_parms.h
index 247c996..66f3637 100644
--- a/include/cutils/str_parms.h
+++ b/include/cutils/str_parms.h
@@ -34,6 +34,12 @@
int str_parms_add_float(struct str_parms *str_parms, const char *key,
float value);
+// Returns non-zero if the str_parms contains the specified key.
+int str_parms_has_key(struct str_parms *str_parms, const char *key);
+
+// Gets value associated with the specified key (if present), placing it in the buffer
+// pointed to by the out_val parameter. Returns the length of the returned string value.
+// If 'key' isn't in the parms, then return -ENOENT (-2) and leave 'out_val' untouched.
int str_parms_get_str(struct str_parms *str_parms, const char *key,
char *out_val, int len);
int str_parms_get_int(struct str_parms *str_parms, const char *key,
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 1c8f107..dbd5e25 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -17,13 +17,14 @@
#ifndef _LIBS_CUTILS_TRACE_H
#define _LIBS_CUTILS_TRACE_H
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
-#include <stdint.h>
-#include <stdbool.h>
#include <unistd.h>
-#include <cutils/compiler.h>
+#include <cutils/compiler.h>
#ifdef ANDROID_SMP
#include <cutils/atomic-inline.h>
#else
@@ -217,8 +218,8 @@
char buf[ATRACE_MESSAGE_LENGTH];
size_t len;
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%d", getpid(),
- name, cookie);
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%" PRId32,
+ getpid(), name, cookie);
write(atrace_marker_fd, buf, len);
}
}
@@ -235,8 +236,8 @@
char buf[ATRACE_MESSAGE_LENGTH];
size_t len;
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%d", getpid(),
- name, cookie);
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%" PRId32,
+ getpid(), name, cookie);
write(atrace_marker_fd, buf, len);
}
}
@@ -253,7 +254,7 @@
char buf[ATRACE_MESSAGE_LENGTH];
size_t len;
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%d",
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%" PRId32,
getpid(), name, value);
write(atrace_marker_fd, buf, len);
}
@@ -270,7 +271,7 @@
char buf[ATRACE_MESSAGE_LENGTH];
size_t len;
- len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%lld",
+ len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%" PRId64,
getpid(), name, value);
write(atrace_marker_fd, buf, len);
}
diff --git a/init/Android.mk b/init/Android.mk
index 740d10f..15a23be 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -17,6 +17,8 @@
ueventd_parser.c \
watchdogd.c
+LOCAL_CFLAGS += -Wno-unused-parameter
+
ifeq ($(strip $(INIT_BOOTCHART)),true)
LOCAL_SRC_FILES += bootchart.c
LOCAL_CFLAGS += -DBOOTCHART=1
diff --git a/init/builtins.c b/init/builtins.c
index a168062..a857c98 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -501,8 +501,12 @@
return -1;
}
- /* ret is 1 if the device appears encrypted, 0 if not, and -1 on error */
- if (ret == 1) {
+ /* ret is 2 if device needs encrypted, 1 if the device appears encrypted,
+ * 0 if not, and -1 on error */
+ if (ret == 2) {
+ property_set("ro.crypto.state", "unencrypted");
+ property_set("vold.decrypt", "trigger_encryption");
+ } else if (ret == 1) {
property_set("ro.crypto.state", "encrypted");
property_set("vold.decrypt", "trigger_default_encryption");
} else if (ret == 0) {
diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c
index 7cfbcb3..1edef11 100644
--- a/libcutils/str_parms.c
+++ b/libcutils/str_parms.c
@@ -240,6 +240,10 @@
return ret;
}
+int str_parms_has_key(struct str_parms *str_parms, const char *key) {
+ return hashmapGet(str_parms->map, (void *)key) != NULL;
+}
+
int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val,
int len)
{
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index c3efc33..9c73dad 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -77,32 +77,78 @@
return (g_log_status == kLogAvailable);
}
+/* give up, resources too limited */
static int __write_to_log_null(log_id_t log_fd UNUSED, struct iovec *vec UNUSED,
size_t nr UNUSED)
{
return -1;
}
+/* log_init_lock assumed */
+static int __write_to_log_initialize()
+{
+ int i, ret = 0;
+
+#if FAKE_LOG_DEVICE
+ for (i = 0; i < LOG_ID_MAX; i++) {
+ char buf[sizeof("/dev/log_system")];
+ snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
+ log_fds[i] = fakeLogOpen(buf, O_WRONLY);
+ }
+#else
+ if (logd_fd >= 0) {
+ i = logd_fd;
+ logd_fd = -1;
+ close(i);
+ }
+
+ i = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (i < 0) {
+ ret = -errno;
+ write_to_log = __write_to_log_null;
+ } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) {
+ ret = -errno;
+ close(i);
+ i = -1;
+ write_to_log = __write_to_log_null;
+ } else {
+ struct sockaddr_un un;
+ memset(&un, 0, sizeof(struct sockaddr_un));
+ un.sun_family = AF_UNIX;
+ strcpy(un.sun_path, "/dev/socket/logdw");
+
+ if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) {
+ ret = -errno;
+ close(i);
+ i = -1;
+ }
+ }
+ logd_fd = i;
+#endif
+
+ return ret;
+}
+
static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
{
-#if FAKE_LOG_DEVICE
ssize_t ret;
+#if FAKE_LOG_DEVICE
int log_fd;
if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
log_fd = log_fds[(int)log_id];
} else {
- return EBADF;
+ return -EBADF;
}
do {
ret = fakeLogWritev(log_fd, vec, nr);
- } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ } while (ret == -EINTR);
return ret;
#else
- if (logd_fd == -1) {
- return -1;
- }
if (getuid() == AID_LOGD) {
/*
* ignore log messages we send to ourself.
@@ -111,11 +157,39 @@
*/
return 0;
}
- struct iovec newVec[nr + 2];
+
+ if (logd_fd < 0) {
+ return -EBADF;
+ }
+
+ /*
+ * struct {
+ * // what we provide
+ * typeof_log_id_t log_id;
+ * u16 tid;
+ * log_time realtime;
+ * // caller provides
+ * union {
+ * struct {
+ * char prio;
+ * char payload[];
+ * } string;
+ * struct {
+ * uint32_t tag
+ * char payload[];
+ * } binary;
+ * };
+ * };
+ */
+ static const unsigned header_length = 3;
+ struct iovec newVec[nr + header_length];
typeof_log_id_t log_id_buf = log_id;
+ uint16_t tid = gettid();
newVec[0].iov_base = (unsigned char *) &log_id_buf;
newVec[0].iov_len = sizeof_log_id_t;
+ newVec[1].iov_base = (unsigned char *) &tid;
+ newVec[1].iov_len = sizeof(tid);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
@@ -123,17 +197,44 @@
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
- newVec[1].iov_base = (unsigned char *) &realtime_ts;
- newVec[1].iov_len = sizeof(log_time);
+ newVec[2].iov_base = (unsigned char *) &realtime_ts;
+ newVec[2].iov_len = sizeof(log_time);
size_t i;
- for (i = 2; i < nr + 2; i++) {
- newVec[i].iov_base = vec[i-2].iov_base;
- newVec[i].iov_len = vec[i-2].iov_len;
+ for (i = header_length; i < nr + header_length; i++) {
+ newVec[i].iov_base = vec[i-header_length].iov_base;
+ newVec[i].iov_len = vec[i-header_length].iov_len;
}
- /* The write below could be lost, but will never block. */
- return writev(logd_fd, newVec, nr + 2);
+ /*
+ * The write below could be lost, but will never block.
+ *
+ * ENOTCONN occurs if logd dies.
+ * EAGAIN occurs if logd is overloaded.
+ */
+ ret = writev(logd_fd, newVec, nr + header_length);
+ if (ret < 0) {
+ ret = -errno;
+ if (ret == -ENOTCONN) {
+#ifdef HAVE_PTHREADS
+ pthread_mutex_lock(&log_init_lock);
+#endif
+ ret = __write_to_log_initialize();
+#ifdef HAVE_PTHREADS
+ pthread_mutex_unlock(&log_init_lock);
+#endif
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = writev(logd_fd, newVec, nr + header_length);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ }
+ }
+ return ret;
#endif
}
@@ -161,35 +262,17 @@
#endif
if (write_to_log == __write_to_log_init) {
- write_to_log = __write_to_log_kernel;
+ int ret;
-#if FAKE_LOG_DEVICE
- int i;
- for (i = 0; i < LOG_ID_MAX; i++) {
- char buf[sizeof("/dev/log_system")];
- snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
- log_fds[i] = fakeLogOpen(buf, O_WRONLY);
- }
-#else
- int sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (sock != -1) {
- if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
- /* NB: Loss of content */
- close(sock);
- sock = -1;
- } else {
- struct sockaddr_un un;
- memset(&un, 0, sizeof(struct sockaddr_un));
- un.sun_family = AF_UNIX;
- strcpy(un.sun_path, "/dev/socket/logdw");
-
- connect(sock, (struct sockaddr *)&un, sizeof(struct sockaddr_un));
- }
- } else {
- write_to_log = __write_to_log_null;
- }
- logd_fd = sock;
+ ret = __write_to_log_initialize();
+ if (ret < 0) {
+#ifdef HAVE_PTHREADS
+ pthread_mutex_unlock(&log_init_lock);
#endif
+ return ret;
+ }
+
+ write_to_log = __write_to_log_kernel;
}
#ifdef HAVE_PTHREADS
@@ -219,7 +302,7 @@
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS")) {
log_id = LOG_ID_RADIO;
- // Inform third party apps/ril/radio.. to use Rlog or RLOG
+ /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
tag = tmp_tag;
}
@@ -254,7 +337,7 @@
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS"))) {
bufID = LOG_ID_RADIO;
- // Inform third party apps/ril/radio.. to use Rlog or RLOG
+ /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
tag = tmp_tag;
}
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index 32a202b..5ef349b 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -95,12 +95,15 @@
if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
log_fd = log_fds[(int)log_id];
} else {
- return EBADF;
+ return -EBADF;
}
do {
ret = log_writev(log_fd, vec, nr);
- } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ } while (ret == -EINTR);
return ret;
}
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index ffb7fd1..d726f2d 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -38,30 +38,30 @@
_rc; })
TEST(liblog, __android_log_buf_print) {
- ASSERT_LT(0, __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO,
+ EXPECT_LT(0, __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO,
"TEST__android_log_buf_print",
"radio"));
usleep(1000);
- ASSERT_LT(0, __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
+ EXPECT_LT(0, __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
"TEST__android_log_buf_print",
"system"));
usleep(1000);
- ASSERT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
+ EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
"TEST__android_log_buf_print",
"main"));
usleep(1000);
}
TEST(liblog, __android_log_buf_write) {
- ASSERT_LT(0, __android_log_buf_write(LOG_ID_RADIO, ANDROID_LOG_INFO,
+ EXPECT_LT(0, __android_log_buf_write(LOG_ID_RADIO, ANDROID_LOG_INFO,
"TEST__android_log_buf_write",
"radio"));
usleep(1000);
- ASSERT_LT(0, __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
+ EXPECT_LT(0, __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
"TEST__android_log_buf_write",
"system"));
usleep(1000);
- ASSERT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
+ EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
"TEST__android_log_buf_write",
"main"));
usleep(1000);
@@ -69,16 +69,16 @@
TEST(liblog, __android_log_btwrite) {
int intBuf = 0xDEADBEEF;
- ASSERT_LT(0, __android_log_btwrite(0,
+ EXPECT_LT(0, __android_log_btwrite(0,
EVENT_TYPE_INT,
&intBuf, sizeof(intBuf)));
long long longBuf = 0xDEADBEEFA55A5AA5;
- ASSERT_LT(0, __android_log_btwrite(0,
+ EXPECT_LT(0, __android_log_btwrite(0,
EVENT_TYPE_LONG,
&longBuf, sizeof(longBuf)));
usleep(1000);
char Buf[] = "\20\0\0\0DeAdBeEfA55a5aA5";
- ASSERT_LT(0, __android_log_btwrite(0,
+ EXPECT_LT(0, __android_log_btwrite(0,
EVENT_TYPE_STRING,
Buf, sizeof(Buf) - 1));
usleep(1000);
@@ -120,7 +120,7 @@
pid_t pid = getpid();
- ASSERT_EQ(0, NULL == (logger_list = android_logger_list_open(
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, O_RDONLY | O_NDELAY, 1000, pid)));
log_time ts(CLOCK_MONOTONIC);
@@ -155,7 +155,7 @@
}
}
- ASSERT_EQ(1, count);
+ EXPECT_EQ(1, count);
android_logger_list_close(logger_list);
}
@@ -221,7 +221,7 @@
v += pid & 0xFFFF;
- ASSERT_EQ(0, NULL == (logger_list = android_logger_list_open(
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, O_RDONLY, 1000, pid)));
int count = 0;
@@ -277,13 +277,13 @@
++signals;
break;
}
- } while (!signaled || ({log_time t(CLOCK_MONOTONIC); t < signal_time;}));
+ } while (!signaled || (log_time(CLOCK_MONOTONIC) < signal_time));
alarm(0);
signal(SIGALRM, SIG_DFL);
- ASSERT_LT(1, count);
+ EXPECT_LT(1, count);
- ASSERT_EQ(1, signals);
+ EXPECT_EQ(1, signals);
android_logger_list_close(logger_list);
@@ -295,9 +295,245 @@
const unsigned long long one_percent_ticks = alarm_time;
unsigned long long user_ticks = uticks_end - uticks_start;
unsigned long long system_ticks = sticks_end - sticks_start;
- ASSERT_GT(one_percent_ticks, user_ticks);
- ASSERT_GT(one_percent_ticks, system_ticks);
- ASSERT_GT(one_percent_ticks, user_ticks + system_ticks);
+ EXPECT_GT(one_percent_ticks, user_ticks);
+ EXPECT_GT(one_percent_ticks, system_ticks);
+ EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
+}
+
+static const char max_payload_tag[] = "TEST_max_payload_XXXX";
+static const char max_payload_buf[LOGGER_ENTRY_MAX_PAYLOAD
+ - sizeof(max_payload_tag) - 1] = "LEONATO\n\
+I learn in this letter that Don Peter of Arragon\n\
+comes this night to Messina\n\
+MESSENGER\n\
+He is very near by this: he was not three leagues off\n\
+when I left him\n\
+LEONATO\n\
+How many gentlemen have you lost in this action?\n\
+MESSENGER\n\
+But few of any sort, and none of name\n\
+LEONATO\n\
+A victory is twice itself when the achiever brings\n\
+home full numbers. I find here that Don Peter hath\n\
+bestowed much honour on a young Florentine called Claudio\n\
+MESSENGER\n\
+Much deserved on his part and equally remembered by\n\
+Don Pedro: he hath borne himself beyond the\n\
+promise of his age, doing, in the figure of a lamb,\n\
+the feats of a lion: he hath indeed better\n\
+bettered expectation than you must expect of me to\n\
+tell you how\n\
+LEONATO\n\
+He hath an uncle here in Messina will be very much\n\
+glad of it.\n\
+MESSENGER\n\
+I have already delivered him letters, and there\n\
+appears much joy in him; even so much that joy could\n\
+not show itself modest enough without a badge of\n\
+bitterness.\n\
+LEONATO\n\
+Did he break out into tears?\n\
+MESSENGER\n\
+In great measure.\n\
+LEONATO\n\
+A kind overflow of kindness: there are no faces\n\
+truer than those that are so washed. How much\n\
+better is it to weep at joy than to joy at weeping!\n\
+BEATRICE\n\
+I pray you, is Signior Mountanto returned from the\n\
+wars or no?\n\
+MESSENGER\n\
+I know none of that name, lady: there was none such\n\
+in the army of any sort.\n\
+LEONATO\n\
+What is he that you ask for, niece?\n\
+HERO\n\
+My cousin means Signior Benedick of Padua.\n\
+MESSENGER\n\
+O, he's returned; and as pleasant as ever he was.\n\
+BEATRICE\n\
+He set up his bills here in Messina and challenged\n\
+Cupid at the flight; and my uncle's fool, reading\n\
+the challenge, subscribed for Cupid, and challenged\n\
+him at the bird-bolt. I pray you, how many hath he\n\
+killed and eaten in these wars? But how many hath\n\
+he killed? for indeed I promised to eat all of his killing.\n\
+LEONATO\n\
+Faith, niece, you tax Signior Benedick too much;\n\
+but he'll be meet with you, I doubt it not.\n\
+MESSENGER\n\
+He hath done good service, lady, in these wars.\n\
+BEATRICE\n\
+You had musty victual, and he hath holp to eat it:\n\
+he is a very valiant trencherman; he hath an\n\
+excellent stomach.\n\
+MESSENGER\n\
+And a good soldier too, lady.\n\
+BEATRICE\n\
+And a good soldier to a lady: but what is he to a lord?\n\
+MESSENGER\n\
+A lord to a lord, a man to a man; stuffed with all\n\
+honourable virtues.\n\
+BEATRICE\n\
+It is so, indeed; he is no less than a stuffed man:\n\
+but for the stuffing,--well, we are all mortal.\n\
+LEONATO\n\
+You must not, sir, mistake my niece. There is a\n\
+kind of merry war betwixt Signior Benedick and her:\n\
+they never meet but there's a skirmish of wit\n\
+between them.\n\
+BEATRICE\n\
+Alas! he gets nothing by that. In our last\n\
+conflict four of his five wits went halting off, and\n\
+now is the whole man governed with one: so that if\n\
+he have wit enough to keep himself warm, let him\n\
+bear it for a difference between himself and his\n\
+horse; for it is all the wealth that he hath left,\n\
+to be known a reasonable creature. Who is his\n\
+companion now? He hath every month a new sworn brother.\n\
+MESSENGER\n\
+Is't possible?\n\
+BEATRICE\n\
+Very easily possible: he wears his faith but as\n\
+the fashion of his hat; it ever changes with the\n\
+next block.\n\
+MESSENGER\n\
+I see, lady, the gentleman is not in your books.\n\
+BEATRICE\n\
+No; an he were, I would burn my study. But, I pray\n\
+you, who is his companion? Is there no young\n\
+squarer now that will make a voyage with him to the devil?\n\
+MESSENGER\n\
+He is most in the company of the right noble Claudio.\n\
+BEATRICE\n\
+O Lord, he will hang upon him like a disease: he\n\
+is sooner caught than the pestilence, and the taker\n\
+runs presently mad. God help the noble Claudio! if\n\
+he have caught the Benedick, it will cost him a\n\
+thousand pound ere a' be cured.\n\
+MESSENGER\n\
+I will hold friends with you, lady.\n\
+BEATRICE\n\
+Do, good friend.\n\
+LEONATO\n\
+You will never run mad, niece.\n\
+BEATRICE\n\
+No, not till a hot January.\n\
+MESSENGER\n\
+Don Pedro is approached.\n\
+Enter DON PEDRO, DON JOHN, CLAUDIO, BENEDICK, and BALTHASAR\n\
+\n\
+DON PEDRO\n\
+Good Signior Leonato, you are come to meet your\n\
+trouble: the fashion of the world is to avoid\n\
+cost, and you encounter it\n\
+LEONATO\n\
+Never came trouble to my house in the likeness";
+
+TEST(liblog, max_payload) {
+ pid_t pid = getpid();
+ char tag[sizeof(max_payload_tag)];
+ memcpy(tag, max_payload_tag, sizeof(tag));
+ snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
+
+ LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
+ tag, max_payload_buf));
+
+ struct logger_list *logger_list;
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_SYSTEM, O_RDONLY, 100, 0)));
+
+ bool matches = false;
+ ssize_t max_len = 0;
+
+ for(;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
+ continue;
+ }
+
+ char *data = log_msg.msg() + 1;
+
+ if (strcmp(data, tag)) {
+ continue;
+ }
+
+ data += strlen(data) + 1;
+
+ const char *left = data;
+ const char *right = max_payload_buf;
+ while (*left && *right && (*left == *right)) {
+ ++left;
+ ++right;
+ }
+
+ if (max_len <= (left - data)) {
+ max_len = left - data + 1;
+ }
+
+ if (max_len > 512) {
+ matches = true;
+ break;
+ }
+ }
+
+ EXPECT_EQ(true, matches);
+
+ EXPECT_LE(sizeof(max_payload_buf), max_len);
+
+ android_logger_list_close(logger_list);
+}
+
+TEST(liblog, dual_reader) {
+ struct logger_list *logger_list1;
+
+ // >25 messages due to liblog.__android_log_buf_print__concurrentXX above.
+ ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
+ LOG_ID_MAIN, O_RDONLY | O_NDELAY, 25, 0)));
+
+ struct logger_list *logger_list2;
+
+ if (NULL == (logger_list2 = android_logger_list_open(
+ LOG_ID_MAIN, O_RDONLY | O_NDELAY, 15, 0))) {
+ android_logger_list_close(logger_list1);
+ ASSERT_TRUE(NULL != logger_list2);
+ }
+
+ int count1 = 0;
+ bool done1 = false;
+ int count2 = 0;
+ bool done2 = false;
+
+ do {
+ log_msg log_msg;
+
+ if (!done1) {
+ if (android_logger_list_read(logger_list1, &log_msg) <= 0) {
+ done1 = true;
+ } else {
+ ++count1;
+ }
+ }
+
+ if (!done2) {
+ if (android_logger_list_read(logger_list2, &log_msg) <= 0) {
+ done2 = true;
+ } else {
+ ++count2;
+ }
+ }
+ } while ((!done1) || (!done2));
+
+ android_logger_list_close(logger_list1);
+ android_logger_list_close(logger_list2);
+
+ EXPECT_EQ(25, count1);
+ EXPECT_EQ(15, count2);
}
TEST(liblog, android_logger_get_) {
@@ -310,11 +546,11 @@
continue;
}
struct logger * logger;
- ASSERT_EQ(0, NULL == (logger = android_logger_open(logger_list, id)));
- ASSERT_EQ(id, android_logger_get_id(logger));
- ASSERT_LT(0, android_logger_get_log_size(logger));
- ASSERT_LT(0, android_logger_get_log_readable_size(logger));
- ASSERT_LT(0, android_logger_get_log_version(logger));
+ EXPECT_TRUE(NULL != (logger = android_logger_open(logger_list, id)));
+ EXPECT_EQ(id, android_logger_get_id(logger));
+ EXPECT_LT(0, android_logger_get_log_size(logger));
+ EXPECT_LT(0, android_logger_get_log_readable_size(logger));
+ EXPECT_LT(0, android_logger_get_log_version(logger));
}
android_logger_list_close(logger_list);
diff --git a/libnl_2/.gitignore b/libnl_2/.gitignore
deleted file mode 100644
index d4ca744..0000000
--- a/libnl_2/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-include/netlink/version.h.in
-cscope.*
diff --git a/libnl_2/Android.mk b/libnl_2/Android.mk
deleted file mode 100644
index 3721fc6..0000000
--- a/libnl_2/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#######################################
-# * Netlink cache not implemented
-# * Library is not thread safe
-#######################################
-
-LOCAL_PATH := $(call my-dir)
-
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- attr.c \
- cache.c \
- genl/genl.c \
- genl/family.c \
- handlers.c \
- msg.c \
- netlink.c \
- object.c \
- socket.c \
- dbg.c
-
-LOCAL_C_INCLUDES += \
- external/libnl-headers
-
-# Static Library
-LOCAL_MODULE := libnl_2
-LOCAL_MODULE_TAGS := optional
-LOCAL_32_BIT_ONLY := true
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES :=
-LOCAL_WHOLE_STATIC_LIBRARIES:= libnl_2
-LOCAL_SHARED_LIBRARIES:= liblog
-LOCAL_MODULE := libnl_2
-LOCAL_MODULE_TAGS := optional
-LOCAL_32_BIT_ONLY := true
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libnl_2/README b/libnl_2/README
deleted file mode 100644
index 14db6db..0000000
--- a/libnl_2/README
+++ /dev/null
@@ -1,88 +0,0 @@
-Netlink Protocol Library
-
-This library is a clean room re-implementation of libnl 2.0 and
-re-licensed under Apache 2.0. It was developed primarily to support
-wpa_supplicant. However, with additional development can be extended
-to support other netlink applications.
-
-Netlink Protocol Format (RFC3549)
-
-+-----------------+-+-------------------+-+
-|Netlink Message |P| Generic Netlink |P|
-| Header |A| Message Header |A|
-|(struct nlmsghdr)|D|(struct genlmsghdr)|D|
-+-----------------+-+-------------------+-+-------------+
-|len:4|type:2|flags:2|seq:4 pid:4|cmd:1|ver:1|reserved:2|
-+--------------------------------+----------------------+
-+-----------------+-+-----------------+-+-----------------+-+-----------------+-+---+
-|Netlink Attribute|P|Netlink Attribute|P|Netlink Attribute|P|Netlink Attribute|P|...|
-| #0 Header |A| #0 Payload |A| #1 Header |A| #1 Payload |A| |
-| (struct nlattr) |D| (void) |D| (struct nlattr) |D| (void) |D| |
-+-----------------+-+-----------------+-+-----------------+-+-----------------+-+---+
-|len:2(==4+payload)|type:2|payload|pad|
-+-------------------------+-------+---+
-
-NETLINK OVERVIEW
-
-* Each netlink message consists of a bitstream with a netlink header.
-* After this header a second header *can* be used specific to the netlink
- family in use. This library was tested using the generic netlink
- protocol defined by struct genlmsghdr to support nl80211.
-* After the header(s) netlink attributes can be appended to the message
- which hold can hold basic types such as unsigned integers and strings.
-* Attributes can also be nested. This is accomplished by calling "nla_nest_start"
- which creates an empty attribute with nest attributes as its payload. Then to
- close the nest, "nla_nest_end" is called.
-* All data structures in this implementation are byte-aligned (Currently 4 bytes).
-* Acknowledgements (ACKs) are sent as NLMSG_ERROR netlink message types (0x2) and
- have an error value of 0.
-
-KNOWN ISSUES
-
- GENERAL
- * Not tested for thread safety
-
- Android.mk
- * No dynamic library because of netlink cache not implemented and
- not tested for thread safety
-
- attr.c
- * nla_parse - does not use nla_policy argument
-
- cache.c
- * netlink cache not implemented and only supports one netlink family id
- which is stored in the nl_cache pointer instead of an actual cache
-
- netlink.c
- * nl_recvmsgs - does not support nl_cb_overwrite_recv()
- * nl_recv - sets/unsets asynchronous socket flag
-
-SOURCE FILES
-
-* Android.mk - Android makefile
-* README - This file
-* attr.c - Netlink attributes
-* cache.c - Netlink cache
-* genl/family.c - Generic netlink family id
-* genl/genl.c - Generic netlink
-* handlers.c - Netlink callbacks
-* msg.c - Netlink messages construction
-* netlink.c - Netlink socket communication
-* object.c - libnl object wrapper
-* socket.c - Netlink kernel socket utils
-
-IMPORTANT HEADER FILES - NOTE: These are based on the the origin GPL libnl headers
-
-* netlink-types.h - Contains many important structs for libnl
- to represent netlink objects
-* netlink/netlink-kernel.h - Netlink kernel headers and field constants.
-* netlink/msg.h - macros for iterating over netlink messages
-* netlink/attr.h - netlink attribute constants, iteration macros and setters
-
-REFERENCES
-
-* nl80211.h
-* netlink_types.h
-* $LINUX_KERNEL/net/wireless/nl80211.c
-* http://www.infradead.org/~tgr/libnl/doc-3.0/index.html
-* http://www.netfilter.org/projects/libmnl/doxygen/index.html
diff --git a/libnl_2/attr.c b/libnl_2/attr.c
deleted file mode 100644
index 2ef7590..0000000
--- a/libnl_2/attr.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include <errno.h>
-#include "netlink/netlink.h"
-#include "netlink/msg.h"
-#include "netlink/attr.h"
-#include "netlink-types.h"
-
-/* Return payload of string attribute. */
-char *nla_get_string(struct nlattr *nla)
-{
- return (char *) nla_data(nla);
-}
-
-/* Return payload of 16 bit integer attribute. */
-uint16_t nla_get_u16(struct nlattr *nla)
-{
- return *((uint16_t *) nla_data(nla));
-}
-
-/* Return payload of 32 bit integer attribute. */
-uint32_t nla_get_u32(struct nlattr *nla)
-{
- return *((uint32_t *) nla_data(nla));
-}
-
-/* Return value of 8 bit integer attribute. */
-uint8_t nla_get_u8(struct nlattr *nla)
-{
- return *((uint8_t *) nla_data(nla));
-}
-
-/* Return payload of uint64_t attribute. */
-uint64_t nla_get_u64(struct nlattr *nla)
-{
- uint64_t tmp;
- nla_memcpy(&tmp, nla, sizeof(tmp));
- return tmp;
-}
-
-/* Head of payload */
-void *nla_data(const struct nlattr *nla)
-{
- return (void *) ((char *) nla + NLA_HDRLEN);
-}
-
-/* Return length of the payload . */
-int nla_len(const struct nlattr *nla)
-{
- return nla->nla_len - NLA_HDRLEN;
-}
-
-int nla_padlen(int payload)
-{
- return NLA_ALIGN(payload) - payload;
-}
-
-/* Start a new level of nested attributes. */
-struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype)
-{
- struct nlattr *start = (struct nlattr *)nlmsg_tail(msg->nm_nlh);
- int rc;
-
- rc = nla_put(msg, attrtype, 0, NULL);
- if (rc < 0)
- return NULL;
-
- return start;
-}
-
-/* Finalize nesting of attributes. */
-int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
-{
- /* Set attribute size */
- start->nla_len = (unsigned char *)nlmsg_tail(nlmsg_hdr(msg)) -
- (unsigned char *)start;
- return 0;
-}
-
-/* Return next attribute in a stream of attributes. */
-struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
-{
- struct nlattr *next_nla = NULL;
- if (nla->nla_len >= sizeof(struct nlattr) &&
- nla->nla_len <= *remaining){
- next_nla = (struct nlattr *) \
- ((char *) nla + NLA_ALIGN(nla->nla_len));
- *remaining = *remaining - NLA_ALIGN(nla->nla_len);
- }
-
- return next_nla;
-
-}
-
-/* Check if the attribute header and payload can be accessed safely. */
-int nla_ok(const struct nlattr *nla, int remaining)
-{
- return remaining > 0 &&
- nla->nla_len >= sizeof(struct nlattr) &&
- sizeof(struct nlattr) <= (unsigned int) remaining &&
- nla->nla_len <= remaining;
-}
-
-/* Create attribute index based on a stream of attributes. */
-/* NOTE: Policy not used ! */
-int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
- int len, struct nla_policy *policy)
-{
- struct nlattr *pos;
- int rem;
-
- /* First clear table */
- memset(tb, 0, (maxtype + 1) * sizeof(struct nlattr *));
-
- nla_for_each_attr(pos, head, len, rem) {
- int type = nla_type(pos);
-
- if ((type <= maxtype) && (type != 0))
- tb[type] = pos;
- }
-
- return 0;
-}
-
-
-/* Create attribute index based on nested attribute. */
-int nla_parse_nested(struct nlattr *tb[], int maxtype,
- struct nlattr *nla, struct nla_policy *policy)
-{
- return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
-}
-
-
-/* Add a unspecific attribute to netlink message. */
-int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
-{
- struct nlattr *nla;
-
- /* Reserve space and init nla header */
- nla = nla_reserve(msg, attrtype, datalen);
- if (nla) {
- memcpy(nla_data(nla), data, datalen);
- return 0;
- }
-
- return -EINVAL;
-}
-
-/* Add 8 bit integer attribute to netlink message. */
-int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value)
-{
- return nla_put(msg, attrtype, sizeof(uint8_t), &value);
-}
-
-/* Add 16 bit integer attribute to netlink message. */
-int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value)
-{
- return nla_put(msg, attrtype, sizeof(uint16_t), &value);
-}
-
-/* Add 32 bit integer attribute to netlink message. */
-int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value)
-{
- return nla_put(msg, attrtype, sizeof(uint32_t), &value);
-}
-
-/* Add 64 bit integer attribute to netlink message. */
-int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value)
-{
- return nla_put(msg, attrtype, sizeof(uint64_t), &value);
-}
-
-/* Add nested attributes to netlink message. */
-/* Takes the attributes found in the nested message and appends them
- * to the message msg nested in a container of the type attrtype. The
- * nested message may not have a family specific header */
-int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested)
-{
- int rc;
-
- rc = nla_put(msg, attrtype, nlmsg_attrlen(nlmsg_hdr(nested), 0),
- nlmsg_attrdata(nlmsg_hdr(nested), 0));
- return rc;
-
-}
-
-/* Return type of the attribute. */
-int nla_type(const struct nlattr *nla)
-{
- return (int)nla->nla_type & NLA_TYPE_MASK;
-}
-
-/* Reserves room for an attribute in specified netlink message and fills
- * in the attribute header (type,length). Return NULL if insufficient space */
-struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int data_len)
-{
-
- struct nlattr *nla;
- const unsigned int NEW_SIZE = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) +
- NLA_ALIGN(NLA_HDRLEN + data_len);
-
- /* Check enough space for attribute */
- if (NEW_SIZE > msg->nm_size)
- return NULL;
-
- nla = (struct nlattr *)nlmsg_tail(msg->nm_nlh);
- nla->nla_type = attrtype;
- nla->nla_len = NLA_HDRLEN + data_len;
- memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(data_len));
- msg->nm_nlh->nlmsg_len = NEW_SIZE;
- return nla;
-}
-
-/* Copy attribute payload to another memory area. */
-int nla_memcpy(void *dest, struct nlattr *src, int count)
-{
- if (!src || !dest)
- return 0;
- if (count > nla_len(src))
- count = nla_len(src);
- memcpy(dest, nla_data(src), count);
- return count;
-}
diff --git a/libnl_2/cache.c b/libnl_2/cache.c
deleted file mode 100644
index c21974d..0000000
--- a/libnl_2/cache.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include "netlink/cache.h"
-#include "netlink/object.h"
-
-void nl_cache_free(struct nl_cache *cache)
-{
-
-}
-
-void nl_cache_clear(struct nl_cache *cache)
-{
-
-}
-
-void nl_cache_remove(struct nl_object *obj)
-{
-
-}
-
-
diff --git a/libnl_2/dbg.c b/libnl_2/dbg.c
deleted file mode 100644
index 9764de6..0000000
--- a/libnl_2/dbg.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "netlink/netlink.h"
-#include <android/log.h>
-
-void libnl_printf(int level, char *format, ...)
-{
- va_list ap;
-
- level = ANDROID_LOG_ERROR;
- va_start(ap, format);
- __android_log_vprint(level, "libnl_2", format, ap);
- va_end(ap);
-}
diff --git a/libnl_2/genl/family.c b/libnl_2/genl/family.c
deleted file mode 100644
index 1beee6e..0000000
--- a/libnl_2/genl/family.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include "netlink-types.h"
-
-static struct genl_family *genl_family_find_byname(const char *name)
-{
- return NULL;
-}
-
-/* Release reference and none outstanding */
-void genl_family_put(struct genl_family *family)
-{
- family->ce_refcnt--;
- if (family->ce_refcnt <= 0)
- free(family);
-}
-
-unsigned int genl_family_get_id(struct genl_family *family)
-{
- const int NO_FAMILY_ID = 0;
-
- if (!family)
- return NO_FAMILY_ID;
- else
- return family->gf_id;
-
-}
-
diff --git a/libnl_2/genl/genl.c b/libnl_2/genl/genl.c
deleted file mode 100644
index 1a39c6a..0000000
--- a/libnl_2/genl/genl.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <netlink/genl/ctrl.h>
-#include <netlink/genl/family.h>
-#include "netlink-types.h"
-
-/* Get head of attribute data. */
-struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
-{
- return (struct nlattr *) \
- ((char *) gnlh + GENL_HDRLEN + NLMSG_ALIGN(hdrlen));
-
-}
-
-/* Get length of attribute data. */
-int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
-{
- struct nlattr *nla;
- struct nlmsghdr *nlh;
-
- nla = genlmsg_attrdata(gnlh, hdrlen);
- nlh = (struct nlmsghdr *) ((char *) gnlh - NLMSG_HDRLEN);
- return (char *) nlmsg_tail(nlh) - (char *) nla;
-}
-
-/* Add generic netlink header to netlink message. */
-void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
- int hdrlen, int flags, uint8_t cmd, uint8_t version)
-{
- int new_size;
- struct nlmsghdr *nlh;
- struct timeval tv;
- struct genlmsghdr *gmh;
-
- /* Make sure nl_msg has enough space */
- new_size = NLMSG_HDRLEN + GENL_HDRLEN + hdrlen;
- if ((sizeof(struct nl_msg) + new_size) > msg->nm_size)
- goto fail;
-
- /* Fill in netlink header */
- nlh = msg->nm_nlh;
- nlh->nlmsg_len = new_size;
- nlh->nlmsg_type = family;
- nlh->nlmsg_pid = getpid();
- nlh->nlmsg_flags = flags | NLM_F_REQUEST | NLM_F_ACK;
-
- /* Get current time for sequence number */
- if (gettimeofday(&tv, NULL))
- nlh->nlmsg_seq = 1;
- else
- nlh->nlmsg_seq = (int) tv.tv_sec;
-
- /* Setup genlmsghdr in new message */
- gmh = (struct genlmsghdr *) ((char *)nlh + NLMSG_HDRLEN);
- gmh->cmd = (__u8) cmd;
- gmh->version = version;
-
- return gmh;
-fail:
- return NULL;
-
-}
-
-/* Socket has already been alloced to connect it to kernel? */
-int genl_connect(struct nl_sock *sk)
-{
- return nl_connect(sk, NETLINK_GENERIC);
-
-}
-
-int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
-{
- int rc = -1;
- int nl80211_genl_id = -1;
- char sendbuf[sizeof(struct nlmsghdr)+sizeof(struct genlmsghdr)];
- struct nlmsghdr nlmhdr;
- struct genlmsghdr gmhhdr;
- struct iovec sendmsg_iov;
- struct msghdr msg;
- int num_char;
- const int RECV_BUF_SIZE = getpagesize();
- char *recvbuf;
- struct iovec recvmsg_iov;
- int nl80211_flag = 0, nlm_f_multi = 0, nlmsg_done = 0;
- struct nlmsghdr *nlh;
-
- /* REQUEST GENERIC NETLINK FAMILY ID */
- /* Message buffer */
- nlmhdr.nlmsg_len = sizeof(sendbuf);
- nlmhdr.nlmsg_type = NETLINK_GENERIC;
- nlmhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP;
- nlmhdr.nlmsg_seq = sock->s_seq_next;
- nlmhdr.nlmsg_pid = sock->s_local.nl_pid;
-
- /* Generic netlink header */
- memset(&gmhhdr, 0, sizeof(gmhhdr));
- gmhhdr.cmd = CTRL_CMD_GETFAMILY;
- gmhhdr.version = CTRL_ATTR_FAMILY_ID;
-
- /* Combine netlink and generic netlink headers */
- memcpy(&sendbuf[0], &nlmhdr, sizeof(nlmhdr));
- memcpy(&sendbuf[0]+sizeof(nlmhdr), &gmhhdr, sizeof(gmhhdr));
-
- /* Create IO vector with Netlink message */
- sendmsg_iov.iov_base = &sendbuf;
- sendmsg_iov.iov_len = sizeof(sendbuf);
-
- /* Socket message */
- msg.msg_name = (void *) &sock->s_peer;
- msg.msg_namelen = sizeof(sock->s_peer);
- msg.msg_iov = &sendmsg_iov;
- msg.msg_iovlen = 1; /* Only sending one iov */
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- /* Send message and verify sent */
- num_char = sendmsg(sock->s_fd, &msg, 0);
- if (num_char == -1)
- return -errno;
-
- /* RECEIVE GENL CMD RESPONSE */
-
- /* Create receive iov buffer */
- recvbuf = (char *) malloc(RECV_BUF_SIZE);
-
- /* Attach to iov */
- recvmsg_iov.iov_base = recvbuf;
- recvmsg_iov.iov_len = RECV_BUF_SIZE;
-
- msg.msg_iov = &recvmsg_iov;
- msg.msg_iovlen = 1;
-
- /***************************************************************/
- /* Receive message. If multipart message, keep receiving until */
- /* message type is NLMSG_DONE */
- /***************************************************************/
-
- do {
-
- int recvmsg_len, nlmsg_rem;
-
- /* Receive message */
- memset(recvbuf, 0, RECV_BUF_SIZE);
- recvmsg_len = recvmsg(sock->s_fd, &msg, 0);
-
- /* Make sure receive successful */
- if (recvmsg_len < 0) {
- rc = -errno;
- goto error_recvbuf;
- }
-
- /* Parse nlmsghdr */
- nlmsg_for_each_msg(nlh, (struct nlmsghdr *) recvbuf, \
- recvmsg_len, nlmsg_rem) {
- struct nlattr *nla;
- int nla_rem;
-
- /* Check type */
- switch (nlh->nlmsg_type) {
- case NLMSG_DONE:
- goto return_genl_id;
- break;
- case NLMSG_ERROR:
-
- /* Should check nlmsgerr struct received */
- fprintf(stderr, "Receive message error\n");
- goto error_recvbuf;
- case NLMSG_OVERRUN:
- fprintf(stderr, "Receive data partly lost\n");
- goto error_recvbuf;
- case NLMSG_MIN_TYPE:
- case NLMSG_NOOP:
- break;
- default:
- break;
- }
-
-
-
- /* Check flags */
- if (nlh->nlmsg_flags & NLM_F_MULTI)
- nlm_f_multi = 1;
- else
- nlm_f_multi = 0;
-
- if (nlh->nlmsg_type & NLMSG_DONE)
- nlmsg_done = 1;
- else
- nlmsg_done = 0;
-
- /* Iteratve over attributes */
- nla_for_each_attr(nla,
- nlmsg_attrdata(nlh, GENL_HDRLEN),
- nlmsg_attrlen(nlh, GENL_HDRLEN),
- nla_rem){
-
- /* If this family is nl80211 */
- if (nla->nla_type == CTRL_ATTR_FAMILY_NAME &&
- !strcmp((char *)nla_data(nla),
- "nl80211"))
- nl80211_flag = 1;
-
- /* Save the family id */
- else if (nl80211_flag &&
- nla->nla_type == CTRL_ATTR_FAMILY_ID) {
- nl80211_genl_id =
- *((int *)nla_data(nla));
- nl80211_flag = 0;
- }
-
- }
-
- }
-
- } while (nlm_f_multi && !nlmsg_done);
-
-return_genl_id:
- /* Return family id as cache pointer */
- *result = (struct nl_cache *) nl80211_genl_id;
- rc = 0;
-error_recvbuf:
- free(recvbuf);
-error:
- return rc;
-}
-
-/* Checks the netlink cache to find family reference by name string */
-/* NOTE: Caller needs to call genl_family_put() when done with *
- * returned object */
-struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, \
- const char *name)
-{
- struct genl_family *gf = (struct genl_family *) \
- malloc(sizeof(struct genl_family));
- if (!gf)
- goto fail;
- memset(gf, 0, sizeof(*gf));
-
- /* Add ref */
- gf->ce_refcnt++;
-
- /* Overriding cache pointer as family id for now */
- gf->gf_id = (uint16_t) ((uint32_t) cache);
- strncpy(gf->gf_name, name, GENL_NAMSIZ);
-
- return gf;
-fail:
- return NULL;
-
-}
-
-int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
-{
- struct nl_cache *cache = NULL;
- struct genl_family *gf = NULL;
- int id = -1;
-
- /* Hack to support wpa_supplicant */
- if (strcmp(name, "nlctrl") == 0)
- return NETLINK_GENERIC;
-
- if (strcmp(name, "nl80211") != 0) {
- fprintf(stderr, "%s is not supported\n", name);
- return id;
- }
-
- if (!genl_ctrl_alloc_cache(sk, &cache)) {
- gf = genl_ctrl_search_by_name(cache, name);
- if (gf)
- id = genl_family_get_id(gf);
- }
-
- if (gf)
- genl_family_put(gf);
- if (cache)
- nl_cache_free(cache);
-
- return id;
-}
diff --git a/libnl_2/handlers.c b/libnl_2/handlers.c
deleted file mode 100644
index 48dcab4..0000000
--- a/libnl_2/handlers.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include <malloc.h>
-#include "netlink-types.h"
-#include "netlink/handlers.h"
-
-/* Allocate a new callback handle. */
-struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind)
-{
- struct nl_cb *cb;
-
- cb = (struct nl_cb *) malloc(sizeof(struct nl_cb));
- if (cb == NULL)
- goto fail;
- memset(cb, 0, sizeof(*cb));
-
- return nl_cb_get(cb);
-fail:
- return NULL;
-}
-
-/* Clone an existing callback handle */
-struct nl_cb *nl_cb_clone(struct nl_cb *orig)
-{
- struct nl_cb *new_cb;
-
- new_cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (new_cb == NULL)
- goto fail;
-
- /* Copy original and set refcount to 1 */
- memcpy(new_cb, orig, sizeof(*orig));
- new_cb->cb_refcnt = 1;
-
- return new_cb;
-fail:
- return NULL;
-}
-
-/* Set up a callback. */
-int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, \
- nl_recvmsg_msg_cb_t func, void *arg)
-{
- cb->cb_set[type] = func;
- cb->cb_args[type] = arg;
- return 0;
-}
-
-
-
-/* Set up an error callback. */
-int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, \
- nl_recvmsg_err_cb_t func, void *arg)
-{
- cb->cb_err = func;
- cb->cb_err_arg = arg;
- return 0;
-
-}
-
-struct nl_cb *nl_cb_get(struct nl_cb *cb)
-{
- cb->cb_refcnt++;
- return cb;
-}
-
-void nl_cb_put(struct nl_cb *cb)
-{
- if (!cb)
- return;
- cb->cb_refcnt--;
- if (cb->cb_refcnt <= 0)
- free(cb);
-}
diff --git a/libnl_2/msg.c b/libnl_2/msg.c
deleted file mode 100644
index 1303e8a..0000000
--- a/libnl_2/msg.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include <malloc.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include "netlink-types.h"
-
-/* Allocate a new netlink message with the default maximum payload size. */
-struct nl_msg *nlmsg_alloc(void)
-{
- /* Whole page will store nl_msg + nlmsghdr + genlmsghdr + payload */
- const int page_sz = getpagesize();
- struct nl_msg *nm;
- struct nlmsghdr *nlh;
-
- /* Netlink message */
- nm = (struct nl_msg *) malloc(page_sz);
- if (!nm)
- goto fail;
-
- /* Netlink message header pointer */
- nlh = (struct nlmsghdr *) ((char *) nm + sizeof(struct nl_msg));
-
- /* Initialize */
- memset(nm, 0, page_sz);
- nm->nm_size = page_sz;
-
- nm->nm_src.nl_family = AF_NETLINK;
- nm->nm_src.nl_pid = getpid();
-
- nm->nm_dst.nl_family = AF_NETLINK;
- nm->nm_dst.nl_pid = 0; /* Kernel */
-
- /* Initialize and add to netlink message */
- nlh->nlmsg_len = NLMSG_HDRLEN;
- nm->nm_nlh = nlh;
-
- /* Add to reference count and return nl_msg */
- nlmsg_get(nm);
- return nm;
-fail:
- return NULL;
-}
-
-/* Return pointer to message payload. */
-void *nlmsg_data(const struct nlmsghdr *nlh)
-{
- return (char *) nlh + NLMSG_HDRLEN;
-}
-
-/* Add reference count to nl_msg */
-void nlmsg_get(struct nl_msg *nm)
-{
- nm->nm_refcnt++;
-}
-
-/* Release a reference from an netlink message. */
-void nlmsg_free(struct nl_msg *nm)
-{
- if (nm) {
- nm->nm_refcnt--;
- if (nm->nm_refcnt <= 0)
- free(nm);
- }
-
-}
-
-/* Return actual netlink message. */
-struct nlmsghdr *nlmsg_hdr(struct nl_msg *n)
-{
- return n->nm_nlh;
-}
-
-/* Return head of attributes data / payload section */
-struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
-{
- unsigned char *data = nlmsg_data(nlh);
- return (struct nlattr *)(data + NLMSG_ALIGN(hdrlen));
-}
-
-/* Returns pointer to end of netlink message */
-void *nlmsg_tail(const struct nlmsghdr *nlh)
-{
- return (void *)((char *)nlh + NLMSG_ALIGN(nlh->nlmsg_len));
-}
-
-/* Next netlink message in message stream */
-struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
-{
- struct nlmsghdr *next_nlh = NULL;
- int len = nlmsg_len(nlh);
-
- len = NLMSG_ALIGN(len);
- if (*remaining > 0 &&
- len <= *remaining &&
- len >= (int) sizeof(struct nlmsghdr)) {
- next_nlh = (struct nlmsghdr *)((char *)nlh + len);
- *remaining -= len;
- }
-
- return next_nlh;
-}
-
-int nlmsg_datalen(const struct nlmsghdr *nlh)
-{
- return nlh->nlmsg_len - NLMSG_HDRLEN;
-}
-
-/* Length of attributes data */
-int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
-{
- return nlmsg_datalen(nlh) - NLMSG_ALIGN(hdrlen);
-}
-
-/* Length of netlink message */
-int nlmsg_len(const struct nlmsghdr *nlh)
-{
- return nlh->nlmsg_len;
-}
-
-/* Check if the netlink message fits into the remaining bytes */
-int nlmsg_ok(const struct nlmsghdr *nlh, int rem)
-{
- return rem >= (int)sizeof(struct nlmsghdr) &&
- rem >= nlmsg_len(nlh) &&
- nlmsg_len(nlh) >= (int) sizeof(struct nlmsghdr) &&
- nlmsg_len(nlh) <= (rem);
-}
-
-int nlmsg_padlen(int payload)
-{
- return NLMSG_ALIGN(payload) - payload;
-}
diff --git a/libnl_2/netlink.c b/libnl_2/netlink.c
deleted file mode 100644
index ee3d600..0000000
--- a/libnl_2/netlink.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include "netlink-types.h"
-
-#define NL_BUFFER_SZ (32768U)
-
-/* Checks message for completeness and sends it out */
-int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
-{
- struct nlmsghdr *nlh = msg->nm_nlh;
- struct timeval tv;
-
- if (!nlh) {
- int errsv = errno;
- fprintf(stderr, "Netlink message header is NULL!\n");
- return -errsv;
- }
-
- /* Complete the nl_msg header */
- if (gettimeofday(&tv, NULL))
- nlh->nlmsg_seq = 1;
- else
- nlh->nlmsg_seq = (int) tv.tv_sec;
- nlh->nlmsg_pid = sk->s_local.nl_pid;
- nlh->nlmsg_flags |= NLM_F_REQUEST | NLM_F_ACK;
-
- return nl_send(sk, msg);
-}
-
-/* Receives a netlink message, allocates a buffer in *buf and stores
- * the message content. The peer's netlink address is stored in
- * *nla. The caller is responsible for freeing the buffer allocated in
- * *buf if a positive value is returned. Interrupted system calls are
- * handled by repeating the read. The input buffer size is determined
- * by peeking before the actual read is done */
-int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla, \
- unsigned char **buf, struct ucred **creds)
-{
- int rc = -1;
- int sk_flags;
- int RECV_BUF_SIZE = getpagesize();
- int errsv;
- struct iovec recvmsg_iov;
- struct msghdr msg;
-
- /* Allocate buffer */
- *buf = (unsigned char *) malloc(RECV_BUF_SIZE);
- if (!(*buf)) {
- rc = -ENOMEM;
- goto fail;
- }
-
- /* Prepare to receive message */
- recvmsg_iov.iov_base = *buf;
- recvmsg_iov.iov_len = RECV_BUF_SIZE;
-
- msg.msg_name = (void *) &sk->s_peer;
- msg.msg_namelen = sizeof(sk->s_peer);
- msg.msg_iov = &recvmsg_iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- /* Make non blocking and then restore previous setting */
- sk_flags = fcntl(sk->s_fd, F_GETFL, 0);
- fcntl(sk->s_fd, F_SETFL, O_NONBLOCK);
- rc = recvmsg(sk->s_fd, &msg, 0);
- errsv = errno;
- fcntl(sk->s_fd, F_SETFL, sk_flags);
-
- if (rc < 0) {
- rc = -errsv;
- free(*buf);
- *buf = NULL;
- }
-
-fail:
- return rc;
-}
-
-/* Receive a set of messages from a netlink socket */
-/* NOTE: Does not currently support callback replacements!!! */
-int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
-{
- struct sockaddr_nl nla;
- struct ucred *creds;
-
- int rc, cb_rc = NL_OK, done = 0;
-
- do {
- unsigned char *buf;
- int i, rem, flags;
- struct nlmsghdr *nlh;
- struct nlmsgerr *nlme;
- struct nl_msg *msg;
-
- done = 0;
- rc = nl_recv(sk, &nla, &buf, &creds);
- if (rc < 0)
- break;
-
- nlmsg_for_each_msg(nlh, (struct nlmsghdr *) buf, rc, rem) {
-
- if (rc <= 0 || cb_rc == NL_STOP)
- break;
-
- /* Check for callbacks */
-
- msg = (struct nl_msg *) malloc(sizeof(struct nl_msg));
- memset(msg, 0, sizeof(*msg));
- msg->nm_nlh = nlh;
-
- /* Check netlink message type */
-
- switch (msg->nm_nlh->nlmsg_type) {
- case NLMSG_ERROR: /* Used for ACK too */
- /* Certainly we should be doing some
- * checking here to make sure this
- * message is intended for us */
- nlme = nlmsg_data(msg->nm_nlh);
- if (nlme->error == 0)
- msg->nm_nlh->nlmsg_flags |= NLM_F_ACK;
-
- rc = nlme->error;
- cb_rc = cb->cb_err(&nla, nlme, cb->cb_err_arg);
- nlme = NULL;
- break;
-
- case NLMSG_DONE:
- done = 1;
-
- case NLMSG_OVERRUN:
- case NLMSG_NOOP:
- default:
- break;
- };
-
- for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
-
- if (cb->cb_set[i]) {
- switch (i) {
- case NL_CB_VALID:
- if (rc > 0)
- cb_rc = cb->cb_set[i](msg, cb->cb_args[i]);
- break;
-
- case NL_CB_FINISH:
- if ((msg->nm_nlh->nlmsg_flags & NLM_F_MULTI) &&
- (msg->nm_nlh->nlmsg_type & NLMSG_DONE))
- cb_rc = cb->cb_set[i](msg, cb->cb_args[i]);
-
- break;
-
- case NL_CB_ACK:
- if (msg->nm_nlh->nlmsg_flags & NLM_F_ACK)
- cb_rc = cb->cb_set[i](msg, cb->cb_args[i]);
-
- break;
- default:
- break;
- }
- }
- }
-
- free(msg);
- if (done)
- break;
- }
- free(buf);
- buf = NULL;
-
- if (done)
- break;
- } while (rc > 0 && cb_rc != NL_STOP);
-
-success:
-fail:
- return rc;
-}
-
-/* Send raw data over netlink socket */
-int nl_send(struct nl_sock *sk, struct nl_msg *msg)
-{
- struct nlmsghdr *nlh = nlmsg_hdr(msg);
- struct iovec msg_iov;
-
- /* Create IO vector with Netlink message */
- msg_iov.iov_base = nlh;
- msg_iov.iov_len = nlh->nlmsg_len;
-
- return nl_send_iovec(sk, msg, &msg_iov, 1);
-}
-
-/* Send netlink message */
-int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg,
- struct iovec *iov, unsigned iovlen)
-{
- int rc;
-
- /* Socket message */
- struct msghdr mh = {
- .msg_name = (void *) &sk->s_peer,
- .msg_namelen = sizeof(sk->s_peer),
- .msg_iov = iov,
- .msg_iovlen = iovlen,
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_flags = 0
- };
-
- /* Send message and verify sent */
- rc = nl_sendmsg(sk, (struct nl_msg *) &mh, 0);
- if (rc < 0)
- fprintf(stderr, "Error sending netlink message: %d\n", errno);
- return rc;
-
-}
-
-/* Send netlink message with control over sendmsg() message header */
-int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
-{
- return sendmsg(sk->s_fd, (struct msghdr *) msg, (int) hdr);
-}
-
-/* Create and connect netlink socket */
-int nl_connect(struct nl_sock *sk, int protocol)
-{
- struct sockaddr addr;
- socklen_t addrlen;
- int rc;
-
- /* Create RX socket */
- sk->s_fd = socket(PF_NETLINK, SOCK_RAW, protocol);
- if (sk->s_fd < 0)
- return -errno;
-
- /* Set size of RX and TX buffers */
- if (nl_socket_set_buffer_size(sk, NL_BUFFER_SZ, NL_BUFFER_SZ) < 0)
- return -errno;
-
- /* Bind RX socket */
- rc = bind(sk->s_fd, (struct sockaddr *)&sk->s_local, \
- sizeof(sk->s_local));
- if (rc < 0)
- return -errno;
- addrlen = sizeof(addr);
- getsockname(sk->s_fd, &addr, &addrlen);
-
- return 0;
-
-}
diff --git a/libnl_2/object.c b/libnl_2/object.c
deleted file mode 100644
index c53accf..0000000
--- a/libnl_2/object.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include "netlink-types.h"
-
-void nl_object_put(struct nl_object *obj)
-{
- obj->ce_refcnt--;
- if (!obj->ce_refcnt)
- nl_object_free(obj);
-}
-
-void nl_object_free(struct nl_object *obj)
-{
- nl_cache_remove(obj);
-}
-
-
diff --git a/libnl_2/socket.c b/libnl_2/socket.c
deleted file mode 100644
index f51cf56..0000000
--- a/libnl_2/socket.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* NOTICE: This is a clean room re-implementation of libnl */
-
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <malloc.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include "netlink-types.h"
-
-/* Join group */
-int nl_socket_add_membership(struct nl_sock *sk, int group)
-{
- return setsockopt(sk->s_fd, SOL_NETLINK,
- NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
-}
-
-/* Allocate new netlink socket. */
-static struct nl_sock *_nl_socket_alloc(void)
-{
- struct nl_sock *sk;
- struct timeval tv;
- struct nl_cb *cb;
-
- sk = (struct nl_sock *) malloc(sizeof(struct nl_sock));
- if (!sk)
- return NULL;
- memset(sk, 0, sizeof(*sk));
-
- /* Get current time */
-
- if (gettimeofday(&tv, NULL))
- goto fail;
- else
- sk->s_seq_next = (int) tv.tv_sec;
-
- /* Create local socket */
- sk->s_local.nl_family = AF_NETLINK;
- sk->s_local.nl_pid = 0; /* Kernel fills in pid */
- sk->s_local.nl_groups = 0; /* No groups */
-
- /* Create peer socket */
- sk->s_peer.nl_family = AF_NETLINK;
- sk->s_peer.nl_pid = 0; /* Kernel */
- sk->s_peer.nl_groups = 0; /* No groups */
-
- return sk;
-fail:
- free(sk);
- return NULL;
-}
-
-/* Allocate new netlink socket. */
-struct nl_sock *nl_socket_alloc(void)
-{
- struct nl_sock *sk = _nl_socket_alloc();
- struct nl_cb *cb;
-
- if (!sk)
- return NULL;
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (!cb)
- goto cb_fail;
- sk->s_cb = cb;
- return sk;
-cb_fail:
- free(sk);
- return NULL;
-}
-
-/* Allocate new socket with custom callbacks. */
-struct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb)
-{
- struct nl_sock *sk = _nl_socket_alloc();
-
- if (!sk)
- return NULL;
-
- sk->s_cb = cb;
- nl_cb_get(cb);
-
- return sk;
-}
-
-/* Free a netlink socket. */
-void nl_socket_free(struct nl_sock *sk)
-{
- nl_cb_put(sk->s_cb);
- close(sk->s_fd);
- free(sk);
-}
-
-/* Sets socket buffer size of netlink socket */
-int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
-{
- if (setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF, \
- &rxbuf, (socklen_t) sizeof(rxbuf)))
- goto error;
-
- if (setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF, \
- &txbuf, (socklen_t) sizeof(txbuf)))
- goto error;
-
- return 0;
-error:
- return -errno;
-
-}
-
-int nl_socket_get_fd(struct nl_sock *sk)
-{
- return sk->s_fd;
-}
-
-void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb)
-{
- nl_cb_put(sk->s_cb);
- sk->s_cb = cb;
- nl_cb_get(cb);
-}
-
-struct nl_cb *nl_socket_get_cb(struct nl_sock *sk)
-{
- return nl_cb_get(sk->s_cb);
-}
-
-int nl_socket_set_nonblocking(struct nl_sock *sk)
-{
- if (sk->s_fd == -1)
- return -NLE_BAD_SOCK;
-
- if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index f398a82..385c226 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -109,7 +109,7 @@
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
- refs->stack.dump(LOG_TAG);
+ refs->stack.log(LOG_TAG);
#endif
refs = refs->next;
}
@@ -123,7 +123,7 @@
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
- refs->stack.dump(LOG_TAG);
+ refs->stack.log(LOG_TAG);
#endif
refs = refs->next;
}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 5960609..5a80efe 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -807,7 +807,10 @@
// squash out the byte count
cp = buf;
if (!truncated) {
- while (isdigit(*cp) || (*cp == '\n')) {
+ while (isdigit(*cp)) {
+ ++cp;
+ }
+ if (*cp == '\n') {
++cp;
}
}
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 818a978..0165073 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -14,8 +14,11 @@
* limitations under the License.
*/
+#include <ctype.h>
#include <signal.h>
#include <stdio.h>
+#include <string.h>
+
#include <gtest/gtest.h>
#include <log/log.h>
#include <log/logger.h>
@@ -41,7 +44,7 @@
TEST(logcat, sorted_order) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -v time -b radio -b events -b system -b main -d 2>/dev/null",
"r")));
@@ -92,34 +95,49 @@
}
} last(NULL);
+ char *last_buffer = NULL;
char buffer[5120];
int count = 0;
+ int next_lt_last = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncmp(begin, buffer, sizeof(begin) - 1)) {
continue;
}
if (!last.valid()) {
+ free(last_buffer);
+ last_buffer = strdup(buffer);
last.init(buffer);
}
timestamp next(buffer);
- ASSERT_EQ(0, next < last);
+ if (next < last) {
+ if (last_buffer) {
+ fprintf(stderr, "<%s", last_buffer);
+ }
+ fprintf(stderr, ">%s", buffer);
+ ++next_lt_last;
+ }
if (next.valid()) {
+ free(last_buffer);
+ last_buffer = strdup(buffer);
last.init(buffer);
}
++count;
}
+ free(last_buffer);
pclose(fp);
- ASSERT_LT(100, count);
+ EXPECT_EQ(0, next_lt_last);
+
+ EXPECT_LT(100, count);
}
TEST(logcat, buckets) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -b radio -b events -b system -b main -d 2>/dev/null",
"r")));
@@ -141,15 +159,15 @@
pclose(fp);
- ASSERT_EQ(15, ids);
+ EXPECT_EQ(15, ids);
- ASSERT_EQ(4, count);
+ EXPECT_EQ(4, count);
}
TEST(logcat, tail_3) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -b radio -b events -b system -b main -t 3 2>/dev/null",
"r")));
@@ -173,7 +191,7 @@
TEST(logcat, tail_10) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -b radio -b events -b system -b main -t 10 2>/dev/null",
"r")));
@@ -197,7 +215,7 @@
TEST(logcat, tail_100) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -b radio -b events -b system -b main -t 100 2>/dev/null",
"r")));
@@ -221,7 +239,7 @@
TEST(logcat, tail_1000) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -b radio -b events -b system -b main -t 1000 2>/dev/null",
"r")));
@@ -242,6 +260,72 @@
ASSERT_EQ(1000, count);
}
+TEST(logcat, tail_time) {
+ FILE *fp;
+
+ ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r")));
+
+ char buffer[5120];
+ char *last_timestamp = NULL;
+ char *first_timestamp = NULL;
+ int count = 0;
+ const unsigned int time_length = 18;
+ const unsigned int time_offset = 2;
+
+ while (fgets(buffer, sizeof(buffer), fp)) {
+ if ((buffer[0] == '[') && (buffer[1] == ' ')
+ && isdigit(buffer[time_offset]) && isdigit(buffer[time_offset + 1])
+ && (buffer[time_offset + 2] == '-')) {
+ ++count;
+ buffer[time_length + time_offset] = '\0';
+ if (!first_timestamp) {
+ first_timestamp = strdup(buffer + time_offset);
+ }
+ free(last_timestamp);
+ last_timestamp = strdup(buffer + time_offset);
+ }
+ }
+ pclose(fp);
+
+ EXPECT_EQ(10, count);
+ EXPECT_TRUE(last_timestamp != NULL);
+ EXPECT_TRUE(first_timestamp != NULL);
+
+ snprintf(buffer, sizeof(buffer), "logcat -v long -b all -t '%s' 2>&1",
+ first_timestamp);
+ ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
+
+ int second_count = 0;
+ int last_timestamp_count = -1;
+
+ while (fgets(buffer, sizeof(buffer), fp)) {
+ if ((buffer[0] == '[') && (buffer[1] == ' ')
+ && isdigit(buffer[time_offset]) && isdigit(buffer[time_offset + 1])
+ && (buffer[time_offset + 2] == '-')) {
+ ++second_count;
+ buffer[time_length + time_offset] = '\0';
+ if (first_timestamp) {
+ // we can get a transitory *extremely* rare failure if hidden
+ // underneath the time is *exactly* XX-XX XX:XX:XX.XXX000000
+ EXPECT_STREQ(buffer + time_offset, first_timestamp);
+ free(first_timestamp);
+ first_timestamp = NULL;
+ }
+ if (!strcmp(buffer + time_offset, last_timestamp)) {
+ last_timestamp_count = second_count;
+ }
+ }
+ }
+ pclose(fp);
+
+ free(last_timestamp);
+ last_timestamp = NULL;
+
+ EXPECT_TRUE(first_timestamp == NULL);
+ EXPECT_LE(count, second_count);
+ EXPECT_LE(count, last_timestamp_count);
+}
+
TEST(logcat, End_to_End) {
pid_t pid = getpid();
@@ -250,7 +334,7 @@
ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -b events -t 100 2>/dev/null",
"r")));
@@ -281,7 +365,7 @@
TEST(logcat, get_) {
FILE *fp;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"logcat -b radio -b events -b system -b main -g 2>/dev/null",
"r")));
@@ -329,7 +413,7 @@
v &= 0xFFFFFFFFFFFAFFFFULL;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
" logcat -b events 2>&1",
"r")));
@@ -343,7 +427,6 @@
signal(SIGALRM, caught_blocking);
alarm(2);
while (fgets(buffer, sizeof(buffer), fp)) {
- alarm(2);
if (!strncmp(buffer, "DONE", 4)) {
break;
@@ -373,9 +456,9 @@
pclose(fp);
- ASSERT_LE(2, count);
+ EXPECT_LE(2, count);
- ASSERT_EQ(1, signals);
+ EXPECT_EQ(1, signals);
}
static void caught_blocking_tail(int signum)
@@ -399,7 +482,7 @@
v &= 0xFFFAFFFFFFFFFFFFULL;
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
" logcat -b events -T 5 2>&1",
"r")));
@@ -413,7 +496,6 @@
signal(SIGALRM, caught_blocking_tail);
alarm(2);
while (fgets(buffer, sizeof(buffer), fp)) {
- alarm(2);
if (!strncmp(buffer, "DONE", 4)) {
break;
@@ -445,9 +527,9 @@
pclose(fp);
- ASSERT_LE(2, count);
+ EXPECT_LE(2, count);
- ASSERT_EQ(1, signals);
+ EXPECT_EQ(1, signals);
}
static void caught_blocking_clear(int signum)
@@ -469,7 +551,7 @@
// This test is racey; an event occurs between clear and dump.
// We accept that we will get a false positive, but never a false negative.
- ASSERT_EQ(0, NULL == (fp = popen(
+ ASSERT_TRUE(NULL != (fp = popen(
"( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
" logcat -b events -c 2>&1 ;"
" logcat -b events 2>&1",
@@ -484,7 +566,6 @@
signal(SIGALRM, caught_blocking_clear);
alarm(2);
while (fgets(buffer, sizeof(buffer), fp)) {
- alarm(2);
if (!strncmp(buffer, "clearLog: ", 10)) {
fprintf(stderr, "WARNING: Test lacks permission to run :-(\n");
@@ -523,9 +604,9 @@
pclose(fp);
- ASSERT_LE(1, count);
+ EXPECT_LE(1, count);
- ASSERT_EQ(1, signals);
+ EXPECT_EQ(1, signals);
}
#ifdef USERDEBUG_BUILD
@@ -601,22 +682,23 @@
ASSERT_EQ(true, get_white_black(&list));
- static const char adjustment[] = "~! ~1000";
+ static const char adjustment[] = "~! 300/20 300/25 2000 ~1000/5 ~1000/30";
ASSERT_EQ(true, set_white_black(adjustment));
ASSERT_EQ(true, get_white_black(&adjust));
- if (strcmp(adjustment, adjust)) {
- fprintf(stderr, "ERROR: '%s' != '%s'\n", adjustment, adjust);
- }
- ASSERT_STREQ(adjustment, adjust);
+ EXPECT_STREQ(adjustment, adjust);
+ free(adjust);
+ adjust = NULL;
+
+ static const char adjustment2[] = "300/20 300/21 2000 ~1000";
+ ASSERT_EQ(true, set_white_black(adjustment2));
+ ASSERT_EQ(true, get_white_black(&adjust));
+ EXPECT_STREQ(adjustment2, adjust);
free(adjust);
adjust = NULL;
ASSERT_EQ(true, set_white_black(list));
ASSERT_EQ(true, get_white_black(&adjust));
- if (strcmp(list, adjust)) {
- fprintf(stderr, "ERROR: '%s' != '%s'\n", list, adjust);
- }
- ASSERT_STREQ(list, adjust);
+ EXPECT_STREQ(list, adjust);
free(adjust);
adjust = NULL;
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 197b7e8..81eb091 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -37,6 +37,8 @@
LogBuffer::LogBuffer(LastLogTimes *times)
: mTimes(*times) {
pthread_mutex_init(&mLogElementsLock, NULL);
+ dgram_qlen_statistics = false;
+
#ifdef USERDEBUG_BUILD
log_id_for_each(i) {
mMaxSize[i] = LOG_BUFFER_SIZE;
@@ -45,13 +47,13 @@
}
void LogBuffer::log(log_id_t log_id, log_time realtime,
- uid_t uid, pid_t pid, const char *msg,
- unsigned short len) {
+ uid_t uid, pid_t pid, pid_t tid,
+ const char *msg, unsigned short len) {
if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
return;
}
LogBufferElement *elem = new LogBufferElement(log_id, realtime,
- uid, pid, msg, len);
+ uid, pid, tid, msg, len);
pthread_mutex_lock(&mLogElementsLock);
@@ -61,6 +63,23 @@
LogBufferElementCollection::iterator last = it;
while (--it != mLogElements.begin()) {
if ((*it)->getRealTime() <= realtime) {
+ // halves the peak performance, use with caution
+ if (dgram_qlen_statistics) {
+ LogBufferElementCollection::iterator ib = it;
+ unsigned short buckets, num = 1;
+ for (unsigned short i = 0; (buckets = stats.dgram_qlen(i)); ++i) {
+ buckets -= num;
+ num += buckets;
+ while (buckets && (--ib != mLogElements.begin())) {
+ --buckets;
+ }
+ if (buckets) {
+ break;
+ }
+ stats.recordDiff(
+ elem->getRealTime() - (*ib)->getRealTime(), i);
+ }
+ }
break;
}
last = it;
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 0745e56..c3460ca 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -36,6 +36,8 @@
LogStatistics stats;
+ bool dgram_qlen_statistics;
+
#ifdef USERDEBUG_BUILD
PruneList mPrune;
@@ -48,7 +50,8 @@
LogBuffer(LastLogTimes *times);
void log(log_id_t log_id, log_time realtime,
- uid_t uid, pid_t pid, const char *msg, unsigned short len);
+ uid_t uid, pid_t pid, pid_t tid,
+ const char *msg, unsigned short len);
log_time flushTo(SocketClient *writer, const log_time start,
bool privileged,
bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
@@ -63,6 +66,11 @@
// *strp uses malloc, use free to release.
void formatStatistics(char **strp, uid_t uid, unsigned int logMask);
+ void enableDgramQlenStatistics() {
+ stats.enableDgramQlenStatistics();
+ dgram_qlen_statistics = true;
+ }
+
#ifdef USERDEBUG_BUILD
int initPrune(char *cp) { return mPrune.init(cp); }
// *strp uses malloc, use free to release.
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 8d45f34..d959ceb 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -27,11 +27,12 @@
const log_time LogBufferElement::FLUSH_ERROR((uint32_t)0, (uint32_t)0);
LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
- uid_t uid, pid_t pid, const char *msg,
- unsigned short len)
+ uid_t uid, pid_t pid, pid_t tid,
+ const char *msg, unsigned short len)
: mLogId(log_id)
, mUid(uid)
, mPid(pid)
+ , mTid(tid)
, mMsgLen(len)
, mMonotonicTime(CLOCK_MONOTONIC)
, mRealTime(realtime) {
@@ -50,6 +51,7 @@
entry.len = mMsgLen;
entry.lid = mLogId;
entry.pid = mPid;
+ entry.tid = mTid;
entry.sec = mRealTime.tv_sec;
entry.nsec = mRealTime.tv_nsec;
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 1da09ae..fdca973 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -26,6 +26,7 @@
const log_id_t mLogId;
const uid_t mUid;
const pid_t mPid;
+ const pid_t mTid;
char *mMsg;
const unsigned short mMsgLen;
const log_time mMonotonicTime;
@@ -33,12 +34,14 @@
public:
LogBufferElement(log_id_t log_id, log_time realtime,
- uid_t uid, pid_t pid, const char *msg, unsigned short len);
+ uid_t uid, pid_t pid, pid_t tid,
+ const char *msg, unsigned short len);
virtual ~LogBufferElement();
log_id_t getLogId() const { return mLogId; }
uid_t getUid(void) const { return mUid; }
pid_t getPid(void) const { return mPid; }
+ pid_t getTid(void) const { return mTid; }
unsigned short getMsgLen() const { return mMsgLen; }
log_time getMonotonicTime(void) const { return mMonotonicTime; }
log_time getRealTime(void) const { return mRealTime; }
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 2aa2ebb..b835b4f 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -50,7 +50,7 @@
int socket = cli->getSocket();
ssize_t n = recvmsg(socket, &hdr, 0);
- if (n <= (ssize_t) sizeof_log_id_t) {
+ if (n <= (ssize_t)(sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time))) {
return false;
}
@@ -82,17 +82,24 @@
if (log_id < 0 || log_id >= LOG_ID_MAX) {
return false;
}
-
char *msg = ((char *)buffer) + sizeof_log_id_t;
n -= sizeof_log_id_t;
+ // second element is the thread id of the caller
+ pid_t tid = (pid_t) *((uint16_t *) msg);
+ msg += sizeof(uint16_t);
+ n -= sizeof(uint16_t);
+
+ // third element is the realtime at point of caller
log_time realtime(msg);
msg += sizeof(log_time);
n -= sizeof(log_time);
- unsigned short len = n;
+ // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
+ // truncated message to the logs.
+ unsigned short len = n; // cap to internal maximum
if (len == n) {
- logbuf->log(log_id, realtime, cred->uid, cred->pid, msg, len);
+ logbuf->log(log_id, realtime, cred->uid, cred->pid, tid, msg, len);
reader->notifyNewLog();
}
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 49ee50d..5622ee5 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -275,6 +275,66 @@
mSizes[i] = 0;
mElements[i] = 0;
}
+
+ dgram_qlen_statistics = false;
+ for(unsigned short bucket = 0; dgram_qlen(bucket); ++bucket) {
+ mMinimum[bucket].tv_sec = (uint32_t)-1;
+ mMinimum[bucket].tv_nsec = 999999999UL;
+ }
+}
+
+// Each bucket below represents a dgram_qlen of log messages. By
+// finding the minimum period of time from start to finish
+// of each dgram_qlen, we can get a performance expectation for
+// the user space logger. The net result is that the period
+// of time divided by the dgram_qlen will give us the average time
+// between log messages; at the point where the average time
+// is greater than the throughput capability of the logger
+// we will not longer require the benefits of the FIFO formed
+// by max_dgram_qlen. We will also expect to see a very visible
+// knee in the average time between log messages at this point,
+// so we do not necessarily have to compare the rate against the
+// measured performance (BM_log_maximum_retry) of the logger.
+//
+// for example (reformatted):
+//
+// Minimum time between log events per dgram_qlen:
+// 1 2 3 5 10 20 30 50 100 200 300 400 500 600
+// 5u2 12u 13u 15u 16u 27u 30u 36u 407u 3m1 3m3 3m9 3m9 5m5
+//
+// demonstrates a clear knee rising at 100, so this means that for this
+// case max_dgram_qlen = 100 would be more than sufficient to handle the
+// worst that the system could stuff into the logger. The
+// BM_log_maximum_retry performance (derated by the log collection) on the
+// same system was 33.2us so we would almost be fine with max_dgram_qlen = 50.
+// BM_log_maxumum_retry with statistics off is roughly 20us, so
+// max_dgram_qlen = 20 would work. We will be more than willing to have
+// a large engineering margin so the rule of thumb that lead us to 100 is
+// fine.
+//
+// bucket dgram_qlen are tuned for /proc/sys/net/unix/max_dgram_qlen = 300
+const unsigned short LogStatistics::mBuckets[] = {
+ 1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 400, 500, 600
+};
+
+unsigned short LogStatistics::dgram_qlen(unsigned short bucket) {
+ if (bucket >= sizeof(mBuckets) / sizeof(mBuckets[0])) {
+ return 0;
+ }
+ return mBuckets[bucket];
+}
+
+unsigned long long LogStatistics::minimum(unsigned short bucket) {
+ if (mMinimum[bucket].tv_sec == LONG_MAX) {
+ return 0;
+ }
+ return mMinimum[bucket].nsec();
+}
+
+void LogStatistics::recordDiff(log_time diff, unsigned short bucket) {
+ if ((diff.tv_sec || diff.tv_nsec) && (mMinimum[bucket] > diff)) {
+ mMinimum[bucket] = diff;
+ }
}
void LogStatistics::add(unsigned short size,
@@ -352,6 +412,9 @@
log_id_for_each(i) {
if (logMask & (1 << i)) {
oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s%s", spaces, "", android_log_id_to_name(i));
spaces += spaces_total + oldLength - string.length();
}
@@ -369,6 +432,9 @@
continue;
}
oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s%zu/%zu", spaces, "",
sizesTotal(i), elementsTotal(i));
spaces += spaces_total + oldLength - string.length();
@@ -388,12 +454,64 @@
size_t els = elements(i);
if (els) {
oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s%zu/%zu", spaces, "", sizes(i), els);
spaces -= string.length() - oldLength;
}
spaces += spaces_total;
}
+ if (dgram_qlen_statistics) {
+ const unsigned short spaces_time = 6;
+ const unsigned long long max_seconds = 100000;
+ spaces = 0;
+ string.append("\n\nMinimum time between log events per dgram_qlen:\n");
+ for(unsigned short i = 0; dgram_qlen(i); ++i) {
+ oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
+ string.appendFormat("%*s%u", spaces, "", dgram_qlen(i));
+ spaces += spaces_time + oldLength - string.length();
+ }
+ string.append("\n");
+ spaces = 0;
+ unsigned short n;
+ for(unsigned short i = 0; (n = dgram_qlen(i)); ++i) {
+ unsigned long long duration = minimum(i);
+ if (duration) {
+ duration /= n;
+ if (duration >= (NS_PER_SEC * max_seconds)) {
+ duration = NS_PER_SEC * (max_seconds - 1);
+ }
+ oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
+ string.appendFormat("%*s", spaces, "");
+ if (duration >= (NS_PER_SEC * 10)) {
+ string.appendFormat("%llu",
+ (duration + (NS_PER_SEC / 2))
+ / NS_PER_SEC);
+ } else if (duration >= (NS_PER_SEC / (1000 / 10))) {
+ string.appendFormat("%llum",
+ (duration + (NS_PER_SEC / 2 / 1000))
+ / (NS_PER_SEC / 1000));
+ } else if (duration >= (NS_PER_SEC / (1000000 / 10))) {
+ string.appendFormat("%lluu",
+ (duration + (NS_PER_SEC / 2 / 1000000))
+ / (NS_PER_SEC / 1000000));
+ } else {
+ string.appendFormat("%llun", duration);
+ }
+ spaces -= string.length() - oldLength;
+ }
+ spaces += spaces_time;
+ }
+ }
+
log_id_for_each(i) {
if (!(logMask & (1 << i))) {
continue;
@@ -433,7 +551,7 @@
if (!oneline) {
first = true;
- } else if (!first && spaces) {
+ } else if (!first && (spaces > 0)) {
string.appendFormat("%*s", spaces, "");
}
spaces = 0;
@@ -458,10 +576,16 @@
size_t els = up->elements();
if (els == elsTotal) {
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s=", spaces, "");
spaces = -1;
} else if (els) {
oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s%zu/%zu", spaces, "", up->sizes(), els);
spaces -= string.length() - oldLength;
}
@@ -502,7 +626,7 @@
continue;
}
- if (!first && spaces) {
+ if (!first && (spaces > 0)) {
string.appendFormat("%*s", spaces, "");
}
spaces = 0;
@@ -517,10 +641,16 @@
spaces += spaces_total + oldLength - string.length();
if (els == elsTotal) {
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s=", spaces, "");
spaces = -1;
} else if (els) {
oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
string.appendFormat("%*s%zu/%zu", spaces, "",
pp->sizes(), els);
spaces -= string.length() - oldLength;
@@ -531,7 +661,7 @@
}
if (gone_els) {
- if (!first && spaces) {
+ if (!first && (spaces > 0)) {
string.appendFormat("%*s", spaces, "");
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index d44afa2..6a26263 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -114,6 +114,11 @@
size_t mSizes[LOG_ID_MAX];
size_t mElements[LOG_ID_MAX];
+ bool dgram_qlen_statistics;
+
+ static const unsigned short mBuckets[14];
+ log_time mMinimum[sizeof(mBuckets) / sizeof(mBuckets[0])];
+
public:
const log_time start;
@@ -121,6 +126,11 @@
LidStatistics &id(log_id_t log_id) { return LogIds[log_id]; }
+ void enableDgramQlenStatistics() { dgram_qlen_statistics = true; }
+ static unsigned short dgram_qlen(unsigned short bucket);
+ unsigned long long minimum(unsigned short bucket);
+ void recordDiff(log_time diff, unsigned short bucket);
+
void add(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
void subtract(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index d0ceb9f..5f8173f 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -154,8 +154,8 @@
}
m = pid - p->mPid;
}
- if (m >= 0) {
- if (m > 0) {
+ if (m <= 0) {
+ if (m < 0) {
list->insert(it, new Prune(uid,pid));
}
break;
diff --git a/logd/main.cpp b/logd/main.cpp
index 6216b95..8792d32 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -24,9 +24,12 @@
#include <sys/capability.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <unistd.h>
#include <linux/prctl.h>
+#include <cutils/properties.h>
+
#include "private/android_filesystem_config.h"
#include "CommandListener.h"
#include "LogBuffer.h"
@@ -92,6 +95,12 @@
LogBuffer *logBuf = new LogBuffer(times);
+ char dgram_qlen_statistics[PROPERTY_VALUE_MAX];
+ property_get("logd.dgram_qlen.statistics", dgram_qlen_statistics, "");
+ if (atol(dgram_qlen_statistics)) {
+ logBuf->enableDgramQlenStatistics();
+ }
+
// LogReader listens on /dev/socket/logdr. When a client
// connects, log entries in the LogBuffer are written to the client.
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5675cac..6a053b3 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -7,6 +7,7 @@
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
+import /init.${ro.zygote}.rc
import /init.trace.rc
on early-init
@@ -399,6 +400,11 @@
start surfaceflinger
start defaultcrypto
+on property:vold.decrypt=trigger_encryption
+ start surfaceflinger
+ start encrypt
+ class_start main
+
on charger
class_start charger
@@ -442,6 +448,13 @@
critical
seclabel u:r:ueventd:s0
+service logd /system/bin/logd
+ class core
+ socket logd stream 0666 logd logd
+ socket logdr seqpacket 0666 logd logd
+ socket logdw dgram 0222 logd logd
+ seclabel u:r:logd:s0
+
service healthd /sbin/healthd
class core
critical
@@ -474,12 +487,6 @@
critical
socket lmkd seqpacket 0660 system system
-service logd /system/bin/logd
- class main
- socket logd stream 0666 logd logd
- socket logdr seqpacket 0666 logd logd
- socket logdw dgram 0222 logd logd
-
service servicemanager /system/bin/servicemanager
class core
user system
@@ -528,14 +535,6 @@
group input
onrestart restart zygote
-service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
- class main
- socket zygote stream 660 root system
- onrestart write /sys/android_power/request_state wake
- onrestart write /sys/power/state on
- onrestart restart media
- onrestart restart netd
-
service drm /system/bin/drmserver
class main
user drm
@@ -554,6 +553,13 @@
# vold will set vold.decrypt to trigger_restart_framework (default
# encryption) or trigger_restart_min_framework (other encryption)
+# One shot invocation to encrypt unencrypted volumes
+service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace
+ disabled
+ oneshot
+ # vold will set vold.decrypt to trigger_restart_framework (default
+ # encryption)
+
service bootanim /system/bin/bootanimation
class main
user graphics
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
new file mode 100644
index 0000000..75961e6
--- /dev/null
+++ b/rootdir/init.zygote32.rc
@@ -0,0 +1,8 @@
+service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
+ class main
+ socket zygote stream 660 root system
+ onrestart write /sys/android_power/request_state wake
+ onrestart write /sys/power/state on
+ onrestart restart media
+ onrestart restart netd
+
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
new file mode 100644
index 0000000..afb6d63
--- /dev/null
+++ b/rootdir/init.zygote64.rc
@@ -0,0 +1,8 @@
+service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
+ class main
+ socket zygote stream 660 root system
+ onrestart write /sys/android_power/request_state wake
+ onrestart write /sys/power/state on
+ onrestart restart media
+ onrestart restart netd
+
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 9bf17e2..b8fe716 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -35,7 +35,7 @@
/dev/uhid 0660 system net_bt_stack
/dev/uinput 0660 system net_bt_stack
/dev/alarm 0664 system radio
-/dev/rtc0 0664 system radio
+/dev/rtc0 0640 system system
/dev/tty0 0660 root system
/dev/graphics/* 0660 root graphics
/dev/msm_hw3dm 0660 system graphics