Merge korg/donut into korg/master

This commit is contained in:
Jean-Baptiste Queru 2009-07-25 18:07:41 -07:00
commit 96d58f4f52
163 changed files with 8940 additions and 4023 deletions

View File

@ -21,6 +21,7 @@ else
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
adb \
libcutils \
libsysutils \
liblog \
libnetutils \
libpixelflinger \

View File

@ -7,7 +7,6 @@ LOCAL_PATH:= $(call my-dir)
# adb host tool
# =========================================================
ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean (also unused with the sim)
include $(CLEAR_VARS)
# Default to a virtual (sockets) usb interface
@ -54,10 +53,13 @@ LOCAL_SRC_FILES := \
$(USB_SRCS) \
shlist.c \
utils.c \
usb_vendors.c \
ifneq ($(USE_SYSDEPS_WIN32),)
LOCAL_SRC_FILES += sysdeps_win32.c
else
LOCAL_SRC_FILES += fdevent.c
endif
LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter
@ -77,7 +79,6 @@ ifeq ($(HOST_OS),windows)
$(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll
endif
endif
# adbd device daemon
# =========================================================
@ -100,6 +101,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
adb.c \
fdevent.c \
transport.c \
transport_local.c \
transport_usb.c \

View File

@ -23,12 +23,15 @@
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "sysdeps.h"
#include "adb.h"
#if !ADB_HOST
#include <private/android_filesystem_config.h>
#else
#include "usb_vendors.h"
#endif
@ -655,10 +658,25 @@ void start_logging(void)
void start_device_log(void)
{
int fd;
char path[100];
char path[PATH_MAX];
struct tm now;
time_t t;
char value[PROPERTY_VALUE_MAX];
snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL));
fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 0640);
// read the trace mask from persistent property persist.adb.trace_mask
// give up if the property is not set or cannot be parsed
property_get("persist.adb.trace_mask", value, "");
if (sscanf(value, "%x", &adb_trace_mask) != 1)
return;
adb_mkdir("/data/adb", 0775);
tzset();
time(&t);
localtime_r(&t, &now);
strftime(path, sizeof(path),
"/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
&now);
fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
if (fd < 0)
return;
@ -669,11 +687,6 @@ void start_device_log(void)
fd = unix_open("/dev/null", O_RDONLY);
dup2(fd, 0);
// log everything
adb_trace_mask = ~0;
// except TRACE_RWX is a bit too verbose
adb_trace_mask &= ~TRACE_RWX;
}
#endif
@ -818,19 +831,6 @@ int adb_main(int is_daemon)
#if !ADB_HOST
int secure = 0;
char value[PROPERTY_VALUE_MAX];
// prevent the OOM killer from killing us
char text[64];
snprintf(text, sizeof text, "/proc/%d/oom_adj", (int)getpid());
int fd = adb_open(text, O_WRONLY);
if (fd >= 0) {
// -17 should make us immune to OOM
snprintf(text, sizeof text, "%d", -17);
adb_write(fd, text, strlen(text));
adb_close(fd);
} else {
D("adb: unable to open %s\n", text);
}
#endif
atexit(adb_cleanup);
@ -846,6 +846,7 @@ int adb_main(int is_daemon)
#if ADB_HOST
HOST = 1;
usb_vendors_init();
usb_init();
local_init();
@ -885,9 +886,10 @@ int adb_main(int is_daemon)
** AID_INET to diagnose network issues (netcfg, ping)
** AID_GRAPHICS to access the frame buffer
** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
** AID_SDCARD_RW to allow writing to the SD card
*/
gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
AID_NET_BT, AID_NET_BT_ADMIN };
AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW };
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
/* then switch user and group to "shell" */
@ -1088,9 +1090,8 @@ int main(int argc, char **argv)
adb_device_banner = "recovery";
recovery_mode = 1;
}
#if ADB_DEVICE_LOG
start_device_log();
#endif
return adb_main(0);
#endif
}

View File

@ -345,11 +345,6 @@ typedef enum {
#endif
/* set this to log to /data/adb/adb_<time>.txt on the device.
* has no effect if the /data/adb/ directory does not exist.
*/
#define ADB_DEVICE_LOG 0
#if !TRACE_PACKETS
#define print_packet(tag,p) do {} while (0)
#endif
@ -357,18 +352,10 @@ typedef enum {
#define ADB_PORT 5037
#define ADB_LOCAL_TRANSPORT_PORT 5555
// Google's USB Vendor ID
#define VENDOR_ID_GOOGLE 0x18d1
// HTC's USB Vendor ID
#define VENDOR_ID_HTC 0x0bb4
#define ADB_CLASS 0xff
#define ADB_SUBCLASS 0x42
#define ADB_PROTOCOL 0x1
// products for VENDOR_ID_GOOGLE
#define PRODUCT_ID_SOONER 0xd00d // Sooner bootloader
#define PRODUCT_ID_SOONER_COMP 0xdeed // Sooner composite device
// products for VENDOR_ID_HTC
#define PRODUCT_ID_DREAM 0x0c01 // Dream bootloader
#define PRODUCT_ID_DREAM_COMP 0x0c02 // Dream composite device
void local_init();
int local_connect(int port);
@ -382,7 +369,9 @@ int usb_close(usb_handle *h);
void usb_kick(usb_handle *h);
/* used for USB device detection */
#if ADB_HOST
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
#endif
unsigned host_to_le32(unsigned n);
int adb_commandline(int argc, char **argv);

View File

@ -213,7 +213,7 @@ int adb_connect(const char *service)
fprintf(stdout,"* daemon started successfully *\n");
}
/* give the server some time to start properly and detect devices */
adb_sleep_ms(2000);
adb_sleep_ms(3000);
// fall through to _adb_connect
} else {
// if server was running, check its version to make sure it is not out of date

View File

@ -26,7 +26,7 @@
#include <stdarg.h>
#include <stddef.h>
#include <cutils/fdevent.h>
#include "fdevent.h"
#define TRACE(x...) fprintf(stderr,x)
@ -87,7 +87,7 @@ static void fdevent_init()
{
/* XXX: what's a good size for the passed in hint? */
epoll_fd = epoll_create(256);
if(epoll_fd < 0) {
perror("epoll_create() failed");
exit(1);
@ -105,7 +105,7 @@ static void fdevent_connect(fdevent *fde)
ev.events = 0;
ev.data.ptr = fde;
#if 0
#if 0
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
perror("epoll_ctl() failed\n");
exit(1);
@ -116,7 +116,7 @@ static void fdevent_connect(fdevent *fde)
static void fdevent_disconnect(fdevent *fde)
{
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = 0;
ev.data.ptr = fde;
@ -133,9 +133,9 @@ static void fdevent_update(fdevent *fde, unsigned events)
{
struct epoll_event ev;
int active;
active = (fde->state & FDE_EVENTMASK) != 0;
memset(&ev, 0, sizeof(ev));
ev.events = 0;
ev.data.ptr = fde;
@ -241,7 +241,7 @@ static void fdevent_connect(fdevent *fde)
static void fdevent_disconnect(fdevent *fde)
{
int i, n;
FD_CLR(fde->fd, &read_fds);
FD_CLR(fde->fd, &write_fds);
FD_CLR(fde->fd, &error_fds);
@ -283,9 +283,9 @@ static void fdevent_process()
memcpy(&rfd, &read_fds, sizeof(fd_set));
memcpy(&wfd, &write_fds, sizeof(fd_set));
memcpy(&efd, &error_fds, sizeof(fd_set));
n = select(select_n, &rfd, &wfd, &efd, 0);
if(n < 0) {
if(errno == EINTR) return;
perror("select");
@ -300,12 +300,12 @@ static void fdevent_process()
if(events) {
n--;
fde = fd_table[i];
if(fde == 0) FATAL("missing fde for fd %d\n", i);
fde->events |= events;
if(fde->state & FDE_PENDING) continue;
fde->state |= FDE_PENDING;
fdevent_plist_enqueue(fde);
@ -320,7 +320,7 @@ static void fdevent_register(fdevent *fde)
if(fde->fd < 0) {
FATAL("bogus negative fd (%d)\n", fde->fd);
}
if(fde->fd >= fd_table_max) {
int oldmax = fd_table_max;
if(fde->fd > 32000) {
@ -383,9 +383,9 @@ static fdevent *fdevent_plist_dequeue(void)
{
fdevent *list = &list_pending;
fdevent *node = list->next;
if(node == list) return 0;
list->next = node->next;
list->next->prev = list;
node->next = 0;
@ -449,9 +449,9 @@ void fdevent_remove(fdevent *fde)
void fdevent_set(fdevent *fde, unsigned events)
{
events &= FDE_EVENTMASK;
if((fde->state & FDE_EVENTMASK) == events) return;
if(fde->state & FDE_ACTIVE) {
fdevent_update(fde, events);
dump_fde(fde, "update");
@ -487,13 +487,13 @@ void fdevent_del(fdevent *fde, unsigned events)
void fdevent_loop()
{
fdevent *fde;
for(;;) {
#if DEBUG
fprintf(stderr,"--- ---- waiting for events\n");
#endif
fdevent_process();
while((fde = fdevent_plist_dequeue())) {
unsigned events = fde->events;
fde->events = 0;

View File

@ -17,10 +17,13 @@
#ifndef __FDEVENT_H
#define __FDEVENT_H
#include <stdint.h> /* for int64_t */
/* events that may be observed */
#define FDE_READ 0x0001
#define FDE_WRITE 0x0002
#define FDE_ERROR 0x0004
#define FDE_TIMEOUT 0x0008
/* features that may be set (via the events set/add/del interface) */
#define FDE_DONT_CLOSE 0x0080
@ -30,6 +33,8 @@ typedef struct fdevent fdevent;
typedef void (*fd_func)(int fd, unsigned events, void *userdata);
/* Allocate and initialize a new fdevent object
* Note: use FD_TIMER as 'fd' to create a fd-less object
* (used to implement timers).
*/
fdevent *fdevent_create(int fd, fd_func func, void *arg);
@ -53,6 +58,8 @@ void fdevent_set(fdevent *fde, unsigned events);
void fdevent_add(fdevent *fde, unsigned events);
void fdevent_del(fdevent *fde, unsigned events);
void fdevent_set_timeout(fdevent *fde, int64_t timeout_ms);
/* loop forever, handling events.
*/
void fdevent_loop();
@ -65,7 +72,7 @@ struct fdevent
int fd;
unsigned short state;
unsigned short events;
fd_func func;
void *arg;
};

View File

@ -165,7 +165,7 @@ static int sync_start_readtime(int fd, const char *path)
}
static int sync_finish_readtime(int fd, unsigned int *timestamp,
unsigned int *mode, unsigned int *size)
unsigned int *mode, unsigned int *size)
{
syncmsg msg;
@ -908,12 +908,12 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
unsigned int timestamp, mode, size;
if (sync_finish_readtime(fd, &timestamp, &mode, &size))
return 1;
if (size == ci->size) {
if (size == ci->size) {
/* for links, we cannot update the atime/mtime */
if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
(S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
(S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
ci->flag = 1;
}
}
}
}
#endif

View File

@ -20,7 +20,7 @@
#include <string.h>
#include <fcntl.h>
#include <cutils/fdevent.h>
#include "fdevent.h"
#include "adb.h"
#include <linux/fb.h>

View File

@ -23,7 +23,7 @@ implementation to be much more robust.
--- protocol overview and basics ---------------------------------------
The transport layer deals in "messages", which consist of a 24 byte
header followed (optionally) by a payload. The header consists of 6
32 bit words which are sent across the wire in little endian format.
@ -52,7 +52,7 @@ The identifiers "local-id" and "remote-id" are always relative to the
reversed.
--- CONNECT(version, maxdata, "system-identity-string") ----------------
The CONNECT message establishes the presence of a remote system.
@ -114,7 +114,7 @@ is used to establish the connection). Nonetheless, the local-id MUST
not change on later READY messages sent to the same stream.
--- WRITE(0, remote-id, "data") ----------------------------------------
The WRITE message sends data to the recipient's stream identified by
@ -172,7 +172,7 @@ to send across the wire.
#define A_WRTE 0x45545257
--- implementation details ---------------------------------------------
The core of the bridge program will use three threads. One thread

View File

@ -244,6 +244,18 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
cmd, strerror(errno), errno);
exit(-1);
} else {
#if !ADB_HOST
// set child's OOM adjustment to zero
char text[64];
snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
int fd = adb_open(text, O_WRONLY);
if (fd >= 0) {
adb_write(fd, "0", 1);
adb_close(fd);
} else {
D("adb: unable to open %s\n", text);
}
#endif
return ptm;
}
#endif /* !HAVE_WIN32_PROC */

View File

@ -67,16 +67,16 @@ typedef void (*win_thread_func_t)(void* arg);
static __inline__ int adb_thread_create( adb_thread_t *thread, adb_thread_func_t func, void* arg)
{
thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
if (thread->tid == (unsigned)-1L) {
return -1;
}
return 0;
thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
if (thread->tid == (unsigned)-1L) {
return -1;
}
return 0;
}
static __inline__ void close_on_exec(int fd)
{
/* nothing really */
/* nothing really */
}
extern void disable_tcp_nagle(int fd);
@ -138,7 +138,7 @@ static __inline__ int unix_write(int fd, const void* buf, size_t len)
static __inline__ int adb_open_mode(const char* path, int options, int mode)
{
return adb_open(path, options);
return adb_open(path, options);
}
static __inline__ int unix_open(const char* path, int options,...)
@ -169,7 +169,7 @@ extern int socket_network_client(const char *host, int port, int type);
extern int socket_loopback_server(int port, int type);
extern int socket_inaddr_any_server(int port, int type);
/* normally provided by <cutils/fdevent.h> */
/* normally provided by "fdevent.h" */
#define FDE_READ 0x0001
#define FDE_WRITE 0x0002
@ -203,7 +203,7 @@ struct fdevent {
static __inline__ void adb_sleep_ms( int mseconds )
{
Sleep( mseconds );
Sleep( mseconds );
}
extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen);
@ -252,7 +252,7 @@ static __inline__ int adb_is_absolute_host_path( const char* path )
#else /* !_WIN32 a.k.a. Unix */
#include <cutils/fdevent.h>
#include "fdevent.h"
#include <cutils/sockets.h>
#include <cutils/properties.h>
#include <cutils/misc.h>
@ -290,7 +290,7 @@ typedef pthread_mutex_t adb_mutex_t;
static __inline__ void close_on_exec(int fd)
{
fcntl( fd, F_SETFD, FD_CLOEXEC );
fcntl( fd, F_SETFD, FD_CLOEXEC );
}
static __inline__ int unix_open(const char* path, int options,...)
@ -312,7 +312,7 @@ static __inline__ int unix_open(const char* path, int options,...)
static __inline__ int adb_open_mode( const char* pathname, int options, int mode )
{
return open( pathname, options, mode );
return open( pathname, options, mode );
}
@ -368,11 +368,11 @@ static __inline__ int adb_creat(const char* path, int mode)
{
int fd = creat(path, mode);
if ( fd < 0 )
return -1;
if ( fd < 0 )
return -1;
close_on_exec(fd);
return fd;
return fd;
}
#undef creat
#define creat ___xxx_creat
@ -439,12 +439,12 @@ static __inline__ int adb_socketpair( int sv[2] )
static __inline__ void adb_sleep_ms( int mseconds )
{
usleep( mseconds*1000 );
usleep( mseconds*1000 );
}
static __inline__ int adb_mkdir(const char* path, int mode)
{
return mkdir(path, mode);
return mkdir(path, mode);
}
#undef mkdir
#define mkdir ___xxx_mkdir

View File

@ -739,12 +739,12 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrle
{
FH serverfh = _fh_from_int(serverfd);
FH fh;
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
D( "adb_socket_accept: invalid fd %d\n", serverfd );
return -1;
}
fh = _fh_alloc( &_fh_socket_class );
if (!fh) {
D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
@ -757,7 +757,7 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrle
D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
return -1;
}
snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
return _fh_to_int(fh);
@ -768,7 +768,7 @@ void disable_tcp_nagle(int fd)
{
FH fh = _fh_from_int(fd);
int on;
if ( !fh || fh->clazz != &_fh_socket_class )
return;
@ -1746,7 +1746,7 @@ void fdevent_loop()
/** FILE EVENT HOOKS
**/
static void _event_file_prepare( EventHook hook )
{
if (hook->wanted & (FDE_READ|FDE_WRITE)) {

View File

@ -23,6 +23,10 @@
#define TRACE_TAG TRACE_TRANSPORT
#include "adb.h"
#if ADB_HOST
#include "usb_vendors.h"
#endif
/* XXX better define? */
#ifdef __ppc__
#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)
@ -125,23 +129,21 @@ void init_usb_transport(atransport *t, usb_handle *h)
#endif
}
#if ADB_HOST
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol)
{
if (vid == VENDOR_ID_GOOGLE) {
/* might support adb */
} else if (vid == VENDOR_ID_HTC) {
/* might support adb */
} else {
/* not supported */
return 0;
}
unsigned i;
for (i = 0; i < vendorIdCount; i++) {
if (vid == vendorIds[i]) {
if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS &&
usb_protocol == ADB_PROTOCOL) {
return 1;
}
/* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */
if(usb_class == 0xff) {
if((usb_subclass == 0x42) && (usb_protocol == 0x01)) {
return 1;
return 0;
}
}
return 0;
}
#endif

View File

@ -28,24 +28,12 @@
#define TRACE_TAG TRACE_USB
#include "adb.h"
#include "usb_vendors.h"
#define DBG D
typedef struct {
int vid;
int pid;
} VendorProduct;
#define kSupportedDeviceCount 4
VendorProduct kSupportedDevices[kSupportedDeviceCount] = {
{ VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER },
{ VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP },
{ VENDOR_ID_HTC, PRODUCT_ID_DREAM },
{ VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP },
};
static IONotificationPortRef notificationPort = 0;
static io_iterator_t notificationIterators[kSupportedDeviceCount];
static io_iterator_t* notificationIterators;
struct usb_handle
{
@ -61,17 +49,20 @@ static pthread_mutex_t start_lock;
static pthread_cond_t start_cond;
static void AndroidDeviceAdded(void *refCon, io_iterator_t iterator);
static void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument);
static usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product);
static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
natural_t messageType,
void *messageArgument);
static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
UInt16 vendor, UInt16 product);
static int
InitUSB()
{
CFMutableDictionaryRef matchingDict;
CFRunLoopSourceRef runLoopSource;
SInt32 vendor, product;
int i;
SInt32 vendor, if_subclass, if_protocol;
unsigned i;
//* To set up asynchronous notifications, create a notification port and
//* add its run loop event source to the program's run loop
@ -81,51 +72,57 @@ InitUSB()
memset(notificationIterators, 0, sizeof(notificationIterators));
//* loop through all supported vendor/product pairs
for (i = 0; i < kSupportedDeviceCount; i++) {
//* Create our matching dictionary to find the Android device
//* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
//* loop through all supported vendors
for (i = 0; i < vendorIdCount; i++) {
//* Create our matching dictionary to find the Android device's
//* adb interface
//* IOServiceAddMatchingNotification consumes the reference, so we do
//* not need to release this
matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
if (!matchingDict) {
DBG("ERR: Couldn't create USB matching dictionary.\n");
return -1;
}
//* Set up two matching dictionaries, one for each product ID we support.
//* This will cause the kernel to notify us only if the vendor and product IDs match.
vendor = kSupportedDevices[i].vid;
product = kSupportedDevices[i].pid;
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
//* Now set up two notifications: one to be called when a raw device
//* is first matched by the I/O Kit and another to be called when the
//* device is terminated.
//* we need to do this with each matching dictionary.
//* Match based on vendor id, interface subclass and protocol
vendor = vendorIds[i];
if_subclass = ADB_SUBCLASS;
if_protocol = ADB_PROTOCOL;
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID),
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &vendor));
CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass),
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &if_subclass));
CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol),
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &if_protocol));
IOServiceAddMatchingNotification(
notificationPort,
kIOFirstMatchNotification,
matchingDict,
AndroidDeviceAdded,
AndroidInterfaceAdded,
NULL,
&notificationIterators[i]);
//* Iterate over set of matching devices to access already-present devices
//* and to arm the notification
AndroidDeviceAdded(NULL, notificationIterators[i]);
//* Iterate over set of matching interfaces to access already-present
//* devices and to arm the notification
AndroidInterfaceAdded(NULL, notificationIterators[i]);
}
return 0;
}
static void
AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
io_service_t usbInterface;
IOCFPlugInInterface **plugInInterface = NULL;
IOUSBDeviceInterface182 **dev = NULL;
IOUSBInterfaceInterface220 **iface = NULL;
IOUSBDeviceInterface197 **dev = NULL;
HRESULT result;
SInt32 score;
UInt16 vendor;
@ -133,28 +130,66 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
UInt8 serialIndex;
char serial[256];
while ((usbDevice = IOIteratorNext(iterator))) {
//* Create an intermediate plugin
while ((usbInterface = IOIteratorNext(iterator))) {
//* Create an intermediate interface plugin
kr = IOCreatePlugInInterfaceForService(usbInterface,
kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterface, &score);
IOObjectRelease(usbInterface);
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
continue;
}
//* This gets us the interface object
result = (*plugInInterface)->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)
&iface);
//* We only needed the plugin to get the interface, so discard it
(*plugInInterface)->Release(plugInInterface);
if (result || !iface) {
DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
continue;
}
//* this gets us an ioservice, with which we will find the actual
//* device; after getting a plugin, and querying the interface, of
//* course.
//* Gotta love OS X
kr = (*iface)->GetDevice(iface, &usbDevice);
if (kIOReturnSuccess != kr || !usbDevice) {
DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
continue;
}
plugInInterface = NULL;
score = 0;
//* create an intermediate device plugin
kr = IOCreatePlugInInterfaceForService(usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterface, &score);
//* only needed this to find the plugin
(void)IOObjectRelease(usbDevice);
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
DBG("ERR: Unable to create a plug-in (%08x)\n", kr);
goto continue1;
DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
continue;
}
//* Now create the device interface
result = (*plugInInterface)->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
//* only needed this to query the plugin
(*plugInInterface)->Release(plugInInterface);
if (result || !dev) {
DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result);
goto continue2;
DBG("ERR: Couldn't create a device interface (%08x)\n",
(int) result);
continue;
}
//* Check the device to see if it's ours
//* Now after all that, we actually have a ref to the device and
//* the interface that matched our criteria
kr = (*dev)->GetDeviceVendor(dev, &vendor);
kr = (*dev)->GetDeviceProduct(dev, &product);
kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
@ -163,7 +198,8 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
IOUSBDevRequest req;
UInt16 buffer[256];
req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
req.bmRequestType =
USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
req.bRequest = kUSBRqGetDescriptor;
req.wValue = (kUSBStringDesc << 8) | serialIndex;
req.wIndex = 0;
@ -174,219 +210,149 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
if (kr == kIOReturnSuccess && req.wLenDone > 0) {
int i, count;
// skip first word, and copy the rest to the serial string, changing shorts to bytes.
// skip first word, and copy the rest to the serial string,
// changing shorts to bytes.
count = (req.wLenDone - 1) / 2;
for (i = 0; i < count; i++)
serial[i] = buffer[i + 1];
serial[i] = 0;
}
}
(*dev)->Release(dev);
usb_handle* handle = NULL;
//* Open the device
kr = (*dev)->USBDeviceOpen(dev);
if (kr != kIOReturnSuccess) {
DBG("ERR: Could not open device: %08x\n", kr);
goto continue3;
} else {
//* Find an interface for the device
handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product);
}
DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
serial);
usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
vendor, product);
if (handle == NULL) {
DBG("ERR: Could not find device interface: %08x\n", kr);
(*dev)->USBDeviceClose(dev);
goto continue3;
(*iface)->Release(iface);
continue;
}
DBG("AndroidDeviceAdded calling register_usb_transport\n");
register_usb_transport(handle, (serial[0] ? serial : NULL));
// Register for an interest notification of this device being removed. Pass the reference to our
// private data as the refCon for the notification.
// Register for an interest notification of this device being removed.
// Pass the reference to our private data as the refCon for the
// notification.
kr = IOServiceAddInterestNotification(notificationPort,
usbDevice,
usbInterface,
kIOGeneralInterest,
AndroidDeviceNotify,
AndroidInterfaceNotify,
handle,
&handle->usbNotification);
if (kIOReturnSuccess != kr) {
DBG("ERR: Unable to create interest notification (%08x)\n", kr);
}
continue3:
(void)(*dev)->Release(dev);
continue2:
IODestroyPlugInInterface(plugInInterface);
continue1:
IOObjectRelease(usbDevice);
}
}
static void
AndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
{
usb_handle *handle = (usb_handle *)refCon;
if (messageType == kIOMessageServiceIsTerminated) {
DBG("AndroidDeviceNotify\n");
if (!handle) {
DBG("ERR: NULL handle\n");
return;
}
DBG("AndroidInterfaceNotify\n");
IOObjectRelease(handle->usbNotification);
usb_kick(handle);
}
}
//* TODO: simplify this further since we only register to get ADB interface
//* subclass+protocol events
static usb_handle*
FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product)
CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
{
usb_handle* handle = NULL;
IOReturn kr;
IOUSBFindInterfaceRequest request;
io_iterator_t iterator;
io_service_t usbInterface;
IOCFPlugInInterface **plugInInterface;
IOUSBInterfaceInterface **interface = NULL;
HRESULT result;
SInt32 score;
UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
UInt8 endpoint, configuration;
UInt8 endpoint;
//* Placing the constant KIOUSBFindInterfaceDontCare into the following
//* fields of the IOUSBFindInterfaceRequest structure will allow us to
//* find all of the interfaces
request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
//* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary.
configuration = 0;
(*dev)->GetConfiguration(dev, &configuration);
if (configuration != 1)
(*dev)->SetConfiguration(dev, 1);
//* Get an iterator for the interfaces on the device
kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator);
//* Now open the interface. This will cause the pipes associated with
//* the endpoints in the interface descriptor to be instantiated
kr = (*interface)->USBInterfaceOpen(interface);
if (kr != kIOReturnSuccess) {
DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr);
DBG("ERR: Could not open interface: (%08x)\n", kr);
return NULL;
}
while ((usbInterface = IOIteratorNext(iterator))) {
//* Create an intermediate plugin
kr = IOCreatePlugInInterfaceForService(
usbInterface,
kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterface,
&score);
//* No longer need the usbInterface object now that we have the plugin
(void) IOObjectRelease(usbInterface);
if ((kr != kIOReturnSuccess) || (!plugInInterface)) {
DBG("ERR: Unable to create plugin (%08x)\n", kr);
break;
}
//* Now create the interface interface for the interface
result = (*plugInInterface)->QueryInterface(
plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
(LPVOID) &interface);
//* No longer need the intermediate plugin
(*plugInInterface)->Release(plugInInterface);
if (result || !interface) {
DBG("ERR: Couldn't create interface interface: (%08x)\n",
(unsigned int) result);
break;
}
//* Now open the interface. This will cause the pipes associated with
//* the endpoints in the interface descriptor to be instantiated
kr = (*interface)->USBInterfaceOpen(interface);
if (kr != kIOReturnSuccess)
{
DBG("ERR: Could not open interface: (%08x)\n", kr);
(void) (*interface)->Release(interface);
//* continue so we can try the next interface
continue;
}
//* Get the number of endpoints associated with this interface
kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
if (kr != kIOReturnSuccess) {
DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
goto next_interface;
}
//* Get interface class, subclass and protocol
if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
(*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
(*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess)
{
DBG("ERR: Unable to get interface class, subclass and protocol\n");
goto next_interface;
}
//* check to make sure interface class, subclass and protocol match ADB
//* avoid opening mass storage endpoints
if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
handle = calloc(1, sizeof(usb_handle));
//* Iterate over the endpoints for this interface and find the first
//* bulk in/out pipes available. These will be our read/write pipes.
for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
UInt8 transferType;
UInt16 maxPacketSize;
UInt8 interval;
UInt8 number;
UInt8 direction;
kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
&number, &transferType, &maxPacketSize, &interval);
if (kIOReturnSuccess == kr) {
if (kUSBBulk != transferType)
continue;
if (kUSBIn == direction)
handle->bulkIn = endpoint;
if (kUSBOut == direction)
handle->bulkOut = endpoint;
if (interfaceProtocol == 0x01) {
handle->zero_mask = maxPacketSize - 1;
}
} else {
DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
}
}
handle->interface = interface;
break;
}
next_interface:
(*interface)->USBInterfaceClose(interface);
(*interface)->Release(interface);
//* Get the number of endpoints associated with this interface
kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
if (kr != kIOReturnSuccess) {
DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
goto err_get_num_ep;
}
//* Get interface class, subclass and protocol
if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
(*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
(*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
DBG("ERR: Unable to get interface class, subclass and protocol\n");
goto err_get_interface_class;
}
//* check to make sure interface class, subclass and protocol match ADB
//* avoid opening mass storage endpoints
if (!is_adb_interface(vendor, product, interfaceClass,
interfaceSubClass, interfaceProtocol))
goto err_bad_adb_interface;
handle = calloc(1, sizeof(usb_handle));
//* Iterate over the endpoints for this interface and find the first
//* bulk in/out pipes available. These will be our read/write pipes.
for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
UInt8 transferType;
UInt16 maxPacketSize;
UInt8 interval;
UInt8 number;
UInt8 direction;
kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
&number, &transferType, &maxPacketSize, &interval);
if (kIOReturnSuccess == kr) {
if (kUSBBulk != transferType)
continue;
if (kUSBIn == direction)
handle->bulkIn = endpoint;
if (kUSBOut == direction)
handle->bulkOut = endpoint;
handle->zero_mask = maxPacketSize - 1;
} else {
DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
goto err_get_pipe_props;
}
}
handle->interface = interface;
return handle;
err_get_pipe_props:
free(handle);
err_bad_adb_interface:
err_get_interface_class:
err_get_num_ep:
(*interface)->USBInterfaceClose(interface);
return NULL;
}
void* RunLoopThread(void* unused)
{
int i;
unsigned i;
InitUSB();
@ -400,7 +366,7 @@ void* RunLoopThread(void* unused)
CFRunLoopRun();
currentRunLoop = 0;
for (i = 0; i < kSupportedDeviceCount; i++) {
for (i = 0; i < vendorIdCount; i++) {
IOObjectRelease(notificationIterators[i]);
}
IONotificationPortDestroy(notificationPort);
@ -417,6 +383,9 @@ void usb_init()
{
adb_thread_t tid;
notificationIterators = (io_iterator_t*)malloc(
vendorIdCount * sizeof(io_iterator_t));
adb_mutex_init(&start_lock, NULL);
adb_cond_init(&start_cond, NULL);
@ -441,6 +410,11 @@ void usb_cleanup()
close_usb_devices();
if (currentRunLoop)
CFRunLoopStop(currentRunLoop);
if (notificationIterators != NULL) {
free(notificationIterators);
notificationIterators = NULL;
}
}
int usb_write(usb_handle *handle, const void *buf, int len)
@ -527,6 +501,9 @@ int usb_close(usb_handle *handle)
void usb_kick(usb_handle *handle)
{
/* release the interface */
if (!handle)
return;
if (handle->interface)
{
(*handle->interface)->USBInterfaceClose(handle->interface);

134
adb/usb_vendors.c Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (C) 2009 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.
*/
#include "usb_vendors.h"
#include <stdio.h>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include "windows.h"
# include "shlobj.h"
#else
# include <unistd.h>
# include <sys/stat.h>
#endif
#include "sysdeps.h"
#include "adb.h"
#define ANDROID_PATH ".android"
#define ANDROID_ADB_INI "adb_usb.ini"
#define TRACE_TAG TRACE_USB
// Google's USB Vendor ID
#define VENDOR_ID_GOOGLE 0x18d1
// HTC's USB Vendor ID
#define VENDOR_ID_HTC 0x0bb4
/** built-in vendor list */
int builtInVendorIds[] = {
VENDOR_ID_GOOGLE,
VENDOR_ID_HTC,
};
#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
/* max number of supported vendor ids (built-in + 3rd party). increase as needed */
#define VENDOR_COUNT_MAX 128
int vendorIds[VENDOR_COUNT_MAX];
unsigned vendorIdCount = 0;
int get_adb_usb_ini(char* buff, size_t len);
void usb_vendors_init(void)
{
if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) {
fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n");
exit(2);
}
/* add the built-in vendors at the beginning of the array */
memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds));
/* default array size is the number of built-in vendors */
vendorIdCount = BUILT_IN_VENDOR_COUNT;
if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT)
return;
char temp[PATH_MAX];
if (get_adb_usb_ini(temp, sizeof(temp)) == 0) {
FILE * f = fopen(temp, "rt");
if (f != NULL) {
/* The vendor id file is pretty basic. 1 vendor id per line.
Lines starting with # are comments */
while (fgets(temp, sizeof(temp), f) != NULL) {
if (temp[0] == '#')
continue;
long value = strtol(temp, NULL, 0);
if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) {
fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI);
exit(2);
}
vendorIds[vendorIdCount++] = (int)value;
/* make sure we don't go beyond the array */
if (vendorIdCount == VENDOR_COUNT_MAX) {
break;
}
}
}
}
}
/* Utils methods */
/* builds the path to the adb vendor id file. returns 0 if success */
int build_path(char* buff, size_t len, const char* format, const char* home)
{
if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) {
return 1;
}
return 0;
}
/* fills buff with the path to the adb vendor id file. returns 0 if success */
int get_adb_usb_ini(char* buff, size_t len)
{
#ifdef _WIN32
const char* home = getenv("ANDROID_SDK_HOME");
if (home != NULL) {
return build_path(buff, len, "%s\\%s\\%s", home);
} else {
char path[MAX_PATH];
SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path);
return build_path(buff, len, "%s\\%s\\%s", path);
}
#else
const char* home = getenv("HOME");
if (home == NULL)
home = "/tmp";
return build_path(buff, len, "%s/%s/%s", home);
#endif
}

25
adb/usb_vendors.h Normal file
View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2009 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.
*/
#ifndef __USB_VENDORS_H
#define __USB_VENDORS_H
extern int vendorIds[];
extern unsigned vendorIdCount;
void usb_vendors_init(void);
#endif

View File

@ -446,7 +446,7 @@ int recognized_device(usb_handle* handle) {
}
void find_devices() {
usb_handle* handle = NULL;
usb_handle* handle = NULL;
char entry_buffer[2048];
char interf_name[2048];
AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);

View File

@ -40,7 +40,7 @@ void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size,
unsigned page_size, unsigned base,
unsigned *bootimg_size)
{
unsigned kernel_actual;
@ -65,15 +65,14 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
hdr->kernel_size = kernel_size;
hdr->kernel_addr = 0x10008000;
hdr->kernel_size = kernel_size;
hdr->ramdisk_size = ramdisk_size;
hdr->ramdisk_addr = 0x11000000;
hdr->second_size = second_size;
hdr->second_addr = 0x10F00000;
hdr->tags_addr = 0x10000100;
hdr->page_size = page_size;
hdr->second_size = second_size;
hdr->kernel_addr = base + 0x00008000;
hdr->ramdisk_addr = base + 0x01000000;
hdr->second_addr = base + 0x00F00000;
hdr->tags_addr = base + 0x00000100;
hdr->page_size = page_size;
memcpy(hdr->magic + page_size,
kernel, kernel_size);

View File

@ -42,6 +42,14 @@
#include "fastboot.h"
void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size, unsigned base,
unsigned *bootimg_size);
static usb_handle *usb = 0;
static const char *serial = 0;
static const char *product = 0;
@ -49,6 +57,8 @@ static const char *cmdline = 0;
static int wipe_data = 0;
static unsigned short vendor_id = 0;
static unsigned base_addr = 0x10000000;
void die(const char *fmt, ...)
{
va_list ap;
@ -212,6 +222,7 @@ void usage(void)
" -p <product> specify product name\n"
" -c <cmdline> override kernel commandline\n"
" -i <vendor id> specify a custom USB vendor id\n"
" -b <base_addr> specify a custom kernel base address\n"
);
exit(1);
}
@ -257,7 +268,7 @@ void *load_bootable_image(const char *kernel, const char *ramdisk,
}
fprintf(stderr,"creating boot image...\n");
bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, 2048, &bsize);
bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, 2048, base_addr, &bsize);
if(bdata == 0) {
fprintf(stderr,"failed to create boot.img\n");
return 0;
@ -545,6 +556,10 @@ int main(int argc, char **argv)
if(!strcmp(*argv, "-w")) {
wants_wipe = 1;
skip(1);
} else if(!strcmp(*argv, "-b")) {
require(2);
base_addr = strtoul(argv[1], 0, 16);
skip(2);
} else if(!strcmp(*argv, "-s")) {
require(2);
serial = argv[1];

128
include/android/log.h Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2009 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.
*/
#ifndef _ANDROID_LOG_H
#define _ANDROID_LOG_H
/******************************************************************
*
* IMPORTANT NOTICE:
*
* This file is part of Android's set of stable system headers
* exposed by the Android NDK (Native Development Kit) since
* platform release 1.5
*
* Third-party source AND binary code relies on the definitions
* here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
*
* - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
* - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
* - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
*/
/*
* Support routines to send messages to the Android in-kernel log buffer,
* which can later be accessed through the 'logcat' utility.
*
* Each log message must have
* - a priority
* - a log tag
* - some text
*
* The tag normally corresponds to the component that emits the log message,
* and should be reasonably small.
*
* Log message text may be truncated to less than an implementation-specific
* limit (e.g. 1023 characters max).
*
* Note that a newline character ("\n") will be appended automatically to your
* log message, if not already there. It is not possible to send several messages
* and have them appear on a single line in logcat.
*
* PLEASE USE LOGS WITH MODERATION:
*
* - Sending log messages eats CPU and slow down your application and the
* system.
*
* - The circular log buffer is pretty small (<64KB), sending many messages
* might push off other important log messages from the rest of the system.
*
* - In release builds, only send log messages to account for exceptional
* conditions.
*
* NOTE: These functions MUST be implemented by /system/lib/liblog.so
*/
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Android log priority values, in ascending priority order.
*/
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
} android_LogPriority;
/*
* Send a simple string to the log.
*/
int __android_log_write(int prio, const char *tag, const char *text);
/*
* Send a formatted string to the log, used like printf(fmt,...)
*/
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
#if defined(__GNUC__)
__attribute__ ((format(printf, 3, 4)))
#endif
;
/*
* A variant of __android_log_print() that takes a va_list to list
* additional parameters.
*/
int __android_log_vprint(int prio, const char *tag,
const char *fmt, va_list ap);
/*
* Log an assertion failure and SIGTRAP the process to have a chance
* to inspect it, if a debugger is attached. This uses the FATAL priority.
*/
void __android_log_assert(const char *cond, const char *tag,
const char *fmt, ...)
#if defined(__GNUC__)
__attribute__ ((noreturn))
__attribute__ ((format(printf, 3, 4)))
#endif
;
#ifdef __cplusplus
}
#endif
#endif /* _ANDROID_LOG_H */

View File

@ -18,6 +18,7 @@ int ashmem_create_region(const char *name, size_t size);
int ashmem_set_prot_region(int fd, int prot);
int ashmem_pin_region(int fd, size_t offset, size_t len);
int ashmem_unpin_region(int fd, size_t offset, size_t len);
int ashmem_get_size_region(int fd);
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006 The Android Open Source Project
* Copyright (C) 2009 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.
@ -17,6 +17,12 @@
#ifndef _ANDROID_CUTILS_LOGD_H
#define _ANDROID_CUTILS_LOGD_H
/* the stable/frozen log-related definitions have been
* moved to this header, which is exposed by the NDK
*/
#include <android/log.h>
/* the rest is only used internally by the system */
#include <time.h>
#include <stdio.h>
#include <unistd.h>
@ -32,45 +38,10 @@
extern "C" {
#endif
/*
* Priority values, in ascending priority order.
*/
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
} android_LogPriority;
int __android_log_write(int prio, const char *tag, const char *text);
int __android_log_vprint(int prio, const char *tag,
const char *fmt, va_list ap);
int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
int __android_log_btwrite(int32_t tag, char type, const void *payload,
size_t len);
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
#if defined(__GNUC__)
__attribute__ ((format(printf, 3, 4)))
#endif
;
void __android_log_assert(const char *cond, const char *tag,
const char *fmt, ...)
#if defined(__GNUC__)
__attribute__ ((noreturn))
__attribute__ ((format(printf, 3, 4)))
#endif
;
#ifdef __cplusplus
}
#endif

View File

@ -17,12 +17,57 @@
#ifndef NATIVE_HANDLE_H_
#define NATIVE_HANDLE_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
int version; /* sizeof(native_handle) */
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
int data[0]; /* numFds + numInts ints */
} native_handle;
} native_handle_t;
/* keep the old definition for backward source-compatibility */
typedef native_handle_t native_handle;
/*
* native_handle_close
*
* closes the file descriptors contained in this native_handle_t
*
* return 0 on success, or a negative error code on failure
*
*/
int native_handle_close(const native_handle_t* h);
/*
* native_handle_create
*
* creates a native_handle_t and initializes it. must be destroyed with
* native_handle_delete().
*
*/
native_handle_t* native_handle_create(int numFds, int numInts);
/*
* native_handle_delete
*
* frees a native_handle_t allocated with native_handle_create().
* This ONLY frees the memory allocated for the native_handle_t, but doesn't
* close the file descriptors; which can be achieved with native_handle_close().
*
* return 0 on success, or a negative error code on failure
*
*/
int native_handle_delete(native_handle_t* h);
#ifdef __cplusplus
}
#endif
#endif /* NATIVE_HANDLE_H_ */

View File

@ -27,6 +27,7 @@ void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz);
struct strftime_locale {
const char *mon[12]; /* short names */
const char *month[12]; /* long names */
const char *standalone_month[12]; /* long standalone names */
const char *wday[7]; /* short names */
const char *weekday[7]; /* long names */
const char *X_fmt;

View File

@ -48,6 +48,9 @@
#define AID_INSTALL 1012 /* group for installing packages */
#define AID_MEDIA 1013 /* mediaserver process */
#define AID_DHCP 1014 /* dhcp client */
#define AID_SDCARD_RW 1015 /* external storage write access */
#define AID_VPN 1016 /* vpn system */
#define AID_KEYSTORE 1017 /* keystore subsystem */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
@ -59,6 +62,7 @@
#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
#define AID_NET_RAW 3004 /* can create raw INET sockets */
#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
#define AID_MISC 9998 /* access to misc storage */
#define AID_NOBODY 9999
@ -93,8 +97,12 @@ static struct android_id_info android_ids[] = {
{ "diag", AID_DIAG, },
{ "net_bt_admin", AID_NET_BT_ADMIN, },
{ "net_bt", AID_NET_BT, },
{ "inet", AID_INET, },
{ "sdcard_rw", AID_SDCARD_RW, },
{ "vpn", AID_VPN, },
{ "keystore", AID_KEYSTORE, },
{ "inet", AID_INET, },
{ "net_raw", AID_NET_RAW, },
{ "net_admin", AID_NET_ADMIN, },
{ "misc", AID_MISC, },
{ "nobody", AID_NOBODY, },
};
@ -129,7 +137,7 @@ static struct fs_path_config android_dirs[] = {
{ 00750, AID_ROOT, AID_SHELL, "sbin" },
{ 00755, AID_ROOT, AID_SHELL, "system/bin" },
{ 00755, AID_ROOT, AID_SHELL, "system/xbin" },
{ 00777, AID_ROOT, AID_ROOT, "system/etc/ppp" }, /* REMOVE */
{ 00755, AID_ROOT, AID_ROOT, "system/etc/ppp" },
{ 00777, AID_ROOT, AID_ROOT, "sdcard" },
{ 00755, AID_ROOT, AID_ROOT, 0 },
};
@ -141,20 +149,18 @@ static struct fs_path_config android_dirs[] = {
** and will allow partial matches.
*/
static struct fs_path_config android_files[] = {
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/ip-up" },
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/ip-down" },
{ 00440, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.rc" },
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.sh" },
{ 00440, AID_ROOT, AID_SHELL, "system/etc/init.trout.rc" },
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.ril" },
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" },
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.gprs-pppd" },
{ 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" },
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" },
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/hcid.conf" },
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" },
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" },
{ 00440, AID_RADIO, AID_AUDIO, "/system/etc/AudioPara4.csv" },
{ 00440, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" },
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" },
{ 00644, AID_APP, AID_APP, "data/data/*" },
@ -168,6 +174,7 @@ static struct fs_path_config android_files[] = {
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/librank" },
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/procrank" },
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/procmem" },
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/tcpdump" },
{ 00755, AID_ROOT, AID_SHELL, "system/bin/*" },
{ 00755, AID_ROOT, AID_SHELL, "system/xbin/*" },
{ 00750, AID_ROOT, AID_SHELL, "sbin/*" },

View File

@ -0,0 +1,21 @@
#ifndef _FRAMEWORK_CLIENT_H
#define _FRAMEWORK_CLIENT_H
#include "../../../frameworks/base/include/utils/List.h"
#include <pthread.h>
class FrameworkClient {
int mSocket;
pthread_mutex_t mWriteMutex;
public:
FrameworkClient(int sock);
virtual ~FrameworkClient() {}
int sendMsg(const char *msg);
int sendMsg(const char *msg, const char *data);
};
typedef android::List<FrameworkClient *> FrameworkClientCollection;
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef __FRAMEWORK_CMD_HANDLER_H
#define __FRAMEWORK_CMD_HANDLER_H
#include "../../../frameworks/base/include/utils/List.h"
class SocketClient;
class FrameworkCommand {
private:
const char *mCommand;
public:
FrameworkCommand(const char *cmd);
virtual ~FrameworkCommand() { }
virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
const char *getCommand() { return mCommand; }
};
typedef android::List<FrameworkCommand *> FrameworkCommandCollection;
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _FRAMEWORKSOCKETLISTENER_H
#define _FRAMEWORKSOCKETLISTENER_H
#include "SocketListener.h"
#include "FrameworkCommand.h"
class SocketClient;
class FrameworkListener : public SocketListener {
public:
static const int CMD_ARGS_MAX = 8;
private:
FrameworkCommandCollection *mCommands;
public:
FrameworkListener(const char *socketName);
virtual ~FrameworkListener() {}
protected:
void registerCmd(FrameworkCommand *cmd);
virtual bool onDataAvailable(SocketClient *c);
private:
void dispatchCommand(SocketClient *c, char *data);
};
#endif

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _NETLINKEVENT_H
#define _NETLINKEVENT_H
#define NL_PARAMS_MAX 32
class NetlinkEvent {
int mSeq;
char *mPath;
int mAction;
char *mSubsystem;
char *mParams[NL_PARAMS_MAX];
public:
const static int NlActionUnknown;
const static int NlActionAdd;
const static int NlActionRemove;
const static int NlActionChange;
NetlinkEvent();
virtual ~NetlinkEvent();
bool decode(char *buffer, int size);
const char *findParam(const char *paramName);
const char *getSubsystem() { return mSubsystem; }
int getAction() { return mAction; }
};
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _NETLINKLISTENER_H
#define _NETLINKLISTENER_H
#include "SocketListener.h"
class NetlinkEvent;
class NetlinkListener : public SocketListener {
char mBuffer[64 * 1024];
public:
NetlinkListener(int socket);
virtual ~NetlinkListener() {}
protected:
virtual bool onDataAvailable(SocketClient *cli);
};
#endif

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _SERVICE_MANAGER_H
#define _SERVICE_MANAGER_H
class ServiceManager {
public:
ServiceManager();
virtual ~ServiceManager() {}
int start(const char *name);
int stop(const char *name);
bool isRunning(const char *name);
};
#endif

View File

@ -0,0 +1,23 @@
#ifndef _SOCKET_CLIENT_H
#define _SOCKET_CLIENT_H
#include "../../../frameworks/base/include/utils/List.h"
#include <pthread.h>
class SocketClient {
int mSocket;
pthread_mutex_t mWriteMutex;
public:
SocketClient(int sock);
virtual ~SocketClient() {}
int getSocket() { return mSocket; }
int sendMsg(int code, const char *msg, bool addErrno);
int sendMsg(const char *msg);
};
typedef android::List<SocketClient *> SocketClientCollection;
#endif

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _SOCKETLISTENER_H
#define _SOCKETLISTENER_H
#include <pthread.h>
#include <sysutils/SocketClient.h>
class SocketListener {
int mSock;
const char *mSocketName;
SocketClientCollection *mClients;
pthread_mutex_t mClientsLock;
bool mListen;
int mCtrlPipe[2];
pthread_t mThread;
public:
SocketListener(const char *socketNames, bool listen);
SocketListener(int socketFd, bool listen);
virtual ~SocketListener() {}
int startListener();
int stopListener();
void sendBroadcast(int code, const char *msg, bool addErrno);
void sendBroadcast(const char *msg);
protected:
virtual bool onDataAvailable(SocketClient *c) = 0;
private:
static void *threadStart(void *obj);
void runListener();
};
#endif

View File

@ -127,7 +127,7 @@ done:
static void service_start_if_not_disabled(struct service *svc)
{
if (!(svc->flags & SVC_DISABLED)) {
service_start(svc);
service_start(svc, NULL);
}
}
@ -372,7 +372,7 @@ int do_start(int nargs, char **args)
struct service *svc;
svc = service_find_by_name(args[1]);
if (svc) {
service_start(svc);
service_start(svc, NULL);
}
return 0;
}
@ -393,7 +393,7 @@ int do_restart(int nargs, char **args)
svc = service_find_by_name(args[1]);
if (svc) {
service_stop(svc);
service_start(svc);
service_start(svc, NULL);
}
return 0;
}

View File

@ -115,6 +115,7 @@ static struct perms_ devperms[] = {
{ "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
{ "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
{ "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 },
{ "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
@ -126,10 +127,13 @@ static struct perms_ devperms[] = {
{ "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qemu_trace", 0666, AID_SYSTEM, AID_SYSTEM, 0 },
{ "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/ppp", 0660, AID_RADIO, AID_VPN, 0 },
{ "/dev/tun", 0640, AID_VPN, AID_VPN, 0 },
{ NULL, 0, 0, 0, 0 },
};
@ -380,7 +384,10 @@ static void handle_device_event(struct uevent *uevent)
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
base = "/dev/adsp/";
mkdir(base, 0755);
} else if(!strncmp(uevent->subsystem, "input", 5)) {
} else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
base = "/dev/msm_camera/";
mkdir(base, 0755);
} else if(!strncmp(uevent->subsystem, "input", 5)) {
base = "/dev/input/";
mkdir(base, 0755);
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {

View File

@ -156,7 +156,7 @@ static void publish_socket(const char *name, int fd)
fcntl(fd, F_SETFD, 0);
}
void service_start(struct service *svc)
void service_start(struct service *svc, const char *dynamic_args)
{
struct stat s;
pid_t pid;
@ -192,6 +192,13 @@ void service_start(struct service *svc)
return;
}
if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
svc->args[0]);
svc->flags |= SVC_DISABLED;
return;
}
NOTICE("starting '%s'\n", svc->name);
pid = fork();
@ -248,8 +255,27 @@ void service_start(struct service *svc)
setuid(svc->uid);
}
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
if (!dynamic_args)
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0)
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
else {
char *arg_ptrs[SVC_MAXARGS+1];
int arg_idx = svc->nargs;
char *tmp = strdup(dynamic_args);
char *next = tmp;
char *bword;
/* Copy the static arguments */
memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
while((bword = strsep(&next, " "))) {
arg_ptrs[arg_idx++] = bword;
if (arg_idx == SVC_MAXARGS)
break;
}
arg_ptrs[arg_idx] = '\0';
if (execve(svc->args[0], (char**) arg_ptrs, (char**) ENV) < 0)
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
}
_exit(127);
}
@ -381,7 +407,7 @@ static void restart_service_if_needed(struct service *svc)
if (next_start_time <= gettime()) {
svc->flags &= (~SVC_RESTARTING);
service_start(svc);
service_start(svc, NULL);
return;
}
@ -407,13 +433,28 @@ static void sigchld_handler(int s)
static void msg_start(const char *name)
{
struct service *svc = service_find_by_name(name);
struct service *svc;
char *tmp = NULL;
char *args = NULL;
if (!strchr(name, ':'))
svc = service_find_by_name(name);
else {
tmp = strdup(name);
args = strchr(tmp, ':');
*args = '\0';
args++;
svc = service_find_by_name(tmp);
}
if (svc) {
service_start(svc);
service_start(svc, args);
} else {
ERROR("no such service '%s'\n", name);
}
if (tmp)
free(tmp);
}
static void msg_stop(const char *name)
@ -423,7 +464,7 @@ static void msg_stop(const char *name)
if (svc) {
service_stop(svc);
} else {
ERROR("no such service '%s'\n");
ERROR("no such service '%s'\n", name);
}
}
@ -739,7 +780,7 @@ void handle_keychord(int fd)
svc = service_find_by_keychord(id);
if (svc) {
INFO("starting service %s from keychord\n", svc->name);
service_start(svc);
service_start(svc, NULL);
} else {
ERROR("service for keychord %d not found\n", id);
}

View File

@ -29,7 +29,8 @@ void *read_file(const char *fn, unsigned *_sz);
void log_init(void);
void log_set_level(int level);
void log_close(void);
void log_write(int level, const char *fmt, ...);
void log_write(int level, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
#define ERROR(x...) log_write(3, "<3>init: " x)
#define NOTICE(x...) log_write(5, "<5>init: " x)
@ -115,6 +116,8 @@ struct svcenvinfo {
#define NR_SVC_SUPP_GIDS 6 /* six supplementary groups */
#define SVC_MAXARGS 64
struct service {
/* list of all services */
struct listnode slist;
@ -136,15 +139,17 @@ struct service {
struct socketinfo *sockets;
struct svcenvinfo *envvars;
int nargs;
char *args[1];
struct action onrestart; /* Actions to execute on restart. */
/* keycodes for triggering this service via /dev/keychord */
int *keycodes;
int nkeycodes;
int keychord_id;
};
int nargs;
/* "MUST BE AT THE END OF THE STRUCT" */
char *args[1];
}; /* ^-------'args' MUST be at the end of this struct! */
int parse_config_file(const char *fn);
@ -157,7 +162,7 @@ void service_for_each_class(const char *classname,
void service_for_each_flags(unsigned matchflags,
void (*func)(struct service *svc));
void service_stop(struct service *svc);
void service_start(struct service *svc);
void service_start(struct service *svc, const char *dynamic_args);
void property_changed(const char *name, const char *value);
struct action *action_remove_queue_head(void);

View File

@ -60,8 +60,6 @@ void DUMP(void)
#endif
}
#define MAXARGS 64
#define T_EOF 0
#define T_TEXT 1
#define T_NEWLINE 2
@ -357,7 +355,7 @@ void parse_new_section(struct parse_state *state, int kw,
static void parse_config(const char *fn, char *s)
{
struct parse_state state;
char *args[MAXARGS];
char *args[SVC_MAXARGS];
int nargs;
nargs = 0;
@ -384,7 +382,7 @@ static void parse_config(const char *fn, char *s)
}
break;
case T_TEXT:
if (nargs < MAXARGS) {
if (nargs < SVC_MAXARGS) {
args[nargs++] = state.text;
}
break;
@ -536,7 +534,7 @@ void queue_all_property_triggers()
const char* name = act->name + strlen("property:");
const char* equals = strchr(name, '=');
if (equals) {
char* prop_name[PROP_NAME_MAX + 1];
char prop_name[PROP_NAME_MAX + 1];
const char* value;
int length = equals - name;
if (length > PROP_NAME_MAX) {
@ -546,7 +544,7 @@ void queue_all_property_triggers()
prop_name[length] = 0;
/* does the property exist, and match the trigger value? */
value = property_get((const char *)&prop_name[0]);
value = property_get(prop_name);
if (value && !strcmp(equals + 1, value)) {
action_add_queue_tail(act);
}

View File

@ -67,6 +67,8 @@ struct {
{ "wlan.", AID_SYSTEM },
{ "dhcp.", AID_SYSTEM },
{ "dhcp.", AID_DHCP },
{ "vpn.", AID_SYSTEM },
{ "vpn.", AID_VPN },
{ "debug.", AID_SHELL },
{ "log.", AID_SHELL },
{ "service.adb.root", AID_SHELL },
@ -296,7 +298,7 @@ int property_set(const char *name, const char *value)
__futex_wake(&pa->serial, INT32_MAX);
}
/* If name starts with "net." treat as a DNS property. */
if (strncmp("net.", name, sizeof("net.") - 1) == 0) {
if (strncmp("net.", name, strlen("net.")) == 0) {
if (strcmp("net.change", name) == 0) {
return 0;
}
@ -307,7 +309,7 @@ int property_set(const char *name, const char *value)
*/
property_set("net.change", name);
} else if (persistent_properties_loaded &&
strncmp("persist.", name, sizeof("persist.") - 1) == 0) {
strncmp("persist.", name, strlen("persist.")) == 0) {
/*
* Don't write properties to disk until after we have read all default properties
* to prevent them from being overwritten by default values.
@ -446,8 +448,7 @@ static void load_persistent_properties()
if (dir) {
while ((entry = readdir(dir)) != NULL) {
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ||
strncmp("persist.", entry->d_name, sizeof("persist.") - 1))
if (strncmp("persist.", entry->d_name, strlen("persist.")))
continue;
#if HAVE_DIRENT_D_TYPE
if (entry->d_type != DT_REG)

View File

@ -21,6 +21,7 @@ commonSources := \
array.c \
hashmap.c \
atomic.c \
native_handle.c \
buffer.c \
socket_inaddr_any_server.c \
socket_local_client.c \
@ -59,7 +60,6 @@ else
commonSources += \
mspace.c \
selector.c \
fdevent.c \
tztime.c \
tzstrftime.c \
adb_networking.c \

View File

@ -83,3 +83,8 @@ int ashmem_unpin_region(int fd, size_t offset, size_t len)
struct ashmem_pin pin = { offset, len };
return ioctl(fd, ASHMEM_UNPIN, &pin);
}
int ashmem_get_size_region(int fd)
{
return ioctl(fd, ASHMEM_GET_SIZE, NULL);
}

View File

@ -92,3 +92,23 @@ int ashmem_unpin_region(int fd, size_t offset, size_t len)
{
return ASHMEM_IS_UNPINNED;
}
int ashmem_get_size_region(int fd)
{
struct stat buf;
int result;
result = fstat(fd, &buf);
if (result == -1) {
return -1;
}
// Check if this is an "ashmem" region.
// TODO: This is very hacky, and can easily break. We need some reliable indicator.
if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) {
errno = ENOTTY;
return -1;
}
return (int)buf.st_size; // TODO: care about overflow (> 2GB file)?
}

60
libcutils/native_handle.c Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2007 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.
*/
#define LOG_TAG "NativeHandle"
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <cutils/log.h>
#include <cutils/native_handle.h>
native_handle_t* native_handle_create(int numFds, int numInts)
{
native_handle_t* h = malloc(
sizeof(native_handle_t) + sizeof(int)*(numFds+numInts));
h->version = sizeof(native_handle_t);
h->numFds = numFds;
h->numInts = numInts;
return h;
}
int native_handle_delete(native_handle_t* h)
{
if (h) {
if (h->version != sizeof(native_handle_t))
return -EINVAL;
free(h);
}
return 0;
}
int native_handle_close(const native_handle_t* h)
{
if (h->version != sizeof(native_handle_t))
return -EINVAL;
const int numFds = h->numFds;
int i;
for (i=0 ; i<numFds ; i++) {
close(h->data[i]);
}
return 0;
}

View File

@ -172,10 +172,17 @@ label:
pt, ptlim, modifier);
continue;
case 'B':
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->month[t->tm_mon],
pt, ptlim, modifier);
if (modifier == '-') {
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->standalone_month[t->tm_mon],
pt, ptlim, modifier);
} else {
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->month[t->tm_mon],
pt, ptlim, modifier);
}
continue;
case 'b':
case 'h':

View File

@ -143,12 +143,16 @@ int __android_log_write(int prio, const char *tag, const char *msg)
/* XXX: This needs to go! */
if (!strcmp(tag, "HTC_RIL") ||
!strcmp(tag, "RILJ") ||
!strcmp(tag, "RILB") ||
!strcmp(tag, "RILC") ||
!strcmp(tag, "RILD") ||
!strcmp(tag, "RIL") ||
!strcmp(tag, "AT") ||
!strcmp(tag, "GSM") ||
!strcmp(tag, "STK"))
!strcmp(tag, "STK") ||
!strcmp(tag, "CDMA") ||
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS"))
log_id = LOG_ID_RADIO;
vec[0].iov_base = (unsigned char *) &prio;

View File

@ -21,8 +21,9 @@
#include <stdint.h>
#include <sys/types.h>
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
#include "tinyutils/Vector.h"
#include "tinyutils/KeyedVector.h"
#include "tinyutils/smartpointer.h"
#include "tinyutils/smartpointer.h"
#include "codeflinger/ARMAssemblerInterface.h"

View File

@ -23,8 +23,7 @@
#include <pthread.h>
#include <sys/types.h>
#include <utils/KeyedVector.h>
#include "tinyutils/KeyedVector.h"
#include "tinyutils/smartpointer.h"
namespace android {

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2007 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.
*/
#ifndef ANDROID_ERRORS_H
#define ANDROID_ERRORS_H
#include <sys/types.h>
#include <errno.h>
namespace android {
// use this type to return error codes
typedef int32_t status_t;
/*
* Error codes.
* All error codes are negative values.
*/
enum {
OK = 0, // Everything's swell.
NO_ERROR = 0, // No errors.
UNKNOWN_ERROR = 0x80000000,
NO_MEMORY = -ENOMEM,
INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
BAD_TYPE = 0x80000001,
NAME_NOT_FOUND = -ENOENT,
PERMISSION_DENIED = -EPERM,
NO_INIT = -ENODEV,
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = 0x80000002,
JPARKS_BROKE_IT = -EPIPE,
BAD_INDEX = -EOVERFLOW,
NOT_ENOUGH_DATA = -ENODATA,
WOULD_BLOCK = -EWOULDBLOCK,
TIMED_OUT = -ETIME,
UNKNOWN_TRANSACTION = -EBADMSG,
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_ERRORS_H

View File

@ -0,0 +1,282 @@
/*
* Copyright (C) 2005 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.
*/
#ifndef ANDROID_SORTED_VECTOR_H
#define ANDROID_SORTED_VECTOR_H
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
#include "tinyutils/Vector.h"
#include "tinyutils/VectorImpl.h"
#include "tinyutils/TypeHelpers.h"
// ---------------------------------------------------------------------------
namespace android {
template <class TYPE>
class SortedVector : private SortedVectorImpl
{
public:
typedef TYPE value_type;
/*!
* Constructors and destructors
*/
SortedVector();
SortedVector(const SortedVector<TYPE>& rhs);
virtual ~SortedVector();
/*! copy operator */
const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
/*
* empty the vector
*/
inline void clear() { VectorImpl::clear(); }
/*!
* vector stats
*/
//! returns number of items in the vector
inline size_t size() const { return VectorImpl::size(); }
//! returns wether or not the vector is empty
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
//! returns how many items can be stored without reallocating the backing store
inline size_t capacity() const { return VectorImpl::capacity(); }
//! setst the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
/*!
* C-style array access
*/
//! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access. BE VERY CAREFUL when modifying the array
//! you ust keep it sorted! You usually don't use this function.
TYPE* editArray();
//! finds the index of an item
ssize_t indexOf(const TYPE& item) const;
//! finds where this item should be inserted
size_t orderOf(const TYPE& item) const;
/*!
* accessors
*/
//! read-only access to an item at a given index
inline const TYPE& operator [] (size_t index) const;
//! alternate name for operator []
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
//! same as operator [], but allows to access the vector backward (from the end) with a negative index
const TYPE& mirrorItemAt(ssize_t index) const;
/*!
* modifing the array
*/
//! add an item in the right place (and replace the one that is there)
ssize_t add(const TYPE& item);
//! editItemAt() MUST NOT change the order of this item
TYPE& editItemAt(size_t index) {
return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
}
//! merges a vector into this one
ssize_t merge(const Vector<TYPE>& vector);
ssize_t merge(const SortedVector<TYPE>& vector);
//! removes an item
ssize_t remove(const TYPE&);
//! remove several items
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
virtual void do_copy(void* dest, const void* from, size_t num) const;
virtual void do_splat(void* dest, const void* item, size_t num) const;
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
virtual int do_compare(const void* lhs, const void* rhs) const;
};
// ---------------------------------------------------------------------------
// No user serviceable parts from here...
// ---------------------------------------------------------------------------
template<class TYPE> inline
SortedVector<TYPE>::SortedVector()
: SortedVectorImpl(sizeof(TYPE),
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0)
|(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
)
{
}
template<class TYPE> inline
SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
: SortedVectorImpl(rhs) {
}
template<class TYPE> inline
SortedVector<TYPE>::~SortedVector() {
finish_vector();
}
template<class TYPE> inline
SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
SortedVectorImpl::operator = (rhs);
return *this;
}
template<class TYPE> inline
const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
SortedVectorImpl::operator = (rhs);
return *this;
}
template<class TYPE> inline
const TYPE* SortedVector<TYPE>::array() const {
return static_cast<const TYPE *>(arrayImpl());
}
template<class TYPE> inline
TYPE* SortedVector<TYPE>::editArray() {
return static_cast<TYPE *>(editArrayImpl());
}
template<class TYPE> inline
const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
assert( index<size() );
return *(array() + index);
}
template<class TYPE> inline
const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
return operator[](index);
}
template<class TYPE> inline
const TYPE& SortedVector<TYPE>::mirrorItemAt(ssize_t index) const {
assert( (index>0 ? index : -index)<size() );
return *(array() + ((index<0) ? (size()-index) : index));
}
template<class TYPE> inline
const TYPE& SortedVector<TYPE>::top() const {
return *(array() + size() - 1);
}
template<class TYPE> inline
ssize_t SortedVector<TYPE>::add(const TYPE& item) {
return SortedVectorImpl::add(&item);
}
template<class TYPE> inline
ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
return SortedVectorImpl::indexOf(&item);
}
template<class TYPE> inline
size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
return SortedVectorImpl::orderOf(&item);
}
template<class TYPE> inline
ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
}
template<class TYPE> inline
ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
}
template<class TYPE> inline
ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
return SortedVectorImpl::remove(&item);
}
template<class TYPE> inline
ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
return VectorImpl::removeItemsAt(index, count);
}
// ---------------------------------------------------------------------------
template<class TYPE>
void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
destroy_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
}
template<class TYPE>
void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
}
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_SORTED_VECTOR_H

View File

@ -15,6 +15,7 @@
#include <cutils/log.h>
#include "tinyutils/Errors.h"
#include "tinyutils/VectorImpl.h"
#include "tinyutils/TypeHelpers.h"
@ -302,16 +303,6 @@ ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
return VectorImpl::removeItemsAt(index, count);
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
return VectorImpl::sort((VectorImpl::compar_t)cmp);
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
}
// ---------------------------------------------------------------------------
template<class TYPE>

35
libsysutils/Android.mk Normal file
View File

@ -0,0 +1,35 @@
BUILD_LIBSYSUTILS := false
ifneq ($(TARGET_SIMULATOR),true)
BUILD_LIBSYSUTILS := true
endif
ifeq ($(BUILD_LIBSYSUTILS),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
src/SocketListener.cpp \
src/FrameworkListener.cpp \
src/NetlinkListener.cpp \
src/NetlinkEvent.cpp \
src/FrameworkCommand.cpp \
src/SocketClient.cpp \
src/ServiceManager.cpp \
LOCAL_MODULE:= libsysutils
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libcutils
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -lpthread
endif
include $(BUILD_SHARED_LIBRARY)
endif

View File

@ -0,0 +1,40 @@
#include <alloca.h>
#include <errno.h>
#include <sys/types.h>
#include <pthread.h>
#define LOG_TAG "FrameworkClient"
#include <cutils/log.h>
#include <sysutils/FrameworkClient.h>
FrameworkClient::FrameworkClient(int socket) {
mSocket = socket;
pthread_mutex_init(&mWriteMutex, NULL);
}
int FrameworkClient::sendMsg(const char *msg) {
if (mSocket < 0) {
errno = EHOSTUNREACH;
return -1;
}
pthread_mutex_lock(&mWriteMutex);
if (write(mSocket, msg, strlen(msg) +1) < 0) {
LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
}
pthread_mutex_unlock(&mWriteMutex);
return 0;
}
int FrameworkClient::sendMsg(const char *msg, const char *data) {
char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1);
if (!buffer) {
errno = -ENOMEM;
return -1;
}
strcpy(buffer, msg);
strcat(buffer, data);
return sendMsg(buffer);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2008 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.
*/
#include <errno.h>
#define LOG_TAG "FrameworkCommand"
#include <cutils/log.h>
#include <sysutils/FrameworkCommand.h>
FrameworkCommand::FrameworkCommand(const char *cmd) {
mCommand = cmd;
}
int FrameworkCommand::runCommand(SocketClient *c, int argc, char **argv) {
LOGW("Command %s has no run handler!", getCommand());
errno = ENOSYS;
return -1;
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2008 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.
*/
#include <errno.h>
#include <string.h>
#define LOG_TAG "FrameworkListener"
#include <cutils/log.h>
#include <sysutils/FrameworkListener.h>
#include <sysutils/FrameworkCommand.h>
#include <sysutils/SocketClient.h>
FrameworkListener::FrameworkListener(const char *socketName) :
SocketListener(socketName, true) {
mCommands = new FrameworkCommandCollection();
}
bool FrameworkListener::onDataAvailable(SocketClient *c) {
char buffer[255];
int len;
if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
LOGE("read() failed (%s)", strerror(errno));
return errno;
} else if (!len)
return false;
int offset = 0;
int i;
for (i = 0; i < len; i++) {
if (buffer[i] == '\0') {
dispatchCommand(c, buffer + offset);
offset = i + 1;
}
}
return true;
}
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
mCommands->push_back(cmd);
}
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
int argc;
char *argv[FrameworkListener::CMD_ARGS_MAX];
if (!index(data, '"')) {
char *next = data;
char *field;
int i;
for (i = 0; (i < FrameworkListener::CMD_ARGS_MAX) &&
(argv[i] = strsep(&next, " ")); i++);
argc = i+1;
} else {
LOGD("blehhh not supported");
return;
}
FrameworkCommandCollection::iterator i;
for (i = mCommands->begin(); i != mCommands->end(); ++i) {
FrameworkCommand *c = *i;
if (!strcmp(argv[0], c->getCommand())) {
if (c->runCommand(cli, argc, argv)) {
LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
}
return;
}
}
cli->sendMsg(500, "Command not recognized", false);
return;
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdlib.h>
#include <string.h>
#define LOG_TAG "NetlinkEvent"
#include <cutils/log.h>
#include <sysutils/NetlinkEvent.h>
const int NetlinkEvent::NlActionUnknown = 0;
const int NetlinkEvent::NlActionAdd = 1;
const int NetlinkEvent::NlActionRemove = 2;
const int NetlinkEvent::NlActionChange = 3;
NetlinkEvent::NetlinkEvent() {
mAction = NlActionUnknown;
}
NetlinkEvent::~NetlinkEvent() {
int i;
if (mPath)
free(mPath);
if (mSubsystem)
free(mSubsystem);
for (i = 0; i < NL_PARAMS_MAX; i++) {
if (!mParams[i])
break;
free(mParams[i]);
}
}
bool NetlinkEvent::decode(char *buffer, int size) {
char *s = buffer;
char *end;
int param_idx = 0;
int i;
int first = 1;
end = s + size;
while (s < end) {
if (first) {
char *p;
for (p = s; *p != '@'; p++);
p++;
mPath = strdup(p);
first = 0;
} else {
if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
char *a = s + strlen("ACTION=");
if (!strcmp(a, "add"))
mAction = NlActionAdd;
else if (!strcmp(a, "remove"))
mAction = NlActionRemove;
else if (!strcmp(a, "change"))
mAction = NlActionChange;
} else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
mSeq = atoi(s + strlen("SEQNUM="));
else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
mSubsystem = strdup(s + strlen("SUBSYSTEM="));
else
mParams[param_idx++] = strdup(s);
}
s+= strlen(s) + 1;
}
return true;
}
const char *NetlinkEvent::findParam(const char *paramName) {
int i;
for (i = 0; i < NL_PARAMS_MAX; i++) {
if (!mParams[i])
break;
if (!strncmp(mParams[i], paramName, strlen(paramName)))
return &mParams[i][strlen(paramName) + 1];
}
LOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
return NULL;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2008 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.
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#define LOG_TAG "NetlinkListener"
#include <cutils/log.h>
#include <sysutils/NetlinkListener.h>
#include <sysutils/NetlinkEvent.h>
NetlinkListener::NetlinkListener(int socket) :
SocketListener(socket, false) {
}
bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
int socket = cli->getSocket();
LOGD("NetlinkListener::onDataAvailable()");
int count;
if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) {
LOGE("recv failed (%s)", strerror(errno));
return false;
}
NetlinkEvent *evt = new NetlinkEvent();
if (!evt->decode(mBuffer, count)) {
LOGE("Error decoding NetlinkEvent");
goto out;
}
LOGD("Ignoring '%s' netlink event", evt->getSubsystem());
out:
delete evt;
return true;
}

View File

@ -0,0 +1,73 @@
#include <errno.h>
#include <sysutils/ServiceManager.h>
#define LOG_TAG "Service"
#include <cutils/log.h>
#include <cutils/properties.h>
ServiceManager::ServiceManager() {
}
int ServiceManager::start(const char *name) {
if (isRunning(name)) {
LOGW("Service '%s' is already running", name);
return 0;
}
LOGD("Starting service '%s'", name);
property_set("ctl.start", name);
int count = 200;
while(count--) {
sched_yield();
if (isRunning(name))
break;
}
if (!count) {
LOGW("Timed out waiting for service '%s' to start", name);
errno = ETIMEDOUT;
return -1;
}
LOGD("Sucessfully started '%s'", name);
return 0;
}
int ServiceManager::stop(const char *name) {
if (!isRunning(name)) {
LOGW("Service '%s' is already stopped", name);
return 0;
}
LOGD("Stopping service '%s'", name);
property_set("ctl.stop", name);
int count = 200;
while(count--) {
sched_yield();
if (!isRunning(name))
break;
}
if (!count) {
LOGW("Timed out waiting for service '%s' to stop", name);
errno = ETIMEDOUT;
return -1;
}
LOGD("Sucessfully stopped '%s'", name);
return 0;
}
bool ServiceManager::isRunning(const char *name) {
char propVal[PROPERTY_VALUE_MAX];
char propName[255];
snprintf(propName, sizeof(propVal), "init.svc.%s", name);
if (property_get(propName, propVal, NULL)) {
if (!strcmp(propVal, "running"))
return true;
}
return false;
}

View File

@ -0,0 +1,58 @@
#include <alloca.h>
#include <errno.h>
#include <sys/types.h>
#include <pthread.h>
#include <string.h>
#define LOG_TAG "SocketClient"
#include <cutils/log.h>
#include <sysutils/SocketClient.h>
SocketClient::SocketClient(int socket) {
mSocket = socket;
pthread_mutex_init(&mWriteMutex, NULL);
}
int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
char *buf;
if (addErrno) {
buf = (char *) alloca(strlen(msg) + strlen(strerror(errno)) + 8);
sprintf(buf, "%.3d %s (%s)", code, msg, strerror(errno));
} else {
buf = (char *) alloca(strlen(msg) + strlen("XXX "));
sprintf(buf, "%.3d %s", code, msg);
}
return sendMsg(buf);
}
int SocketClient::sendMsg(const char *msg) {
if (mSocket < 0) {
errno = EHOSTUNREACH;
return -1;
}
// Send the message including null character
int rc = 0;
const char *p = msg;
int brtw = strlen(msg) + 1;
pthread_mutex_lock(&mWriteMutex);
while(brtw) {
if ((rc = write(mSocket,p, brtw)) < 0) {
LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
pthread_mutex_unlock(&mWriteMutex);
return -1;
} else if (!rc) {
LOGW("0 length write :(");
errno = EIO;
pthread_mutex_unlock(&mWriteMutex);
return -1;
}
p += rc;
brtw -= rc;
}
pthread_mutex_unlock(&mWriteMutex);
return 0;
}

View File

@ -0,0 +1,197 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#define LOG_TAG "SocketListener"
#include <cutils/log.h>
#include <cutils/sockets.h>
#include <sysutils/SocketListener.h>
#include <sysutils/SocketClient.h>
SocketListener::SocketListener(const char *socketName, bool listen) {
mListen = listen;
mSocketName = socketName;
mSock = -1;
pthread_mutex_init(&mClientsLock, NULL);
mClients = new SocketClientCollection();
}
SocketListener::SocketListener(int socketFd, bool listen) {
mListen = listen;
mSocketName = NULL;
mSock = socketFd;
pthread_mutex_init(&mClientsLock, NULL);
mClients = new SocketClientCollection();
}
int SocketListener::startListener() {
if (!mSocketName && mSock == -1) {
errno = EINVAL;
return -1;
} else if (mSocketName) {
if ((mSock = android_get_control_socket(mSocketName)) < 0) {
LOGE("Obtaining file descriptor socket '%s' failed: %s",
mSocketName, strerror(errno));
return -1;
}
}
if (mListen && listen(mSock, 4) < 0) {
LOGE("Unable to listen on socket (%s)", strerror(errno));
return -1;
} else if (!mListen)
mClients->push_back(new SocketClient(mSock));
if (pipe(mCtrlPipe))
return -1;
if (pthread_create(&mThread, NULL, SocketListener::threadStart, this))
return -1;
return 0;
}
int SocketListener::stopListener() {
char c = 0;
if (write(mCtrlPipe[1], &c, 1) != 1) {
LOGE("Error writing to control pipe (%s)", strerror(errno));
return -1;
}
void *ret;
if (pthread_join(mThread, &ret)) {
LOGE("Error joining to listener thread (%s)", strerror(errno));
return -1;
}
close(mCtrlPipe[0]);
close(mCtrlPipe[1]);
return 0;
}
void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast<SocketListener *>(obj);
me->runListener();
pthread_exit(NULL);
return NULL;
}
void SocketListener::runListener() {
while(1) {
SocketClientCollection::iterator it;
fd_set read_fds;
int rc = 0;
int max = 0;
FD_ZERO(&read_fds);
if (mListen) {
max = mSock;
FD_SET(mSock, &read_fds);
}
FD_SET(mCtrlPipe[0], &read_fds);
if (mCtrlPipe[0] > max)
max = mCtrlPipe[0];
pthread_mutex_lock(&mClientsLock);
for (it = mClients->begin(); it != mClients->end(); ++it) {
FD_SET((*it)->getSocket(), &read_fds);
if ((*it)->getSocket() > max)
max = (*it)->getSocket();
}
pthread_mutex_unlock(&mClientsLock);
if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
LOGE("select failed (%s)", strerror(errno));
sleep(1);
continue;
} else if (!rc)
continue;
if (FD_ISSET(mCtrlPipe[0], &read_fds))
break;
if (mListen && FD_ISSET(mSock, &read_fds)) {
struct sockaddr addr;
socklen_t alen = sizeof(addr);
int c;
if ((c = accept(mSock, &addr, &alen)) < 0) {
LOGE("accept failed (%s)", strerror(errno));
sleep(1);
continue;
}
pthread_mutex_lock(&mClientsLock);
mClients->push_back(new SocketClient(c));
pthread_mutex_unlock(&mClientsLock);
}
do {
pthread_mutex_lock(&mClientsLock);
for (it = mClients->begin(); it != mClients->end(); ++it) {
int fd = (*it)->getSocket();
if (FD_ISSET(fd, &read_fds)) {
pthread_mutex_unlock(&mClientsLock);
if (!onDataAvailable(*it)) {
close(fd);
pthread_mutex_lock(&mClientsLock);
delete *it;
it = mClients->erase(it);
pthread_mutex_unlock(&mClientsLock);
}
FD_CLR(fd, &read_fds);
continue;
}
}
pthread_mutex_unlock(&mClientsLock);
} while (0);
}
}
void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
pthread_mutex_lock(&mClientsLock);
SocketClientCollection::iterator i;
for (i = mClients->begin(); i != mClients->end(); ++i) {
if ((*i)->sendMsg(code, msg, addErrno)) {
LOGW("Error sending broadcast (%s)", strerror(errno));
}
}
pthread_mutex_unlock(&mClientsLock);
}
void SocketListener::sendBroadcast(const char *msg) {
pthread_mutex_lock(&mClientsLock);
SocketClientCollection::iterator i;
for (i = mClients->begin(); i != mClients->end(); ++i) {
if ((*i)->sendMsg(msg)) {
LOGW("Error sending broadcast (%s)", strerror(errno));
}
}
pthread_mutex_unlock(&mClientsLock);
}

View File

@ -323,6 +323,12 @@
# PDP drop caused by network
50109 pdp_network_drop (cid|1|5), (network_type|1|5)
# CDMA data network setup failure
50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5)
# CDMA data network drop
50111 cdma_data_drop (cid|1|5), (network_type|1|5)
# Do not change these names without updating tag in:
#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5)
@ -344,3 +350,6 @@
# browser stats for diary study
70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3)
70102 browser_double_tap_duration (duration|1|3),(time|2|3)
# NOTE - the range 1000000-2000000 is reserved for partners and others who
# want to define their own log tags without conflicting with the core platform.

View File

@ -63,6 +63,7 @@ int usage(void)
" [ --second <2ndbootloader-filename> ]\n"
" [ --cmdline <kernel-commandline> ]\n"
" [ --board <boardname> ]\n"
" [ --base <address> ]\n"
" -o|--output <filename>\n"
);
return 1;
@ -104,7 +105,6 @@ int main(int argc, char **argv)
char *bootimg = 0;
char *board = "";
unsigned pagesize = 2048;
unsigned saddr = 0;
int fd;
SHA_CTX ctx;
uint8_t* sha;
@ -114,6 +114,14 @@ int main(int argc, char **argv)
memset(&hdr, 0, sizeof(hdr));
/* default load addresses */
hdr.kernel_addr = 0x10008000;
hdr.ramdisk_addr = 0x11000000;
hdr.second_addr = 0x10F00000;
hdr.tags_addr = 0x10000100;
hdr.page_size = pagesize;
while(argc > 0){
char *arg = argv[0];
char *val = argv[1];
@ -132,8 +140,12 @@ int main(int argc, char **argv)
second_fn = val;
} else if(!strcmp(arg, "--cmdline")) {
cmdline = val;
} else if(!strcmp(arg, "--saddr")) {
saddr = strtoul(val, 0, 16);
} else if(!strcmp(arg, "--base")) {
unsigned base = strtoul(val, 0, 16);
hdr.kernel_addr = base + 0x00008000;
hdr.ramdisk_addr = base + 0x01000000;
hdr.second_addr = base + 0x00F00000;
hdr.tags_addr = base + 0x00000100;
} else if(!strcmp(arg, "--board")) {
board = val;
} else {
@ -163,16 +175,6 @@ int main(int argc, char **argv)
strcpy(hdr.name, board);
hdr.kernel_addr = 0x10008000;
hdr.ramdisk_addr = 0x11000000;
if(saddr) {
hdr.second_addr = 0x00300000;
} else {
hdr.second_addr = 0x10F00000;
}
hdr.tags_addr = 0x10000100;
hdr.page_size = pagesize;
memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {

View File

@ -1,774 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
/*
** Android Secure External Cache
*/
#include "mountd.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <pwd.h>
#include <stdlib.h>
#include <poll.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <linux/dm-ioctl.h>
#include <linux/loop.h>
#include <cutils/properties.h>
#include <cutils/misc.h>
#include "ASEC.h"
//#define MODULE_FAILURE_IS_FATAL
extern int init_module(void *, unsigned long, const char *);
extern int delete_module(const char *, unsigned int);
struct asec_context
{
char *name; // Device mapper volume name
char *srcPath; // Path to the source (original) mount
char *backingFile; // Name of the image file
unsigned int sectors; // Number of sectors
char *dstPath; // Destination mount point
char *crypt; // Crypt options
boolean needs_format;
boolean started;
int cacheFd;
int lo_num;
int dm_num;
unsigned char key[16];
};
static const char *MODULES[] = { "dm_mod", "crypto", "crypto_algapi", "crypto_blkcipher",
"cryptomgr", "dm_crypt", "jbd",
"twofish_common", "twofish", "cbc",
"mbcache", "ext3",
NULL };
static const char KEY_PATH[] = "/data/system/asec.key";
static const char MODULE_PATH[] = "/system/lib/modules";
static const char MKE2FS_PATH[] = "/system/bin/mke2fs";
static const char E2FSCK_PATH[] = "/system/bin/e2fsck";
boolean AsecIsStarted(void *Handle)
{
struct asec_context *ctx = (struct asec_context *) Handle;
return ctx->started;
}
const char *AsecMountPoint(void *Handle)
{
struct asec_context *ctx = (struct asec_context *) Handle;
return ctx->dstPath;
}
static boolean AsecIsEnabled()
{
char value[PROPERTY_VALUE_MAX];
int enabled;
property_get(ASEC_ENABLED, value, "0");
if (atoi(value) == 1)
return true;
return false;
}
void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile,
const char *Size, const char *DstPath, const char *Crypt)
{
struct asec_context *ctx;
if (!AsecIsEnabled())
return NULL;
LOG_ASEC("AsecInit(%s, %s, %s, %s, %s, %s):\n",
Name, SrcPath, BackingFile, Size, DstPath, Crypt);
if (!Name || !SrcPath || !BackingFile || !Size || !DstPath || !Crypt) {
LOG_ERROR("AsecInit(): Invalid arguments\n");
return NULL;
}
if (!(ctx = malloc(sizeof(struct asec_context)))) {
LOG_ERROR("AsecInit(): Out of memory\n");
return NULL;
}
memset(ctx, 0, sizeof(struct asec_context));
ctx->name = strdup(Name);
ctx->srcPath = strdup(SrcPath);
ctx->backingFile = strdup(BackingFile);
ctx->sectors = atoi(Size);
ctx->dstPath = strdup(DstPath);
ctx->crypt = strdup(Crypt);
return ctx;
}
void AsecDeinit(void *Handle)
{
struct asec_context *ctx = (struct asec_context *) Handle;
free(ctx->name);
free(ctx->srcPath);
free(ctx->backingFile);
free(ctx->dstPath);
free(ctx->crypt);
free(ctx);
}
static int AsecLoadModules()
{
int i;
for (i = 0; MODULES[i] != NULL; i++) {
const char *moduleName = MODULES[i];
char moduleFile[255];
int rc = 0;
void *module;
unsigned int size;
sprintf(moduleFile, "%s/%s.ko", MODULE_PATH, moduleName);
module = load_file(moduleFile, &size);
if (!module) {
LOG_ERROR("Failed to load module %s (%d)\n", moduleFile, errno);
return -1;
}
rc = init_module(module, size, "");
free(module);
if (rc && errno != EEXIST) {
LOG_ERROR("Failed to init module %s (%d)\n", moduleFile, errno);
return -errno;
}
}
return 0;
}
static int AsecUnloadModules()
{
int i, j, rc;
for (i = 0; MODULES[i] != NULL; i++);
for (j = (i - 1); j >= 0; j--) {
const char *moduleName = MODULES[j];
int maxretry = 10;
while(maxretry-- > 0) {
rc = delete_module(moduleName, O_NONBLOCK | O_EXCL);
if (rc < 0 && errno == EAGAIN)
usleep(500000);
else
break;
}
if (rc != 0) {
LOG_ERROR("Failed to unload module %s\n", moduleName);
return -errno;
}
}
return 0;
}
static int AsecGenerateKey(struct asec_context *ctx)
{
LOG_ASEC("AsecGenerateKey():\n");
memset((void *) ctx->key, 0x69, sizeof(ctx->key));
return 0;
}
static int AsecLoadGenerateKey(struct asec_context *ctx)
{
int fd;
int rc = 0;
if ((fd = open(KEY_PATH, O_RDWR | O_CREAT, 0600)) < 0) {
LOG_ERROR("Error opening / creating keyfile (%d)\n", errno);
return -errno;
}
if (read(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) {
LOG_ASEC("Generating key\n");
if ((rc = AsecGenerateKey(ctx)) < 0) {
LOG_ERROR("Error generating key (%d)\n", rc);
goto out;
}
if (write(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) {
LOG_ERROR("Error writing keyfile (%d)\n", errno);
rc = -1;
goto out;
}
}
out:
close (fd);
return rc;
}
static int AsecFormatFilesystem(struct asec_context *ctx)
{
char cmdline[255];
int rc;
sprintf(cmdline,
"%s -b 4096 -m 1 -j -L \"%s\" /dev/block/dm-%d",
MKE2FS_PATH, ctx->name, ctx->dm_num);
LOG_ASEC("Formatting filesystem (%s)\n", cmdline);
// XXX: PROTECT FROM VIKING KILLER
if ((rc = system(cmdline)) < 0) {
LOG_ERROR("Error executing format command (%d)\n", errno);
return -errno;
}
rc = WEXITSTATUS(rc);
if (!rc) {
LOG_ASEC("Format completed\n");
} else {
LOG_ASEC("Format failed (%d)\n", rc);
}
return rc;
}
static int AsecCheckFilesystem(struct asec_context *ctx)
{
char cmdline[255];
int rc;
sprintf(cmdline, "%s -p /dev/block/dm-%d", E2FSCK_PATH, ctx->dm_num);
LOG_ASEC("Checking filesystem (%s)\n", cmdline);
// XXX: PROTECT FROM VIKING KILLER
if ((rc = system(cmdline)) < 0) {
LOG_ERROR("Error executing check command (%d)\n", errno);
return -errno;
}
rc = WEXITSTATUS(rc);
if (rc == 0) {
LOG_ASEC("ASEC volume '%s' had no errors\n", ctx->name);
} else if (rc == 1) {
LOG_ASEC("ASEC volume '%s' had corrected errors\n", ctx->name);
rc = 0;
} else if (rc == 2) {
LOG_ERROR("ASEC volume '%s' had corrected errors (system should be rebooted)\n", ctx->name);
} else if (rc == 4) {
LOG_ERROR("ASEC volume '%s' had uncorrectable errors\n", ctx->name);
} else if (rc == 8) {
LOG_ERROR("Operational error while checking volume '%s'\n", ctx->name);
} else {
LOG_ERROR("Unknown e2fsck exit code (%d)\n", rc);
}
return rc;
}
static int AsecOpenCreateCache(struct asec_context *ctx)
{
char filepath[255];
sprintf(filepath, "%s/%s", ctx->srcPath, ctx->backingFile);
if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) {
if (errno == ENOENT) {
int rc = 0;
LOG_ASEC("Creating cache file (%u sectors)\n", ctx->sectors);
if ((ctx->cacheFd = creat(filepath, 0600)) < 0) {
LOG_ERROR("Error creating cache (%d)\n", errno);
return -errno;
}
if (ftruncate(ctx->cacheFd, ctx->sectors * 512) < 0) {
LOG_ERROR("Error truncating cache (%d)\n", errno);
close(ctx->cacheFd);
unlink(filepath);
return -errno;
}
LOG_ASEC("Cache created (%u sectors) \n", ctx->sectors);
close(ctx->cacheFd); // creat() is WRONLY
if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) {
LOG_ERROR("Error opening cache file (%d)\n", errno);
close(ctx->cacheFd);
unlink(filepath);
return -errno;
}
ctx->needs_format = 1;
} else
return -errno;
} else {
struct stat stat_buf;
if (fstat(ctx->cacheFd, &stat_buf) < 0) {
LOG_ERROR("Failed to fstat cache (%d)\n", errno);
close(ctx->cacheFd);
return -errno;
}
if (stat_buf.st_size != ctx->sectors * 512) {
LOG_ERROR("Cache size %lld != configured size %u\n",
stat_buf.st_size, ctx->sectors * 512);
}
// XXX: Verify volume label matches ctx->name
}
return 0;
}
static void AsecCloseCache(struct asec_context *ctx)
{
close(ctx->cacheFd);
}
static void *_align(void *ptr, unsigned int a)
{
register unsigned long agn = --a;
return (void *) (((unsigned long) ptr + agn) & ~agn);
}
static struct dm_ioctl *_dm_ioctl_setup(struct asec_context *ctx, int flags)
{
void *buffer;
void *p;
const size_t min_size = 16 * 1024;
size_t len = sizeof(struct dm_ioctl);
struct dm_ioctl *io;
struct dm_target_spec *tgt;
int i;
char params[1024];
char key[80];
key[0] = '\0';
for (i = 0; i < (int) sizeof(ctx->key); i++) {
char tmp[8];
sprintf(tmp, "%02x", ctx->key[i]);
strcat(key, tmp);
}
// XXX: Handle ctx->crypt
sprintf(params, "twofish %s 0 /dev/block/loop%d 0", key, ctx->lo_num);
if (len < min_size)
len = min_size;
if (!(buffer = malloc(len))) {
LOG_ERROR("Unable to allocate memory\n");
return NULL;
}
memset(buffer, 0, len);
io = buffer;
tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
io->version[0] = 4;
io->version[1] = 0;
io->version[2] = 0;
io->data_size = len;
io->data_start = sizeof(struct dm_ioctl);
io->flags = flags;
io->dev = 0;
io->target_count = 1;
io->event_nr = 1;
strncpy(io->name, ctx->name, sizeof(io->name));
tgt->status = 0;
tgt->sector_start = 0;
tgt->length = ctx->sectors;
strncpy(tgt->target_type, "crypt", sizeof(tgt->target_type));
p = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
strcpy((char *) p, params);
p+= strlen(params) + 1;
p = _align(p, 8);
tgt->next = p - buffer;
return io;
}
static int FindNextAvailableDm()
{
int i;
for (i = 0; i < 8; i++) {
char path[255];
sprintf(path, "/dev/block/dm-%d", i);
if ((access(path, F_OK) < 0) && (errno == ENOENT))
return i;
}
LOG_ERROR("Out of device mapper numbers\n");
return -1;
}
static int AsecCreateDeviceMapping(struct asec_context *ctx)
{
struct dm_ioctl *io;
int dmFd;
int rc = 0;
ctx->dm_num = FindNextAvailableDm();
if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
LOG_ERROR("Error opening device mapper (%d)\n", errno);
return -errno;
}
if (!(io = _dm_ioctl_setup(ctx, 0))) {
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
close(dmFd);
return -ENOMEM;
}
if ((rc = ioctl(dmFd, DM_DEV_CREATE, io)) < 0) {
LOG_ERROR("device-mapper create ioctl failed (%d)\n", errno);
rc = -errno;
goto out_free;
}
free(io);
if (!(io = _dm_ioctl_setup(ctx, DM_STATUS_TABLE_FLAG))) {
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
rc = -ENOMEM;
goto out_nofree;
}
if ((rc = ioctl(dmFd, DM_TABLE_LOAD, io)) < 0) {
LOG_ERROR("device-mapper load ioctl failed (%d)\n", errno);
rc = -errno;
goto out_free;
}
free(io);
if (!(io = _dm_ioctl_setup(ctx, 0))) {
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
rc = -ENOMEM;
goto out_nofree;
}
if ((rc = ioctl(dmFd, DM_DEV_SUSPEND, io)) < 0) {
LOG_ERROR("device-mapper resume ioctl failed (%d)\n", errno);
rc = -errno;
goto out_free;
}
out_free:
free (io);
out_nofree:
close (dmFd);
return rc;
}
static int AsecDestroyDeviceMapping(struct asec_context *ctx)
{
struct dm_ioctl *io;
int dmFd;
int rc = 0;
if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
LOG_ERROR("Error opening device mapper (%d)\n", errno);
return -errno;
}
if (!(io = _dm_ioctl_setup(ctx, DM_PERSISTENT_DEV_FLAG))) {
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
rc = -ENOMEM;
goto out_nofree;
}
if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) {
LOG_ERROR("device-mapper remove ioctl failed (%d)\n", errno);
rc = -errno;
goto out_free;
}
out_free:
free (io);
out_nofree:
close (dmFd);
return rc;
}
static int AsecMountCache(struct asec_context *ctx)
{
int flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME;
char devname[255];
if (access(ctx->dstPath, R_OK)) {
LOG_ERROR("Destination mount point '%s' unavailable (%d)\n", ctx->dstPath, errno);
return -errno;
}
sprintf(devname, "/dev/block/dm-%d", ctx->dm_num);
if (mount(devname, ctx->dstPath, "ext3", flags, NULL)) {
LOG_ERROR("ASEC mount failed (%d)\n", errno);
return -errno;
}
return 0;
}
static int AsecUnmountCache(struct asec_context *ctx)
{
if (umount(ctx->dstPath)) {
if (errno == EBUSY) {
LOG_ASEC("ASEC volume '%s' still busy\n", ctx->name);
} else {
LOG_ERROR("ASEC umount failed (%d)\n", errno);
}
return -errno;
}
LOG_ASEC("ASEC volume '%s' unmounted\n", ctx->name);
return 0;
}
static int FindNextAvailableLoop()
{
int i;
for (i = 0; i < MAX_LOOP; i++) {
struct loop_info info;
char devname[255];
int fd;
sprintf(devname, "/dev/block/loop%d", i);
if ((fd = open(devname, O_RDONLY)) < 0) {
LOG_ERROR("Unable to open %s (%d)\n", devname, errno);
return -errno;
}
if (ioctl(fd, LOOP_GET_STATUS, &info) < 0) {
close(fd);
if (errno == ENXIO)
return i;
LOG_ERROR("Unable to get loop status for %s (%d)\n", devname, errno);
return -errno;
}
close(fd);
}
return -ENXIO;
}
static int AsecCreateLoop(struct asec_context *ctx)
{
char devname[255];
int device_fd;
int rc = 0;
ctx->lo_num = FindNextAvailableLoop();
if (ctx->lo_num < 0) {
LOG_ERROR("No loop devices available\n");
return -ENXIO;
}
sprintf(devname, "/dev/block/loop%d", ctx->lo_num);
device_fd = open(devname, O_RDWR);
if (device_fd < 0) {
LOG_ERROR("failed to open loop device (%d)\n", errno);
return -errno;
}
if (ioctl(device_fd, LOOP_SET_FD, ctx->cacheFd) < 0) {
LOG_ERROR("loop_set_fd ioctl failed (%d)\n", errno);
rc = -errno;
}
close(device_fd);
return rc;
}
static int AsecDestroyLoop(struct asec_context *ctx)
{
char devname[255];
int device_fd;
int rc = 0;
sprintf(devname, "/dev/block/loop%d", ctx->lo_num);
device_fd = open(devname, O_RDONLY);
if (device_fd < 0) {
LOG_ERROR("Failed to open loop (%d)\n", errno);
return -errno;
}
if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
LOG_ERROR("Failed to destroy loop (%d)\n", errno);
rc = -errno;
}
close(device_fd);
return rc;
}
int AsecStart(void *Handle)
{
struct asec_context *ctx = (struct asec_context *) Handle;
char value[PROPERTY_VALUE_MAX];
int rc = 0;
if (!ctx)
return -EINVAL;
if (ctx->started)
return -EBUSY;
LOG_ASEC("AsecStart(%s):\n", ctx->name);
NotifyAsecState(ASEC_BUSY, ctx->dstPath);
if ((rc = AsecLoadModules()) < 0) {
LOG_ERROR("AsecStart: Failed to load kernel modules\n");
#ifdef MODULE_FAILURE_IS_FATAL
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
#endif
}
if ((rc = AsecLoadGenerateKey(ctx))) {
LOG_ERROR("AsecStart: Failed to load / generate key\n");
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
}
if ((rc = AsecOpenCreateCache(ctx)) < 0) {
LOG_ERROR("AsecStart: Failed to open / create cache\n");
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
}
if ((rc = AsecCreateLoop(ctx)) < 0) {
LOG_ERROR("AsecStart: Failed to create loop\n");
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
goto fail_closecache;
}
if ((rc = AsecCreateDeviceMapping(ctx)) < 0) {
LOG_ERROR("AsecStart: Failed to create devmapping (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
goto fail_destroyloop;
}
if (ctx->needs_format) {
if ((rc = AsecFormatFilesystem(ctx))) {
LOG_ERROR("AsecStart: Failed to format cache (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
goto fail_destroydm;
}
ctx->needs_format = 0;
} else {
if ((rc = AsecCheckFilesystem(ctx))) {
LOG_ERROR("AsecStart: Failed to check filesystem (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
goto fail_destroydm;
}
}
if ((rc = AsecMountCache(ctx)) < 0) {
LOG_ERROR("AsecStart: Failed to mount cache (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
goto fail_destroydm;
}
NotifyAsecState(ASEC_AVAILABLE, ctx->dstPath);
ctx->started = true;
return rc;
fail_destroydm:
AsecDestroyDeviceMapping(ctx);
fail_destroyloop:
AsecDestroyLoop(ctx);
fail_closecache:
AsecCloseCache(ctx);
return rc;
}
int AsecStop(void *Handle)
{
struct asec_context *ctx = (struct asec_context *) Handle;
int rc = 0;
if (!ctx->started)
return -EINVAL;
LOG_ASEC("AsecStop(%s):\n", ctx->name);
NotifyAsecState(ASEC_BUSY, ctx->dstPath);
if ((rc = AsecUnmountCache(ctx)) < 0) {
LOG_ERROR("AsecStop: Failed to unmount cache (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
}
if ((rc = AsecDestroyDeviceMapping(ctx)) < 0) {
LOG_ERROR("AsecStop: Failed to destroy devmapping (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
}
if ((rc = AsecDestroyLoop(ctx)) < 0) {
LOG_ERROR("AsecStop: Failed to destroy loop device (%d)\n", rc);
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
}
AsecCloseCache(ctx);
if ((rc = AsecUnloadModules()) < 0) {
if (rc == -EAGAIN) {
LOG_ASEC("AsecStop: Kernel modules still in use\n");
} else {
LOG_ERROR("AsecStop: Failed to unload kernel modules (%d)\n", rc);
#ifdef MODULE_FAILURE_IS_FATAL
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
return rc;
#endif
}
}
ctx->started = false;
NotifyAsecState(ASEC_DISABLED, ctx->dstPath);
return rc;
}

View File

@ -1,66 +0,0 @@
#ifndef _ASEC_H
#define _ASEC_H
#define ASEC_STORES_MAX 4
#define MAX_LOOP 8
typedef enum AsecState {
// Feature disabled
ASEC_DISABLED,
// Feature enabled and operational
ASEC_AVAILABLE,
// Busy
ASEC_BUSY,
// Internal Error
ASEC_FAILED_INTERR,
// No media available
ASEC_FAILED_NOMEDIA,
// Media is corrupt
ASEC_FAILED_BADMEDIA,
// Key mismatch
ASEC_FAILED_BADKEY,
} AsecState;
/*
* ASEC commands
*/
#define ASEC_CMD_SEND_STATUS "asec_send_status"
#define ASEC_CMD_ENABLE "asec_enable"
#define ASEC_CMD_DISABLE "asec_disable"
/*
* ASEC events
*/
// These events correspond to the states in the AsecState enum.
// A path to the ASEC mount point follows the colon
#define ASEC_EVENT_DISABLED "asec_disabled:"
#define ASEC_EVENT_AVAILABLE "asec_available:"
#define ASEC_EVENT_BUSY "asec_busy:"
#define ASEC_EVENT_FAILED_INTERR "asec_failed_interror:"
#define ASEC_EVENT_FAILED_NOMEDIA "asec_failed_nomedia"
#define ASEC_EVENT_FAILED_BADMEDIA "asec_failed_badmedia:"
#define ASEC_EVENT_FAILED_BADKEY "asec_failed_badkey:"
/*
* System Properties
*/
#define ASEC_ENABLED "asec.enabled"
#define ASEC_STATUS "ro.asec.status"
#define ASEC_STATUS_DISABLED "disabled"
#define ASEC_STATUS_AVAILABLE "available"
#define ASEC_STATUS_BUSY "busy"
#define ASEC_STATUS_FAILED_INTERR "internal_error"
#define ASEC_STATUS_FAILED_NOMEDIA "no_media"
#define ASEC_STATUS_FAILED_BADMEDIA "bad_media"
#define ASEC_STATUS_FAILED_BADKEY "bad_key"
#endif

View File

@ -1,22 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
AutoMount.c \
ProcessKiller.c \
Server.c \
mountd.c \
ASEC.c \
logwrapper.c
LOCAL_MODULE:= mountd
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_CFLAGS := -DCREATE_MOUNT_POINTS=0
LOCAL_SHARED_LIBRARIES := libcutils
# disabled - we are using vold now instead
# include $(BUILD_EXECUTABLE)

File diff suppressed because it is too large Load Diff

View File

@ -1,190 +0,0 @@
Copyright (c) 2005-2008, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,222 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
/*
** mountd process killer
*/
#include "mountd.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <pwd.h>
#include <stdlib.h>
#include <poll.h>
#include <sys/stat.h>
static boolean ReadSymLink(const char* path, char* link)
{
struct stat s;
int length;
if (lstat(path, &s) < 0)
return false;
if ((s.st_mode & S_IFMT) != S_IFLNK)
return false;
// we have a symlink
length = readlink(path, link, PATH_MAX - 1);
if (length <= 0)
return false;
link[length] = 0;
return true;
}
static boolean PathMatchesMountPoint(const char* path, const char* mountPoint)
{
int length = strlen(mountPoint);
if (length > 1 && strncmp(path, mountPoint, length) == 0)
{
// we need to do extra checking if mountPoint does not end in a '/'
if (mountPoint[length - 1] == '/')
return true;
// if mountPoint does not have a trailing slash, we need to make sure
// there is one in the path to avoid partial matches.
return (path[length] == 0 || path[length] == '/');
}
return false;
}
static void GetProcessName(int pid, char buffer[PATH_MAX])
{
int fd;
sprintf(buffer, "/proc/%d/cmdline", pid);
fd = open(buffer, O_RDONLY);
if (fd < 0) {
strcpy(buffer, "???");
} else {
int length = read(fd, buffer, PATH_MAX - 1);
buffer[length] = 0;
close(fd);
}
}
static boolean CheckFileDescriptorSymLinks(int pid, const char* mountPoint)
{
DIR* dir;
struct dirent* de;
boolean fileOpen = false;
char path[PATH_MAX];
char link[PATH_MAX];
int parent_length;
// compute path to process's directory of open files
sprintf(path, "/proc/%d/fd", pid);
dir = opendir(path);
if (!dir)
return false;
// remember length of the path
parent_length = strlen(path);
// append a trailing '/'
path[parent_length++] = '/';
while ((de = readdir(dir)) != 0 && !fileOpen) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
// append the file name, after truncating to parent directory
path[parent_length] = 0;
strcat(path, de->d_name);
if (ReadSymLink(path, link) && PathMatchesMountPoint(link, mountPoint))
{
char name[PATH_MAX];
GetProcessName(pid, name);
LOG_ERROR("process %s (%d) has open file %s\n", name, pid, link);
fileOpen = true;
}
}
closedir(dir);
return fileOpen;
}
static boolean CheckFileMaps(int pid, const char* mountPoint)
{
FILE* file;
char buffer[PATH_MAX + 100];
boolean mapOpen = false;
sprintf(buffer, "/proc/%d/maps", pid);
file = fopen(buffer, "r");
if (!file)
return false;
while (!mapOpen && fgets(buffer, sizeof(buffer), file))
{
// skip to the path
const char* path = strchr(buffer, '/');
if (path && PathMatchesMountPoint(path, mountPoint))
{
char name[PATH_MAX];
GetProcessName(pid, name);
LOG_ERROR("process %s (%d) has open file map for %s\n", name, pid, path);
mapOpen = true;
}
}
fclose(file);
return mapOpen;
}
static boolean CheckSymLink(int pid, const char* mountPoint, const char* name, const char* message)
{
char path[PATH_MAX];
char link[PATH_MAX];
sprintf(path, "/proc/%d/%s", pid, name);
if (ReadSymLink(path, link) && PathMatchesMountPoint(link, mountPoint))
{
char name[PATH_MAX];
GetProcessName(pid, name);
LOG_ERROR("process %s (%d) has %s in %s\n", name, pid, message, mountPoint);
return true;
}
else
return false;
}
static int get_pid(const char* s)
{
int result = 0;
while (*s) {
if (!isdigit(*s)) return -1;
result = 10 * result + (*s++ - '0');
}
return result;
}
// hunt down and kill processes that have files open on the given mount point
void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded)
{
DIR* dir;
struct dirent* de;
LOG_ERROR("KillProcessesWithOpenFiles %s\n", mountPoint);
dir = opendir("/proc");
if (!dir) return;
while ((de = readdir(dir)) != 0)
{
boolean killed = false;
// does the name look like a process ID?
int pid = get_pid(de->d_name);
if (pid == -1) continue;
if (CheckFileDescriptorSymLinks(pid, mountPoint) // check for open files
|| CheckFileMaps(pid, mountPoint) // check for mmap()
|| CheckSymLink(pid, mountPoint, "cwd", "working directory") // check working directory
|| CheckSymLink(pid, mountPoint, "root", "chroot") // check for chroot()
|| CheckSymLink(pid, mountPoint, "exe", "executable path") // check executable path
)
{
int i;
boolean hit = false;
for (i = 0; i < num_excluded; i++) {
if (pid == excluded[i]) {
LOG_ERROR("I just need a little more TIME captain!\n");
hit = true;
break;
}
}
if (!hit) {
LOG_ERROR("Killing process %d\n", pid);
kill(pid, (sigkill ? SIGKILL : SIGTERM));
}
}
}
closedir(dir);
}

View File

@ -1,313 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
/*
** mountd server support
*/
#include "mountd.h"
#include "ASEC.h"
#include <cutils/properties.h>
#include <cutils/sockets.h>
#include <pthread.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <private/android_filesystem_config.h>
// current client file descriptor
static int sFD = -1;
// to synchronize writing to client
static pthread_mutex_t sWriteMutex = PTHREAD_MUTEX_INITIALIZER;
// path for media that failed to mount before the runtime is connected
static char* sDeferredUnmountableMediaPath = NULL;
// last asec msg before the runtime was connected
static char* sAsecDeferredMessage = NULL;
static char* sAsecDeferredArgument = NULL;
static int Write(const char* message)
{
int result = -1;
pthread_mutex_lock(&sWriteMutex);
LOG_SERVER("Write: %s\n", message);
if (sFD >= 0)
result = write(sFD, message, strlen(message) + 1);
pthread_mutex_unlock(&sWriteMutex);
return result;
}
static int Write2(const char* message, const char* data)
{
int result = -1;
char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
if (!buffer)
{
LOG_ERROR("alloca failed in Write2\n");
return -1;
}
strcpy(buffer, message);
strcat(buffer, data);
return Write(buffer);
}
static void SendStatus()
{
Write(IsMassStorageConnected() ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED);
Write(IsMassStorageEnabled() ? MOUNTD_UMS_ENABLED : MOUNTD_UMS_DISABLED);
}
static void DoCommand(const char* command)
{
LOG_SERVER("DoCommand %s\n", command);
if (strcmp(command, MOUNTD_ENABLE_UMS) == 0)
{
EnableMassStorage(true);
Write(MOUNTD_UMS_ENABLED);
}
else if (strcmp(command, MOUNTD_DISABLE_UMS) == 0)
{
EnableMassStorage(false);
Write(MOUNTD_UMS_DISABLED);
}
else if (strcmp(command, MOUNTD_SEND_STATUS) == 0)
{
SendStatus();
}
else if (strncmp(command, MOUNTD_MOUNT_MEDIA, strlen(MOUNTD_MOUNT_MEDIA)) == 0)
{
const char* path = command + strlen(MOUNTD_MOUNT_MEDIA);
MountMedia(path);
}
else if (strncmp(command, MOUNTD_EJECT_MEDIA, strlen(MOUNTD_EJECT_MEDIA)) == 0)
{
const char* path = command + strlen(MOUNTD_EJECT_MEDIA);
UnmountMedia(path);
}
else if (strncmp(command, ASEC_CMD_ENABLE, strlen(ASEC_CMD_ENABLE)) == 0) {
LOG_ASEC("Got ASEC_CMD_ENABLE\n");
// XXX: SAN: Impliment
}
else if (strncmp(command, ASEC_CMD_DISABLE, strlen(ASEC_CMD_DISABLE)) == 0) {
LOG_ASEC("Got ASEC_CMD_DISABLE\n");
// XXX: SAN: Impliment
}
else if (strncmp(command, ASEC_CMD_SEND_STATUS, strlen(ASEC_CMD_SEND_STATUS)) == 0) {
LOG_ASEC("Got ASEC_CMD_SEND_STATUS\n");
// XXX: SAN: Impliment
}
else
LOGE("unknown command %s\n", command);
}
int RunServer()
{
int socket = android_get_control_socket(MOUNTD_SOCKET);
if (socket < 0) {
LOGE("Obtaining file descriptor for socket '%s' failed: %s",
MOUNTD_SOCKET, strerror(errno));
return -1;
}
if (listen(socket, 4) < 0) {
LOGE("Unable to listen on file descriptor '%d' for socket '%s': %s",
socket, MOUNTD_SOCKET, strerror(errno));
return -1;
}
while (1)
{
struct sockaddr addr;
socklen_t alen;
struct ucred cred;
socklen_t size;
alen = sizeof(addr);
sFD = accept(socket, &addr, &alen);
if (sFD < 0)
continue;
if (sDeferredUnmountableMediaPath) {
NotifyMediaState(sDeferredUnmountableMediaPath, MEDIA_UNMOUNTABLE, false);
free(sDeferredUnmountableMediaPath);
sDeferredUnmountableMediaPath = NULL;
}
if (sAsecDeferredMessage) {
if (Write2(sAsecDeferredMessage, sAsecDeferredArgument) < 0)
LOG_ERROR("Failed to deliver deferred ASEC msg to framework\n");
free(sAsecDeferredMessage);
free(sAsecDeferredArgument);
sAsecDeferredMessage = sAsecDeferredArgument = NULL;
}
while (1)
{
char buffer[101];
int result = read(sFD, buffer, sizeof(buffer) - 1);
if (result > 0)
{
int start = 0;
int i;
// command should be zero terminated, but just in case
buffer[result] = 0;
for (i = 0; i < result; i++)
{
if (buffer[i] == 0)
{
DoCommand(buffer + start);
start = i + 1;
}
}
}
else
{
close(sFD);
sFD = -1;
break;
}
}
}
// should never get here
return 0;
}
void SendMassStorageConnected(boolean connected)
{
Write(connected ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED);
}
void SendUnmountRequest(const char* path)
{
Write2(MOUNTD_REQUEST_EJECT, path);
}
void NotifyAsecState(AsecState state, const char *argument)
{
const char *event = NULL;
const char *status = NULL;
boolean deferr = true;;
switch (state) {
case ASEC_DISABLED:
event = ASEC_EVENT_DISABLED;
status = ASEC_STATUS_DISABLED;
break;
case ASEC_AVAILABLE:
event = ASEC_EVENT_AVAILABLE;
status = ASEC_STATUS_AVAILABLE;
break;
case ASEC_BUSY:
event = ASEC_EVENT_BUSY;
status = ASEC_STATUS_BUSY;
deferr = false;
break;
case ASEC_FAILED_INTERR:
event = ASEC_EVENT_FAILED_INTERR;
status = ASEC_STATUS_FAILED_INTERR;
break;
case ASEC_FAILED_NOMEDIA:
event = ASEC_EVENT_FAILED_NOMEDIA;
status = ASEC_STATUS_FAILED_NOMEDIA;
break;
case ASEC_FAILED_BADMEDIA:
event = ASEC_EVENT_FAILED_BADMEDIA;
status = ASEC_STATUS_FAILED_BADMEDIA;
break;
case ASEC_FAILED_BADKEY:
event = ASEC_EVENT_FAILED_BADKEY;
status = ASEC_STATUS_FAILED_BADKEY;
break;
default:
LOG_ERROR("unknown AsecState %d in NotifyAsecState\n", state);
return;
}
property_set(ASEC_STATUS, status);
int result = Write2(event, argument);
if ((result < 0) && deferr) {
if (sAsecDeferredMessage)
free(sAsecDeferredMessage);
sAsecDeferredMessage = strdup(event);
if (sAsecDeferredArgument)
free(sAsecDeferredArgument);
sAsecDeferredArgument = strdup(argument);
LOG_ASEC("Deferring event '%s' arg '%s' until framework connects\n", event, argument);
}
}
void NotifyMediaState(const char* path, MediaState state, boolean readOnly)
{
const char* event = NULL;
const char* propertyValue = NULL;
switch (state) {
case MEDIA_REMOVED:
event = MOUNTD_MEDIA_REMOVED;
propertyValue = EXTERNAL_STORAGE_REMOVED;
break;
case MEDIA_UNMOUNTED:
event = MOUNTD_MEDIA_UNMOUNTED;
propertyValue = EXTERNAL_STORAGE_UNMOUNTED;
break;
case MEDIA_MOUNTED:
event = (readOnly ? MOUNTD_MEDIA_MOUNTED_READ_ONLY : MOUNTD_MEDIA_MOUNTED);
propertyValue = (readOnly ? EXTERNAL_STORAGE_MOUNTED_READ_ONLY : EXTERNAL_STORAGE_MOUNTED);
break;
case MEDIA_SHARED:
event = MOUNTD_MEDIA_SHARED;
propertyValue = EXTERNAL_STORAGE_SHARED;
break;
case MEDIA_BAD_REMOVAL:
event = MOUNTD_MEDIA_BAD_REMOVAL;
propertyValue = EXTERNAL_STORAGE_BAD_REMOVAL;
break;
case MEDIA_UNMOUNTABLE:
event = MOUNTD_MEDIA_UNMOUNTABLE;
propertyValue = EXTERNAL_STORAGE_UNMOUNTABLE;
break;
default:
LOG_ERROR("unknown MediaState %d in NotifyMediaState\n", state);
return;
}
property_set(EXTERNAL_STORAGE_STATE, propertyValue);
int result = Write2(event, path);
if (result < 0 && state == MEDIA_UNMOUNTABLE) {
// if we cannot communicate with the runtime, defer this message until the runtime is available
sDeferredUnmountableMediaPath = strdup(path);
}
}

View File

@ -1,154 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "private/android_filesystem_config.h"
#include "cutils/log.h"
int parent(const char *tag, int parent_read) {
int status;
char buffer[4096];
int a = 0; // start index of unprocessed data
int b = 0; // end index of unprocessed data
int sz;
while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
sz += b;
// Log one line at a time
for (b = 0; b < sz; b++) {
if (buffer[b] == '\r') {
buffer[b] = '\0';
} else if (buffer[b] == '\n') {
buffer[b] = '\0';
LOG(LOG_INFO, tag, &buffer[a]);
a = b + 1;
}
}
if (a == 0 && b == sizeof(buffer) - 1) {
// buffer is full, flush
buffer[b] = '\0';
LOG(LOG_INFO, tag, &buffer[a]);
b = 0;
} else if (a != b) {
// Keep left-overs
b -= a;
memmove(buffer, &buffer[a], b);
a = 0;
} else {
a = 0;
b = 0;
}
}
// Flush remaining data
if (a != b) {
buffer[b] = '\0';
LOG(LOG_INFO, tag, &buffer[a]);
}
status = 0xAAAA;
if (wait(&status) != -1) { // Wait for child
if (WIFEXITED(status)) {
LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
WEXITSTATUS(status));
return WEXITSTATUS(status);
} else if (WIFSIGNALED(status))
LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
WTERMSIG(status));
else if (WIFSTOPPED(status))
LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
WSTOPSIG(status));
} else
LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
strerror(errno), errno);
return -EAGAIN;
}
void child(int argc, char* argv[]) {
// create null terminated argv_child array
char* argv_child[argc + 1];
memcpy(argv_child, argv, argc * sizeof(char *));
argv_child[argc] = NULL;
// XXX: PROTECT FROM VIKING KILLER
if (execvp(argv_child[0], argv_child)) {
LOG(LOG_ERROR, "logwrapper",
"executing %s failed: %s\n", argv_child[0], strerror(errno));
exit(-1);
}
}
int logwrap(int argc, char* argv[])
{
pid_t pid;
int parent_ptty;
int child_ptty;
char *child_devname = NULL;
/* Use ptty instead of socketpair so that STDOUT is not buffered */
parent_ptty = open("/dev/ptmx", O_RDWR);
if (parent_ptty < 0) {
LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty\n");
return -errno;
}
if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx\n");
return -1;
}
pid = fork();
if (pid < 0) {
LOG(LOG_ERROR, "logwrapper", "Failed to fork\n");
return -errno;
} else if (pid == 0) {
child_ptty = open(child_devname, O_RDWR);
if (child_ptty < 0) {
LOG(LOG_ERROR, "logwrapper", "Problem with child ptty\n");
return -errno;
}
// redirect stdout and stderr
close(parent_ptty);
dup2(child_ptty, 1);
dup2(child_ptty, 2);
close(child_ptty);
child(argc, argv);
} else {
// switch user and group to "log"
// this may fail if we are not root,
// but in that case switching user/group is unnecessary
// setgid(AID_LOG);
// setuid(AID_LOG);
return parent(argv[0], parent_ptty);
}
return 0;
}

View File

@ -1,174 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
/*
** mountd main program
*/
#include "mountd.h"
#include <cutils/config_utils.h>
#include <cutils/cpu_info.h>
#include <cutils/properties.h>
#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/capability.h>
#include <linux/prctl.h>
#include <private/android_filesystem_config.h>
#ifdef MOUNTD_LOG
FILE* logFile;
#endif
struct asec_cfg {
const char *name;
const char *backing_file;
const char *size;
const char *mount_point;
const char *crypt;
};
static int ProcessAsecData(cnode *node, struct asec_cfg *stores, int idx)
{
cnode *child = node->first_child;
const char *name = NULL;
const char *file = NULL;
const char *size = NULL;
const char *mp = NULL;
const char *crypt = NULL;
LOG_ASEC("ProcessAsecData(%s, %p, %d)\n", node->name, stores, idx);
while (child) {
if (!strcmp(child->name, "name"))
name = child->value;
else if (!strcmp(child->name, "backing_file"))
file = child->value;
else if (!strcmp(child->name, "size"))
size = child->value;
else if (!strcmp(child->name, "mount_point"))
mp = child->value;
else if (!strcmp(child->name, "crypt"))
crypt = child->value;
child = child->next;
}
if (!name || !file || !size || !mp || !crypt) {
LOG_ERROR("Missing required token from config. Skipping ASEC volume\n");
return -1;
} else if (idx == ASEC_STORES_MAX) {
LOG_ERROR("Maximum # of ASEC stores already defined\n");
return -1;
}
stores[idx].name = name;
stores[idx].backing_file = file;
stores[idx].size = size;
stores[idx].mount_point = mp;
stores[idx].crypt = crypt;
return ++idx;
}
static void ReadConfigFile(const char* path)
{
cnode* root = config_node("", "");
cnode* node;
config_load_file(root, path);
node = root->first_child;
while (node)
{
if (strcmp(node->name, "mount") == 0)
{
const char* block_device = NULL;
const char* mount_point = NULL;
const char* driver_store_path = NULL;
boolean enable_ums = false;
cnode* child = node->first_child;
struct asec_cfg asec_stores[ASEC_STORES_MAX];
int asec_idx = 0;
memset(asec_stores, 0, sizeof(asec_stores));
while (child)
{
const char* name = child->name;
const char* value = child->value;
if (!strncmp(name, "asec_", 5)) {
int rc = ProcessAsecData(child, asec_stores, asec_idx);
if (rc < 0) {
LOG_ERROR("Error processing ASEC cfg data\n");
} else
asec_idx = rc;
} else if (strcmp(name, "block_device") == 0)
block_device = value;
else if (strcmp(name, "mount_point") == 0)
mount_point = value;
else if (strcmp(name, "driver_store_path") == 0)
driver_store_path = value;
else if (strcmp(name, "enable_ums") == 0 &&
strcmp(value, "true") == 0)
enable_ums = true;
child = child->next;
}
// mount point and removable fields are optional
if (block_device && mount_point)
{
void *mp = AddMountPoint(block_device, mount_point, driver_store_path, enable_ums);
int i;
for (i = 0; i < asec_idx; i++) {
AddAsecToMountPoint(mp, asec_stores[i].name, asec_stores[i].backing_file,
asec_stores[i].size, asec_stores[i].mount_point,
asec_stores[i].crypt);
}
}
}
node = node->next;
}
}
int main(int argc, char* argv[])
{
const char* configPath = "/system/etc/mountd.conf";
int i;
for (i = 1; i < argc; i++)
{
const char* arg = argv[i];
if (strcmp(arg, "-f") == 0)
{
if (i < argc - 1)
configPath = argv[++i];
}
}
ReadConfigFile(configPath);
StartAutoMounter();
return RunServer();
}

View File

@ -1,190 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef MOUNTD_H__
#define MOUNTD_H__
#define LOG_TAG "mountd"
#include "cutils/log.h"
#include "ASEC.h"
typedef int boolean;
enum {
false = 0,
true = 1
};
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
// Set this for logging error messages
#define ENABLE_LOG_ERROR
// set this to log automounter events
#define ENABLE_LOG_MOUNT
// set this to log server events
//#define ENABLE_LOG_SERVER
// set this to log ASEC events
#define ENABLE_LOG_ASEC
#ifdef ENABLE_LOG_ERROR
#define LOG_ERROR(fmt, args...) \
{ LOGE(fmt , ## args); }
#else
#define LOG_ERROR(fmt, args...) \
do { } while (0)
#endif /* ENABLE_LOG_ERROR */
#ifdef ENABLE_LOG_MOUNT
#define LOG_MOUNT(fmt, args...) \
{ LOGD(fmt , ## args); }
#else
#define LOG_MOUNT(fmt, args...) \
do { } while (0)
#endif /* ENABLE_LOG_MOUNT */
#ifdef ENABLE_LOG_SERVER
#define LOG_SERVER(fmt, args...) \
{ LOGD(fmt , ## args); }
#else
#define LOG_SERVER(fmt, args...) \
do { } while (0)
#endif /* ENABLE_LOG_SERVER */
#ifdef ENABLE_LOG_ASEC
#define LOG_ASEC(fmt, args...) \
{ LOGD(fmt , ## args); }
#else
#define LOG_ASEC(fmt, args...) \
do { } while (0)
#endif /* ENABLE_LOG_ASEC */
typedef enum MediaState {
// no media in SD card slot
MEDIA_REMOVED,
// media in SD card slot, but not mounted
MEDIA_UNMOUNTED,
// media in SD card slot and mounted at its mount point
MEDIA_MOUNTED,
// media in SD card slot, unmounted, and shared as a mass storage device
MEDIA_SHARED,
// media was removed from SD card slot, but mount point was not unmounted
// this state is cleared after the mount point is unmounted
MEDIA_BAD_REMOVAL,
// media in SD card slot could not be mounted (corrupt file system?)
MEDIA_UNMOUNTABLE,
} MediaState;
// socket name for connecting to mountd
#define MOUNTD_SOCKET "mountd"
// mountd commands
// these must match the corresponding strings in //device/java/android/android/os/UsbListener.java
#define MOUNTD_ENABLE_UMS "enable_ums"
#define MOUNTD_DISABLE_UMS "disable_ums"
#define MOUNTD_SEND_STATUS "send_status"
// these commands should contain a mount point following the colon
#define MOUNTD_MOUNT_MEDIA "mount_media:"
#define MOUNTD_EJECT_MEDIA "eject_media:"
// mountd events
// these must match the corresponding strings in //device/java/android/android/os/UsbListener.java
#define MOUNTD_UMS_ENABLED "ums_enabled"
#define MOUNTD_UMS_DISABLED "ums_disabled"
#define MOUNTD_UMS_CONNECTED "ums_connected"
#define MOUNTD_UMS_DISCONNECTED "ums_disconnected"
// these events correspond to the states in the MediaState enum.
// a path to the mount point follows the colon.
#define MOUNTD_MEDIA_REMOVED "media_removed:"
#define MOUNTD_MEDIA_UNMOUNTED "media_unmounted:"
#define MOUNTD_MEDIA_MOUNTED "media_mounted:"
#define MOUNTD_MEDIA_MOUNTED_READ_ONLY "media_mounted_ro:"
#define MOUNTD_MEDIA_SHARED "media_shared:"
#define MOUNTD_MEDIA_BAD_REMOVAL "media_bad_removal:"
#define MOUNTD_MEDIA_UNMOUNTABLE "media_unmountable:"
// this event sent to request unmount for media mount point
#define MOUNTD_REQUEST_EJECT "request_eject:"
// system properties
// these must match the corresponding strings in //device/java/android/android/os/Environment.java
#define EXTERNAL_STORAGE_STATE "EXTERNAL_STORAGE_STATE"
#define EXTERNAL_STORAGE_REMOVED "removed"
#define EXTERNAL_STORAGE_UNMOUNTED "unmounted"
#define EXTERNAL_STORAGE_MOUNTED "mounted"
#define EXTERNAL_STORAGE_MOUNTED_READ_ONLY "mounted_ro"
#define EXTERNAL_STORAGE_SHARED "shared"
#define EXTERNAL_STORAGE_BAD_REMOVAL "bad_removal"
#define EXTERNAL_STORAGE_UNMOUNTABLE "unmountable"
// AutoMount.c
boolean IsMassStorageEnabled();
boolean IsMassStorageConnected();
void MountMedia(const char* mountPoint);
void UnmountMedia(const char* mountPoint);
void EnableMassStorage(boolean enable);
// call this before StartAutoMounter() to add a mount point to monitor
void *AddMountPoint(const char* device, const char* mountPoint, const char* driverStorePath,
boolean enableUms);
int AddAsecToMountPoint(void *Mp, const char *name, const char *backing_file,
const char *size, const char *mount_point, const char *crypt);
// start automounter thread
void StartAutoMounter();
// check /proc/mounts for mounted file systems, and notify mount or unmount for any that are in our automount list
void NotifyExistingMounts();
// ASEC.c
void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile,
const char *Size, const char *DstPath, const char *Crypt);
int AsecStart(void *Handle);
int AsecStop(void *Handle);
void AsecDeinit(void *Handle);
boolean AsecIsStarted(void *Handle);
const char *AsecMountPoint(void *Handle);
// ProcessKiller.c
void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, pid_t *excluded, int num_excluded);
// logwrapper.c
int logwrap(int argc, char* argv[]);
// Server.c
int RunServer();
void SendMassStorageConnected(boolean connected);
void SendUnmountRequest(const char* path);
void NotifyMediaState(const char* path, MediaState state, boolean readOnly);
void NotifyAsecState(AsecState state, const char *argument);
#endif // MOUNTD_H__

64
nexus/Android.mk Normal file
View File

@ -0,0 +1,64 @@
BUILD_NEXUS := false
ifeq ($(BUILD_NEXUS),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
main.cpp \
NetworkManager.cpp \
CommandListener.cpp \
Controller.cpp \
WifiController.cpp \
LoopController.cpp \
NexusCommand.cpp \
TiwlanWifiController.cpp \
Supplicant.cpp \
SupplicantEvent.cpp \
SupplicantListener.cpp \
VpnController.cpp \
ScanResult.cpp \
WifiScanner.cpp \
WifiNetwork.cpp \
OpenVpnController.cpp \
InterfaceConfig.cpp \
PropertyManager.cpp \
SupplicantState.cpp \
SupplicantEventFactory.cpp \
SupplicantConnectedEvent.cpp \
SupplicantAssociatingEvent.cpp \
SupplicantAssociatedEvent.cpp \
SupplicantStateChangeEvent.cpp \
SupplicantScanResultsEvent.cpp \
SupplicantConnectionTimeoutEvent.cpp \
SupplicantDisconnectedEvent.cpp \
SupplicantStatus.cpp \
TiwlanEventListener.cpp \
DhcpClient.cpp DhcpListener.cpp \
LOCAL_MODULE:= nexus
LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -I../../../frameworks/base/include/
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libsysutils libwpa_client
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
nexctl.c \
LOCAL_MODULE:= nexctl
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
endif # ifeq ($(BUILD_NEXUS),true)

231
nexus/CommandListener.cpp Normal file
View File

@ -0,0 +1,231 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#define LOG_TAG "CommandListener"
#include <cutils/log.h>
#include <sysutils/SocketClient.h>
#include "CommandListener.h"
#include "Controller.h"
#include "Property.h"
#include "NetworkManager.h"
#include "WifiController.h"
#include "VpnController.h"
#include "ErrorCode.h"
CommandListener::CommandListener() :
FrameworkListener("nexus") {
registerCmd(new WifiScanResultsCmd());
registerCmd(new WifiListNetworksCmd());
registerCmd(new WifiCreateNetworkCmd());
registerCmd(new WifiRemoveNetworkCmd());
registerCmd(new GetCmd());
registerCmd(new SetCmd());
registerCmd(new ListCmd());
}
/* -------------
* Wifi Commands
* ------------ */
CommandListener::WifiCreateNetworkCmd::WifiCreateNetworkCmd() :
NexusCommand("wifi_create_network") {
}
int CommandListener::WifiCreateNetworkCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
NetworkManager *nm = NetworkManager::Instance();
WifiController *wc = (WifiController *) nm->findController("WIFI");
WifiNetwork *wn;
if (!(wn = wc->createNetwork()))
cli->sendMsg(ErrorCode::OperationFailed, "Failed to create network", true);
else {
char tmp[128];
sprintf(tmp, "Created network id %d.", wn->getNetworkId());
cli->sendMsg(ErrorCode::CommandOkay, tmp, false);
}
return 0;
}
CommandListener::WifiRemoveNetworkCmd::WifiRemoveNetworkCmd() :
NexusCommand("wifi_remove_network") {
}
int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
NetworkManager *nm = NetworkManager::Instance();
WifiController *wc = (WifiController *) nm->findController("WIFI");
if (wc->removeNetwork(atoi(argv[1])))
cli->sendMsg(ErrorCode::OperationFailed, "Failed to remove network", true);
else {
cli->sendMsg(ErrorCode::CommandOkay, "Network removed.", false);
}
return 0;
}
CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() :
NexusCommand("wifi_scan_results") {
}
int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
NetworkManager *nm = NetworkManager::Instance();
WifiController *wc = (WifiController *) nm->findController("WIFI");
ScanResultCollection *src = wc->createScanResults();
ScanResultCollection::iterator it;
char buffer[256];
for(it = src->begin(); it != src->end(); ++it) {
sprintf(buffer, "%s:%u:%d:%s:%s",
(*it)->getBssid(), (*it)->getFreq(), (*it)->getLevel(),
(*it)->getFlags(), (*it)->getSsid());
cli->sendMsg(ErrorCode::WifiScanResult, buffer, false);
delete (*it);
it = src->erase(it);
}
delete src;
cli->sendMsg(ErrorCode::CommandOkay, "Scan results complete.", false);
return 0;
}
CommandListener::WifiListNetworksCmd::WifiListNetworksCmd() :
NexusCommand("wifi_list_networks") {
}
int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
NetworkManager *nm = NetworkManager::Instance();
WifiController *wc = (WifiController *) nm->findController("WIFI");
WifiNetworkCollection *src = wc->createNetworkList();
WifiNetworkCollection::iterator it;
char buffer[256];
for(it = src->begin(); it != src->end(); ++it) {
sprintf(buffer, "%d:%s", (*it)->getNetworkId(), (*it)->getSsid());
cli->sendMsg(ErrorCode::WifiNetworkList, buffer, false);
delete (*it);
}
delete src;
cli->sendMsg(ErrorCode::CommandOkay, "Network listing complete.", false);
return 0;
}
/* ------------
* Vpn Commands
* ------------ */
/* ----------------
* Generic Commands
* ---------------- */
CommandListener::GetCmd::GetCmd() :
NexusCommand("get") {
}
int CommandListener::GetCmd::runCommand(SocketClient *cli, int argc, char **argv) {
char val[Property::ValueMaxSize];
if (!NetworkManager::Instance()->getPropMngr()->get(argv[1],
val,
sizeof(val))) {
goto out_inval;
}
char *tmp;
asprintf(&tmp, "%s %s", argv[1], val);
cli->sendMsg(ErrorCode::PropertyRead, tmp, false);
free(tmp);
cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false);
return 0;
out_inval:
errno = EINVAL;
cli->sendMsg(ErrorCode::CommandParameterError, "Failed to read property.", true);
return 0;
}
CommandListener::SetCmd::SetCmd() :
NexusCommand("set") {
}
int CommandListener::SetCmd::runCommand(SocketClient *cli, int argc,
char **argv) {
if (NetworkManager::Instance()->getPropMngr()->set(argv[1], argv[2]))
goto out_inval;
cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false);
return 0;
out_inval:
errno = EINVAL;
cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set property.", true);
return 0;
}
CommandListener::ListCmd::ListCmd() :
NexusCommand("list") {
}
int CommandListener::ListCmd::runCommand(SocketClient *cli, int argc, char **argv) {
android::List<char *> *pc;
if (!(pc = NetworkManager::Instance()->getPropMngr()->createPropertyList())) {
errno = ENODATA;
cli->sendMsg(ErrorCode::CommandParameterError, "Failed to list properties.", true);
return 0;
}
android::List<char *>::iterator it;
for (it = pc->begin(); it != pc->end(); ++it) {
char p_v[Property::ValueMaxSize];
if (!NetworkManager::Instance()->getPropMngr()->get((*it),
p_v,
sizeof(p_v))) {
LOGW("Failed to get %s (%s)", (*it), strerror(errno));
}
char *buf;
if (asprintf(&buf, "%s %s", (*it), p_v) < 0) {
LOGE("Failed to allocate memory");
free((*it));
continue;
}
cli->sendMsg(ErrorCode::PropertyList, buf, false);
free(buf);
free((*it));
}
delete pc;
cli->sendMsg(ErrorCode::CommandOkay, "Properties list complete.", false);
return 0;
}

87
nexus/CommandListener.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _COMMANDLISTENER_H__
#define _COMMANDLISTENER_H__
#include <sysutils/FrameworkListener.h>
#include "NexusCommand.h"
class CommandListener : public FrameworkListener {
public:
CommandListener();
virtual ~CommandListener() {}
private:
class WifiScanCmd : public NexusCommand {
public:
WifiScanCmd();
virtual ~WifiScanCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class WifiScanResultsCmd : public NexusCommand {
public:
WifiScanResultsCmd();
virtual ~WifiScanResultsCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class WifiCreateNetworkCmd : public NexusCommand {
public:
WifiCreateNetworkCmd();
virtual ~WifiCreateNetworkCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class WifiRemoveNetworkCmd : public NexusCommand {
public:
WifiRemoveNetworkCmd();
virtual ~WifiRemoveNetworkCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class WifiListNetworksCmd : public NexusCommand {
public:
WifiListNetworksCmd();
virtual ~WifiListNetworksCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class SetCmd : public NexusCommand {
public:
SetCmd();
virtual ~SetCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class GetCmd : public NexusCommand {
public:
GetCmd();
virtual ~GetCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
class ListCmd : public NexusCommand {
public:
ListCmd();
virtual ~ListCmd() {}
int runCommand(SocketClient *c, int argc, char ** argv);
};
};
#endif

176
nexus/Controller.cpp Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define LOG_TAG "Controller"
#include <cutils/log.h>
#include "Controller.h"
extern "C" int init_module(void *, unsigned int, const char *);
extern "C" int delete_module(const char *, unsigned int);
Controller::Controller(const char *name, PropertyManager *propMngr,
IControllerHandler *handlers) {
mPropMngr = propMngr;
mName = strdup(name);
mHandlers = handlers;
mBoundInterface = NULL;
}
Controller::~Controller() {
if (mBoundInterface)
free(mBoundInterface);
if (mName)
free(mName);
}
int Controller::start() {
return 0;
}
int Controller::stop() {
return 0;
}
int Controller::set(const char *name, const char *value) {
errno = ENOENT;
return -1;
}
const char *Controller::get(const char *name, char *buffer, size_t maxsize) {
errno = ENOENT;
return NULL;
}
int Controller::loadKernelModule(char *modpath, const char *args) {
void *module;
unsigned int size;
module = loadFile(modpath, &size);
if (!module) {
errno = -EIO;
return -1;
}
int rc = init_module(module, size, args);
free (module);
return rc;
}
int Controller::unloadKernelModule(const char *modtag) {
int rc = -1;
int retries = 10;
while (retries--) {
rc = delete_module(modtag, O_NONBLOCK | O_EXCL);
if (rc < 0 && errno == EAGAIN)
usleep(1000*500);
else
break;
}
if (rc != 0) {
LOGW("Unable to unload kernel driver '%s' (%s)", modtag,
strerror(errno));
}
return rc;
}
bool Controller::isKernelModuleLoaded(const char *modtag) {
FILE *fp = fopen("/proc/modules", "r");
if (!fp) {
LOGE("Unable to open /proc/modules (%s)", strerror(errno));
return false;
}
char line[255];
while(fgets(line, sizeof(line), fp)) {
char *endTag = strchr(line, ' ');
if (!endTag) {
LOGW("Unable to find tag for line '%s'", line);
continue;
}
if (!strncmp(line, modtag, (endTag - line))) {
fclose(fp);
return true;
}
}
fclose(fp);
return false;
}
void *Controller::loadFile(char *filename, unsigned int *_size)
{
int ret, fd;
struct stat sb;
ssize_t size;
void *buffer = NULL;
/* open the file */
fd = open(filename, O_RDONLY);
if (fd < 0)
return NULL;
/* find out how big it is */
if (fstat(fd, &sb) < 0)
goto bail;
size = sb.st_size;
/* allocate memory for it to be read into */
buffer = malloc(size);
if (!buffer)
goto bail;
/* slurp it into our buffer */
ret = read(fd, buffer, size);
if (ret != size)
goto bail;
/* let the caller know how big it is */
*_size = size;
bail:
close(fd);
return buffer;
}
int Controller::bindInterface(const char *ifname) {
mBoundInterface = strdup(ifname);
LOGD("Controller %s bound to %s", mName, ifname);
return 0;
}
int Controller::unbindInterface(const char *ifname) {
free(mBoundInterface);
mBoundInterface = NULL;
LOGD("Controller %s unbound from %s", mName, ifname);
return 0;
}

74
nexus/Controller.h Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _CONTROLLER_H
#define _CONTROLLER_H
#include <unistd.h>
#include <sys/types.h>
#include <utils/List.h>
class PropertyManager;
class IControllerHandler;
#include "PropertyManager.h"
#include "IPropertyProvider.h"
class Controller : public IPropertyProvider {
/*
* Name of this controller - WIFI/VPN/USBNET/BTNET/BTDUN/LOOP/etc
*/
char *mName;
/*
* Name of the system ethernet interface which this controller is
* bound to.
*/
char *mBoundInterface;
protected:
PropertyManager *mPropMngr;
IControllerHandler *mHandlers;
public:
Controller(const char *name, PropertyManager *propMngr,
IControllerHandler *handlers);
virtual ~Controller();
virtual int start();
virtual int stop();
const char *getName() { return mName; }
const char *getBoundInterface() { return mBoundInterface; }
/* IPropertyProvider methods */
virtual int set(const char *name, const char *value);
virtual const char *get(const char *name, char *buffer, size_t maxsize);
protected:
int loadKernelModule(char *modpath, const char *args);
bool isKernelModuleLoaded(const char *modtag);
int unloadKernelModule(const char *modtag);
int bindInterface(const char *ifname);
int unbindInterface(const char *ifname);
private:
void *loadFile(char *filename, unsigned int *_size);
};
typedef android::List<Controller *> ControllerCollection;
#endif

105
nexus/DhcpClient.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define LOG_TAG "DhcpClient"
#include <cutils/log.h>
#include <cutils/properties.h>
#include <sysutils/ServiceManager.h>
#include "DhcpClient.h"
#include "DhcpState.h"
#include "DhcpListener.h"
#include "IDhcpEventHandlers.h"
extern "C" {
int ifc_disable(const char *ifname);
int ifc_add_host_route(const char *ifname, uint32_t addr);
int ifc_remove_host_routes(const char *ifname);
int ifc_set_default_route(const char *ifname, uint32_t gateway);
int ifc_get_default_route(const char *ifname);
int ifc_remove_default_route(const char *ifname);
int ifc_reset_connections(const char *ifname);
int ifc_configure(const char *ifname, in_addr_t ipaddr, in_addr_t netmask, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2);
int dhcp_do_request(const char *ifname,
in_addr_t *ipaddr,
in_addr_t *gateway,
in_addr_t *mask,
in_addr_t *dns1,
in_addr_t *dns2,
in_addr_t *server,
uint32_t *lease);
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
char *dhcp_get_errmsg();
}
DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) :
mState(DhcpState::STOPPED), mHandlers(handlers) {
mServiceManager = new ServiceManager();
mListener = NULL;
}
DhcpClient::~DhcpClient() {
delete mServiceManager;
if (mListener)
delete mListener;
}
int DhcpClient::start(const char *interface) {
char svc[PROPERTY_VALUE_MAX];
snprintf(svc, sizeof(svc), "dhcpcd_ng:%s", interface);
if (mServiceManager->start(svc)) {
LOGE("Failed to start dhcp service");
return -1;
}
mListener = new DhcpListener(mHandlers);
if (mListener->startListener()) {
LOGE("Failed to start listener");
#if 0
mServiceManager->stop("dhcpcd_ng");
return -1;
#endif
delete mListener;
mListener = NULL;
}
mState = DhcpState::STARTED;
return 0;
}
int DhcpClient::stop() {
if (mListener) {
mListener->stopListener();
delete mListener;
mListener = NULL;
}
if (mServiceManager->stop("dhcpcd_ng"))
LOGW("Failed to stop DHCP service (%s)", strerror(errno));
mState = DhcpState::STOPPED;
return 0;
}

41
nexus/DhcpClient.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _DhcpClient_H
#define _DhcpClient_H
class IDhcpEventHandlers;
class ServiceManager;
class DhcpListener;
class DhcpClient {
int mState;
IDhcpEventHandlers *mHandlers;
ServiceManager *mServiceManager;
DhcpListener *mListener;
public:
DhcpClient(IDhcpEventHandlers *handlers);
virtual ~DhcpClient();
int getState() { return mState; }
int start(const char *interface);
int stop();
};
#endif

34
nexus/DhcpListener.cpp Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2008 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.
*/
#define LOG_TAG "DhcpListener"
#include <cutils/log.h>
#include <DhcpListener.h>
#include "IDhcpEventHandlers.h"
DhcpListener::DhcpListener(IDhcpEventHandlers *handlers) :
SocketListener("dhcp_ng", false) {
mHandlers = handlers;
}
DhcpListener::~DhcpListener() {
}
bool DhcpListener::onDataAvailable(SocketClient *cli) {
LOGD("onDataAvailable()");
return true;
}

36
nexus/DhcpListener.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _DhcpListener_H
#define _DhcpListener_H
#include <sysutils/SocketListener.h>
class IDhcpEventHandlers;
class DhcpListener : public SocketListener {
IDhcpEventHandlers *mHandlers;
public:
DhcpListener(IDhcpEventHandlers *handlers);
virtual ~DhcpListener();
private:
bool onDataAvailable(SocketClient *cli);
};
#endif

27
nexus/DhcpState.h Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _DhcpState_H
#define _DhcpState_H
class DhcpState {
public:
static const int UNKNOWN = 0;
static const int STOPPED = 1;
static const int STARTED = 2;
};
#endif

48
nexus/ErrorCode.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _ERRORCODE_H
#define _ERRORCODE_H
class ErrorCode {
public:
// 100 series - Requestion action was initiated; expect another reply
// before proceeding with a new command.
static const int ActionInitiated = 100;
static const int WifiScanResult = 125;
static const int WifiNetworkList = 126;
static const int PropertyRead = 127;
static const int PropertySet = 128;
static const int PropertyList = 129;
// 200 series - Requested action has been successfully completed
static const int CommandOkay = 200;
// 400 series - The command was accepted but the requested action
// did not take place.
static const int OperationFailed = 400;
// 500 series - The command was not accepted and the requested
// action did not take place.
static const int CommandSyntaxError = 500;
static const int CommandParameterError = 501;
// 600 series - Unsolicited broadcasts
static const int UnsolicitedInformational = 600;
};
#endif

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _ICONTROLLER_HANDLER_H
#define _ICONTROLLER_HANDLER_H
class Controller;
class InterfaceConfig;
class IControllerHandler {
public:
virtual void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) = 0;
virtual void onInterfaceDisconnected(Controller *c, const char *name) = 0;
};
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _IDhcpEventHandlers_H
#define _IDhcpEventHandlers_H
class IDhcpEventHandlers {
public:
};
#endif

33
nexus/IPropertyProvider.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _IPROPERTY_PROVIDER_H
#define _IPROPERTY_PROVIDER_H
#include <unistd.h>
#include <sys/types.h>
#include <utils/List.h>
class IPropertyProvider {
public:
virtual int set(const char *name, const char *value) = 0;
virtual const char *get(const char *name, char *buffer, size_t max) = 0;
};
typedef android::List<IPropertyProvider *> IPropertyProviderCollection;
#endif

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _ISUPPLICANT_EVENT_HANDLER_H
#define _ISUPPLICANT_EVENT_HANDLER_H
class SupplicantAssociatingEvent;
class SupplicantAssociatedEvent;
class SupplicantConnectedEvent;
class SupplicantScanResultsEvent;
class SupplicantStateChangeEvent;
class SupplicantConnectionTimeoutEvent;
class SupplicantDisconnectedEvent;
class ISupplicantEventHandler {
public:
virtual void onAssociatingEvent(SupplicantAssociatingEvent *evt) = 0;
virtual void onAssociatedEvent(SupplicantAssociatedEvent *evt) = 0;
virtual void onConnectedEvent(SupplicantConnectedEvent *evt) = 0;
virtual void onScanResultsEvent(SupplicantScanResultsEvent *evt) = 0;
virtual void onStateChangeEvent(SupplicantStateChangeEvent *evt) = 0;
virtual void onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) = 0;
virtual void onDisconnectedEvent(SupplicantDisconnectedEvent *evt) = 0;
#if 0
virtual void onTerminatingEvent(SupplicantEvent *evt) = 0;
virtual void onPasswordChangedEvent(SupplicantEvent *evt) = 0;
virtual void onEapNotificationEvent(SupplicantEvent *evt) = 0;
virtual void onEapStartedEvent(SupplicantEvent *evt) = 0;
virtual void onEapMethodEvent(SupplicantEvent *evt) = 0;
virtual void onEapSuccessEvent(SupplicantEvent *evt) = 0;
virtual void onEapFailureEvent(SupplicantEvent *evt) = 0;
virtual void onLinkSpeedEvent(SupplicantEvent *evt) = 0;
virtual void onDriverStateEvent(SupplicantEvent *evt) = 0;
#endif
};
#endif

169
nexus/InterfaceConfig.cpp Normal file
View File

@ -0,0 +1,169 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdlib.h>
#include <string.h>
#define LOG_TAG "InterfaceConfig"
#include <cutils/log.h>
#include "InterfaceConfig.h"
#include "NetworkManager.h"
const char *InterfaceConfig::PropertyNames[] = { "dhcp", "ip",
"netmask",
"gateway", "dns1", "dns2",
"dns3", '\0' };
InterfaceConfig::InterfaceConfig(const char *prop_prefix) {
mPropPrefix = strdup(prop_prefix);
mUseDhcp = true;
registerProperties();
}
InterfaceConfig::~InterfaceConfig() {
unregisterProperties();
free(mPropPrefix);
}
InterfaceConfig::InterfaceConfig(const char *prop_prefix,
const char *ip, const char *nm,
const char *gw, const char *dns1, const char *dns2,
const char *dns3) {
mPropPrefix = strdup(prop_prefix);
mUseDhcp = false;
if (!inet_aton(ip, &mIp))
LOGW("Unable to parse ip (%s)", ip);
if (!inet_aton(nm, &mNetmask))
LOGW("Unable to parse netmask (%s)", nm);
if (!inet_aton(gw, &mGateway))
LOGW("Unable to parse gateway (%s)", gw);
if (!inet_aton(dns1, &mDns1))
LOGW("Unable to parse dns1 (%s)", dns1);
if (!inet_aton(dns2, &mDns2))
LOGW("Unable to parse dns2 (%s)", dns2);
if (!inet_aton(dns3, &mDns3))
LOGW("Unable to parse dns3 (%s)", dns3);
registerProperties();
}
InterfaceConfig::InterfaceConfig(const char *prop_prefix,
const struct in_addr *ip,
const struct in_addr *nm, const struct in_addr *gw,
const struct in_addr *dns1, const struct in_addr *dns2,
const struct in_addr *dns3) {
mPropPrefix = strdup(prop_prefix);
mUseDhcp = false;
memcpy(&mIp, ip, sizeof(struct in_addr));
memcpy(&mNetmask, nm, sizeof(struct in_addr));
memcpy(&mGateway, gw, sizeof(struct in_addr));
memcpy(&mDns1, dns1, sizeof(struct in_addr));
memcpy(&mDns2, dns2, sizeof(struct in_addr));
memcpy(&mDns3, dns3, sizeof(struct in_addr));
registerProperties();
}
int InterfaceConfig::registerProperties() {
for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) {
char *tmp;
asprintf(&tmp, "%s.if.%s", mPropPrefix, *p);
if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp,
this)) {
free(tmp);
return -1;
}
free(tmp);
}
return 0;
}
int InterfaceConfig::unregisterProperties() {
for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) {
char *tmp;
asprintf(&tmp, "%s.if.%s", mPropPrefix, *p);
if (NetworkManager::Instance()->getPropMngr()->unregisterProperty(tmp))
LOGW("Unable to remove property '%s' (%s)", tmp, strerror(errno));
free(tmp);
}
return 0;
}
int InterfaceConfig::set(const char *name, const char *value) {
const char *n;
for (n = &name[strlen(name)]; *n != '.'; n--);
n++;
if (!strcasecmp(n, "name")) {
errno = EROFS;
return -1;
} else if (!strcasecmp(n, "ip") && !inet_aton(value, &mIp))
goto out_inval;
else if (!strcasecmp(n, "dhcp"))
mUseDhcp = (atoi(value) == 0 ? false : true);
else if (!strcasecmp(n, "netmask") && !inet_aton(value, &mNetmask))
goto out_inval;
else if (!strcasecmp(n, "gateway") && !inet_aton(value, &mGateway))
goto out_inval;
else if (!strcasecmp(n, "dns1") && !inet_aton(value, &mDns1))
goto out_inval;
else if (!strcasecmp(n, "dns2") && !inet_aton(value, &mDns2))
goto out_inval;
else if (!strcasecmp(n, "dns3") && !inet_aton(value, &mDns3))
goto out_inval;
else {
errno = ENOENT;
return -1;
}
return 0;
out_inval:
errno = EINVAL;
return -1;
}
const char *InterfaceConfig::get(const char *name, char *buffer, size_t max) {
const char *n;
for (n = &name[strlen(name)]; *n != '.'; n--);
n++;
if (!strcasecmp(n, "ip"))
strncpy(buffer, inet_ntoa(mIp), max);
else if (!strcasecmp(n, "dhcp"))
snprintf(buffer, max, "%d", mUseDhcp);
else if (!strcasecmp(n, "netmask"))
strncpy(buffer, inet_ntoa(mNetmask), max);
else if (!strcasecmp(n, "gateway"))
strncpy(buffer, inet_ntoa(mGateway), max);
else if (!strcasecmp(n, "dns1"))
strncpy(buffer, inet_ntoa(mDns1), max);
else if (!strcasecmp(n, "dns2"))
strncpy(buffer, inet_ntoa(mDns2), max);
else if (!strcasecmp(n, "dns3"))
strncpy(buffer, inet_ntoa(mDns3), max);
else {
strncpy(buffer, "(internal error)", max);
errno = ENOENT;
return NULL;
}
return buffer;
}

75
nexus/InterfaceConfig.h Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _INTERFACE_CONFIG_H
#define _INTERFACE_CONFIG_H
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "IPropertyProvider.h"
class PropertyManager;
class InterfaceConfig : public IPropertyProvider {
public:
static const char *PropertyNames[];
private:
char *mPropPrefix;
bool mUseDhcp;
struct in_addr mIp;
struct in_addr mNetmask;
struct in_addr mGateway;
struct in_addr mDns1;
struct in_addr mDns2;
struct in_addr mDns3;
public:
InterfaceConfig(const char *prop_prefix);
InterfaceConfig(const char *prop_prefix,
const char *ip, const char *nm,
const char *gw, const char *dns1, const char *dns2,
const char *dns3);
InterfaceConfig(const char *prop_prefix,
const struct in_addr *ip,
const struct in_addr *nm, const struct in_addr *gw,
const struct in_addr *dns1, const struct in_addr *dns2,
const struct in_addr *dns3);
virtual ~InterfaceConfig();
int set(const char *name, const char *value);
const char *get(const char *name, char *buffer, size_t maxsize);
bool getUseDhcp() const { return mUseDhcp; }
const struct in_addr &getIp() const { return mIp; }
const struct in_addr &getNetmask() const { return mNetmask; }
const struct in_addr &getGateway() const { return mGateway; }
const struct in_addr &getDns1() const { return mDns1; }
const struct in_addr &getDns2() const { return mDns2; }
const struct in_addr &getDns3() const { return mDns3; }
private:
int registerProperties();
int unregisterProperties();
};
#endif

34
nexus/LoopController.cpp Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2008 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.
*/
#include <errno.h>
#include "LoopController.h"
#include "PropertyManager.h"
LoopController::LoopController(PropertyManager *propmngr,
IControllerHandler *handlers) :
Controller("LOOP", propmngr, handlers) {
}
int LoopController::set(const char *name, const char *value) {
return Controller::set(name, value);
}
const char *LoopController::get(const char *name, char *buffer, size_t maxsize) {
return Controller::get(name, buffer, maxsize);
}

33
nexus/LoopController.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _LOOP_CONTROLLER_H
#define _LOOP_CONTROLLER_H
#include "Controller.h"
class ControllerHandler;
class LoopController : public Controller {
public:
LoopController(PropertyManager *propmngr, IControllerHandler *h);
virtual ~LoopController() {}
int set(const char *name, const char *value);
const char *get(const char *name, char *buffer, size_t maxsize);
};
#endif

121
nexus/NetworkManager.cpp Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2008 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.
*/
#include <stdio.h>
#include <errno.h>
#define LOG_TAG "Nexus"
#include <cutils/log.h>
#include "NetworkManager.h"
#include "InterfaceConfig.h"
#include "DhcpClient.h"
NetworkManager *NetworkManager::sInstance = NULL;
NetworkManager *NetworkManager::Instance() {
if (!sInstance)
sInstance = new NetworkManager(new PropertyManager());
return sInstance;
}
NetworkManager::NetworkManager(PropertyManager *propMngr) {
mBroadcaster = NULL;
mControllers = new ControllerCollection();
mPropMngr = propMngr;
mDhcp = new DhcpClient(this);
}
NetworkManager::~NetworkManager() {
}
int NetworkManager::run() {
if (startControllers()) {
LOGW("Unable to start all controllers (%s)", strerror(errno));
}
return 0;
}
int NetworkManager::attachController(Controller *c) {
mControllers->push_back(c);
return 0;
}
int NetworkManager::startControllers() {
int rc = 0;
ControllerCollection::iterator i;
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
int irc = (*i)->start();
LOGD("Controller '%s' start rc = %d", (*i)->getName(), irc);
if (irc && !rc)
rc = irc;
}
return rc;
}
int NetworkManager::stopControllers() {
int rc = 0;
ControllerCollection::iterator i;
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
int irc = (*i)->stop();
LOGD("Controller '%s' stop rc = %d", (*i)->getName(), irc);
if (irc && !rc)
rc = irc;
}
return rc;
}
Controller *NetworkManager::findController(const char *name) {
ControllerCollection::iterator i;
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
if (!strcmp((*i)->getName(), name))
return *i;
}
LOGW("Controller '%s' not found", name);
return NULL;
}
void NetworkManager::onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) {
LOGD("Controller %s interface %s connected", c->getName(), c->getBoundInterface());
// Look up the interface
if (0) { // already started?
}
if (cfg) {
if (cfg->getUseDhcp() && mDhcp->start(c->getBoundInterface())) {
LOGE("DHCP start failed");
} else if (!cfg->getUseDhcp()) {
// Static configuration
}
} else {
LOGD("No InterfaceConfig for %s:%s - assuming self-managed",
c->getName(), c->getBoundInterface());
}
}
void NetworkManager::onInterfaceDisconnected(Controller *c, const char *name) {
LOGD("Controller %s interface %s disconnected", c->getName(), name);
// If we have a DHCP request out on this interface then stop it
if (1) {
mDhcp->stop();
}
}

64
nexus/NetworkManager.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _NETWORKMANAGER_H
#define _NETWORKMANAGER_H
#include <sysutils/SocketListener.h>
#include "Controller.h"
#include "PropertyManager.h"
#include "IControllerHandler.h"
#include "IDhcpEventHandlers.h"
class InterfaceConfig;
class DhcpClient;
class NetworkManager : public IControllerHandler, public IDhcpEventHandlers {
private:
static NetworkManager *sInstance;
private:
ControllerCollection *mControllers;
SocketListener *mBroadcaster;
PropertyManager *mPropMngr;
DhcpClient *mDhcp;
public:
virtual ~NetworkManager();
int run();
int attachController(Controller *controller);
Controller *findController(const char *name);
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
SocketListener *getBroadcaster() { return mBroadcaster; }
PropertyManager *getPropMngr() { return mPropMngr; }
static NetworkManager *Instance();
private:
int startControllers();
int stopControllers();
NetworkManager(PropertyManager *propMngr);
void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg);
void onInterfaceDisconnected(Controller *c, const char *name);
};
#endif

21
nexus/NexusCommand.cpp Normal file
View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2008 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.
*/
#include "NexusCommand.h"
NexusCommand::NexusCommand(const char *cmd) :
FrameworkCommand(cmd) {
}

28
nexus/NexusCommand.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _NEXUS_COMMAND_H
#define _NEXUS_COMMAND_H
#include <sysutils/FrameworkCommand.h>
class NexusCommand : public FrameworkCommand {
public:
NexusCommand(const char *cmd);
virtual ~NexusCommand() {}
};
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2008 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.
*/
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define LOG_TAG "OpenVpnController"
#include <cutils/log.h>
#include <cutils/properties.h>
#include <sysutils/ServiceManager.h>
#include "OpenVpnController.h"
#include "PropertyManager.h"
#define DAEMON_PROP_NAME "vpn.openvpn.status"
#define DAEMON_CONFIG_FILE "/data/misc/openvpn/openvpn.conf"
OpenVpnController::OpenVpnController(PropertyManager *propmngr,
IControllerHandler *handlers) :
VpnController(propmngr, handlers) {
mServiceManager = new ServiceManager();
}
OpenVpnController::~OpenVpnController() {
delete mServiceManager;
}
int OpenVpnController::start() {
return VpnController::start();
}
int OpenVpnController::stop() {
return VpnController::stop();
}
int OpenVpnController::enable() {
char svc[PROPERTY_VALUE_MAX];
char tmp[64];
if (!mPropMngr->get("vpn.gateway", tmp, sizeof(tmp))) {
LOGE("Error reading property 'vpn.gateway' (%s)", strerror(errno));
return -1;
}
snprintf(svc, sizeof(svc), "openvpn:--remote %s 1194", tmp);
if (mServiceManager->start(svc))
return -1;
return 0;
}
int OpenVpnController::disable() {
if (mServiceManager->stop("openvpn"))
return -1;
return 0;
}

42
nexus/OpenVpnController.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2008 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.
*/
#ifndef _OPEN_VPN_CONTROLLER_H
#define _OPEN_VPN_CONTROLLER_H
#include "PropertyManager.h"
#include "VpnController.h"
class ServiceManager;
class IControllerHandler;
class OpenVpnController : public VpnController {
private:
ServiceManager *mServiceManager;
public:
OpenVpnController(PropertyManager *propmngr, IControllerHandler *handlers);
virtual ~OpenVpnController();
int start();
int stop();
private:
int enable();
int disable();
};
#endif

21
nexus/Property.h Normal file
View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2008 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.
*/
class Property {
public:
static const int NameMaxSize = 128;
static const int ValueMaxSize = 255;
};

123
nexus/PropertyManager.cpp Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (C) 2008 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.
*/
#define LOG_TAG "PropertyManager"
#include <cutils/log.h>
#include "PropertyManager.h"
PropertyManager::PropertyManager() {
mPropertyPairs = new PropertyPairCollection();
pthread_mutex_init(&mLock, NULL);
}
PropertyManager::~PropertyManager() {
delete mPropertyPairs;
}
int PropertyManager::registerProperty(const char *name, IPropertyProvider *pp) {
PropertyPairCollection::iterator it;
// LOGD("registerProperty(%s)", name);
pthread_mutex_lock(&mLock);
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
if (!strcmp(name, (*it)->getName())) {
errno = EADDRINUSE;
LOGE("Failed to register property %s (%s)",
name, strerror(errno));
pthread_mutex_unlock(&mLock);
return -1;
}
}
mPropertyPairs->push_back(new PropertyPair(name, pp));
pthread_mutex_unlock(&mLock);
return 0;
}
int PropertyManager::unregisterProperty(const char *name) {
PropertyPairCollection::iterator it;
// LOGD("unregisterProperty(%s)", name);
pthread_mutex_lock(&mLock);
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
if (!strcmp(name, (*it)->getName())) {
delete ((*it));
mPropertyPairs->erase(it);
pthread_mutex_unlock(&mLock);
return 0;
}
}
pthread_mutex_unlock(&mLock);
errno = ENOENT;
return -1;
}
/*
* IPropertyManager methods
*/
int PropertyManager::set(const char *name, const char *value) {
PropertyPairCollection::iterator it;
pthread_mutex_lock(&mLock);
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
if (!strcmp(name, (*it)->getName())) {
pthread_mutex_unlock(&mLock);
return (*it)->getProvider()->set(name, value);
}
}
pthread_mutex_unlock(&mLock);
errno = ENOENT;
return -1;
}
const char *PropertyManager::get(const char *name, char *buffer, size_t max) {
PropertyPairCollection::iterator it;
memset(buffer, 0, max);
pthread_mutex_lock(&mLock);
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
if (!strcmp(name, (*it)->getName())) {
pthread_mutex_unlock(&mLock);
return (*it)->getProvider()->get(name, buffer, max);
}
}
pthread_mutex_unlock(&mLock);
errno = ENOENT;
return NULL;
}
android::List<char *> *PropertyManager::createPropertyList() {
android::List<char *> *c = new android::List<char *>();
PropertyPairCollection::iterator it;
pthread_mutex_lock(&mLock);
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it)
c->push_back(strdup((*it)->getName()));
pthread_mutex_unlock(&mLock);
return c;
}
PropertyPair::PropertyPair(const char *name, IPropertyProvider *pp) {
mName = strdup(name);
mPp = pp;
}
PropertyPair::~PropertyPair() {
free(mName);
}

Some files were not shown because too many files have changed in this diff Show More