Revert "[Feature][T8TSK-250][ADBD]add adb debug patch"
This reverts commit 0300fcc023c83b5b569b0c0799aff58cfd65dd39.
Reason for revert: <INSERT REASONING HERE>
Change-Id: I82e92daf5003f885c4732744291c57425ef27642
diff --git a/meta/meta-mediatek-mt2735/recipes-core/initial/files/init_usb.service b/meta/meta-mediatek-mt2735/recipes-core/initial/files/init_usb.service
old mode 100755
new mode 100644
index a52b6a6..f9dad60
--- a/meta/meta-mediatek-mt2735/recipes-core/initial/files/init_usb.service
+++ b/meta/meta-mediatek-mt2735/recipes-core/initial/files/init_usb.service
@@ -11,7 +11,7 @@
ExecStartPre=/bin/sh /usr/share/init/init_usb pre
ExecStart=/usr/bin/adbd
ExecStartPost=/bin/sh /usr/share/init/init_usb post
-StandardOutput=kmsg+console
+StandardOutput=null
[Install]
WantedBy=basic.target
diff --git a/meta/meta-mediatek-mt2735/recipes-devtools/adbd/adbd_5.0.0_r1.bb b/meta/meta-mediatek-mt2735/recipes-devtools/adbd/adbd_5.0.0_r1.bb
old mode 100755
new mode 100644
index 4bc6e14..3c8253a
--- a/meta/meta-mediatek-mt2735/recipes-devtools/adbd/adbd_5.0.0_r1.bb
+++ b/meta/meta-mediatek-mt2735/recipes-devtools/adbd/adbd_5.0.0_r1.bb
@@ -2,25 +2,24 @@
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://NOTICE;md5=720f14959428458dd19787dbf1e02b95"
FILESEXTRAPATHS_append := ":${THISDIR}/files"
-SRC_URI = "file://usb.config"
+SRC_URI = "file://usb.config \
+ file://service.config "
inherit workonsrc
WORKONSRC = "${TOPDIR}/../src/devtools/adb/"
-DEPENDS += "uci platform-libs-common"
+DEPENDS += "uci platform-libs-common liblynq-uci liblynq-log"
TARGET_CC_ARCH += "${LDFLAGS}"
EXTRA_OEMAKE = "'BB_SYSROOT_ADD=${STAGING_DIR_HOST}'"
EXTRA_OEMAKE += "'PACKAGE_ARCH=${PACKAGE_ARCH}'"
EXTRA_OEMAKE += "'TOP_ROOT=${B}'"
-EXTRA_OEMAKE += "'UCI_PROPERTY_SUPPORT=1'"
-EXTRA_OEMAKE += "'ADB_SERVICE_ENABLE=1'"
INSANE_SKIP_${PN} += "already-stripped"
FILES_${PN} += "${bindir}/adbd"
FILES_${PN} += "/etc/config/usb"
-
+FILES_${PN} += "/etc/config/service"
do_compile() {
oe_runmake all -f ${B}/Makefile
}
@@ -30,6 +29,7 @@
install -m 0755 ${B}adbd ${D}${bindir}
install -d ${D}/etc/config
install -m 0644 ${WORKDIR}/usb.config ${D}/etc/config/usb
+ install -m 0644 ${WORKDIR}/service.config ${D}/etc/config/service
}
do_install_append() {
diff --git a/src/devtools/adb/Makefile b/src/devtools/adb/Makefile
index 9386b84..cf6beac 100644
--- a/src/devtools/adb/Makefile
+++ b/src/devtools/adb/Makefile
@@ -25,6 +25,9 @@
ADBD_SRC_FILES := \
file_sync_service.c \
+ adb_auth_client.c \
+ jdwp_service.c \
+ framebuffer_service.c \
remount_service.c
ifneq ($(ADB_OVER_PCIE),1)
ADBD_SRC_FILES+= usb_linux_client.c
@@ -40,6 +43,7 @@
socket_loopback_server.c \
socket_network_client.c \
sha.c \
+ rsa.c \
sha256.c \
logd_write.c \
thread_utils.c \
@@ -58,13 +62,6 @@
ifeq ($(ADB_OVER_PCIE),1)
LOCAL_CFLAGS+= -DADB_OVER_PCIE=1
-else ifeq ($(UCI_PROPERTY_SUPPORT),1)
- LOCAL_CFLAGS+= -DUCI_PROPERTY_SUPPORT=1
- LIBS+= -luci
-endif
-
-ifeq ($(ADB_SERVICE_ENABLE),1)
- LOCAL_CFLAGS += -DADB_SERVICE_ENABLE
endif
CPPFLAGS+= -DDZONE -DHAVE_FORKEXEC=1 -DHAVE_SYMLINKS -DHAVE_TERMIO_H
@@ -72,7 +69,7 @@
CPPFLAGS+= -I. -I./include
CPPFLAGS+= $(LOCAL_CFLAGS)
-LIBS+= -lpthread -lrt
+LIBS += -lpthread -luci
LOCAL_MODULE := adbd
LOCAL_SRC_FILES+= $(COMMON_SRC_FILES) $(ADBD_SRC_FILES)
diff --git a/src/devtools/adb/adb.c b/src/devtools/adb/adb.c
index 2eb667a..82efb12 100644
--- a/src/devtools/adb/adb.c
+++ b/src/devtools/adb/adb.c
@@ -59,8 +59,6 @@
static const char *root_seclabel = NULL;
#endif
-int adb_service_enable = 1;
-
void fatal(const char *fmt, ...)
{
va_list ap;
@@ -120,7 +118,7 @@
/* use a comma/column/semi-colum/space separated list */
while (*p) {
- unsigned int len, tagn;
+ int len, tagn;
q = strpbrk(p, " ,:;");
if (q == NULL) {
@@ -238,8 +236,6 @@
char *tag;
char *x;
unsigned count;
- char data[DUMPMAX+4];
- int i = 0;
switch(p->msg.command){
case A_SYNC: tag = "SYNC"; break;
@@ -252,26 +248,25 @@
default: tag = "????"; break;
}
+ fprintf(stderr, "%s: %s %08x %08x %04x \"",
+ label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
count = p->msg.data_length;
x = (char*) p->data;
if(count > DUMPMAX) {
count = DUMPMAX;
+ tag = "\n";
+ } else {
+ tag = "\"\n";
}
- while(i < count){
+ while(count-- > 0){
if((*x >= ' ') && (*x < 127)) {
- data[i] = *x;
+ fputc(*x, stderr);
} else {
- data[i] = '.';
+ fputc('.', stderr);
}
x++;
- i++;
}
- data[i++] = '\"';
- data[i++] = '\n';
- data[i] = '\0';
-
- D("%s: %s %08x %08x %04x %s\"",
- label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length, data);
+ fputs(tag, stderr);
}
#endif
@@ -395,6 +390,69 @@
send_packet(cp, t);
}
+void send_auth_request(atransport *t)
+{
+ D("Calling send_auth_request\n");
+ apacket *p;
+ int ret;
+
+ ret = adb_auth_generate_token(t->token, sizeof(t->token));
+ if (ret != sizeof(t->token)) {
+ D("Error generating token ret=%d\n", ret);
+ return;
+ }
+
+ p = get_apacket();
+ memcpy(p->data, t->token, ret);
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_TOKEN;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
+static void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
+{
+ D("Calling send_auth_response\n");
+ apacket *p = get_apacket();
+ int ret;
+
+ ret = adb_auth_sign(t->key, token, token_size, p->data);
+ if (!ret) {
+ D("Error signing the token\n");
+ put_apacket(p);
+ return;
+ }
+
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_SIGNATURE;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
+static void send_auth_publickey(atransport *t)
+{
+ D("Calling send_auth_publickey\n");
+ apacket *p = get_apacket();
+ int ret;
+
+ ret = adb_auth_get_userkey(p->data, sizeof(p->data));
+ if (!ret) {
+ D("Failed to get user public key\n");
+ put_apacket(p);
+ return;
+ }
+
+ p->msg.command = A_AUTH;
+ p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
+ p->msg.data_length = ret;
+ send_packet(p, t);
+}
+
+void adb_auth_verified(atransport *t)
+{
+ handle_online(t);
+ send_connect(t);
+}
#if ADB_HOST
static char *connection_state_name(atransport *t)
@@ -562,11 +620,35 @@
parse_banner((char*) p->data, t);
- if (!adb_service_enable) {
- D("Ignore ADB client CNXN request, ADB keeps disabled");
- } else if (HOST || !auth_enabled) {
+ if (HOST || !auth_enabled) {
handle_online(t);
if(!HOST) send_connect(t);
+ } else {
+ send_auth_request(t);
+ }
+ break;
+
+ case A_AUTH:
+ if (p->msg.arg0 == ADB_AUTH_TOKEN) {
+ t->connection_state = CS_UNAUTHORIZED;
+ t->key = adb_auth_nextkey(t->key);
+ if (t->key) {
+ send_auth_response(p->data, p->msg.data_length, t);
+ } else {
+ /* No more private keys to try, send the public key */
+ send_auth_publickey(t);
+ }
+ } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
+ if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
+ adb_auth_verified(t);
+ t->failed_auth_attempts = 0;
+ } else {
+ if (t->failed_auth_attempts++ > 10)
+ adb_sleep_ms(1000);
+ send_auth_request(t);
+ }
+ } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
+ adb_auth_confirm_key(p->data, p->msg.data_length, t);
}
break;
@@ -944,6 +1026,48 @@
#endif
}
+void start_logging(void)
+{
+#if defined(_WIN32)
+ char temp[ MAX_PATH ];
+ FILE* fnul;
+ FILE* flog;
+
+ GetTempPath( sizeof(temp) - 8, temp );
+ strcat( temp, "adb.log" );
+
+ /* Win32 specific redirections */
+ fnul = fopen( "NUL", "rt" );
+ if (fnul != NULL)
+ stdin[0] = fnul[0];
+
+ flog = fopen( temp, "at" );
+ if (flog == NULL)
+ flog = fnul;
+
+ setvbuf( flog, NULL, _IONBF, 0 );
+
+ stdout[0] = flog[0];
+ stderr[0] = flog[0];
+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+#else
+ int fd;
+
+ fd = unix_open("/dev/null", O_RDONLY);
+ dup2(fd, 0);
+ adb_close(fd);
+
+ fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
+ if(fd < 0) {
+ fd = unix_open("/dev/null", O_WRONLY);
+ }
+ dup2(fd, 1);
+ dup2(fd, 2);
+ adb_close(fd);
+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+#endif
+}
+
#if !ADB_HOST
void start_device_log(void)
{
@@ -951,19 +1075,34 @@
char path[PATH_MAX];
struct tm now;
time_t t;
- char value[PROPERTY_VALUE_MAX] = "";
+ char value[PROPERTY_VALUE_MAX];
// 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 || adb_trace_mask == 0)
- {
- DD("ADB daemon log DISABLED, adb_trace_mask=0x%x\n", adb_trace_mask);
+ if (sscanf(value, "%x", &adb_trace_mask) != 1)
return;
- } else {
- adb_trace_mask %= (1 <<TRACE_LAST);
- DD("ADB daemon log to AP log file ENABLED, adb_trace_mask=0x%x\n", adb_trace_mask);
- }
+
+ adb_mkdir("/tmp/adb", 0775);
+ tzset();
+ time(&t);
+ localtime_r(&t, &now);
+ strftime(path, sizeof(path),
+ "/tmp/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;
+
+ // redirect stdout and stderr to the log file
+ dup2(fd, 1);
+ dup2(fd, 2);
+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
+ adb_close(fd);
+
+ fd = unix_open("/dev/null", O_RDONLY);
+ dup2(fd, 0);
+ adb_close(fd);
}
#endif
@@ -1194,9 +1333,6 @@
return 1;
#else /* ALLOW_ADBD_ROOT */
#ifdef ADB_NON_ANDROID
- if (!adb_service_enable) {
- return 1;
- }
return 0;
#endif /* ADB_NON_ANDROID */
int secure = 0;
@@ -1261,6 +1397,7 @@
usb_init();
#endif
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+ adb_auth_init();
char local_name[30];
build_local_name(local_name, sizeof(local_name), server_port);
@@ -1268,6 +1405,10 @@
exit(1);
}
#else
+ property_get("ro.adb.secure", value, "0");
+ auth_enabled = !strcmp(value, "1");
+ if (auth_enabled)
+ adb_auth_init();
// Our external storage path may be different than apps, since
// we aren't able to bind mount after dropping root.
@@ -1357,6 +1498,9 @@
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
}
+ D("adb_main(): pre init_jdwp()\n");
+ init_jdwp();
+ D("adb_main(): post init_jdwp()\n");
#endif
if (is_daemon)
@@ -1368,6 +1512,7 @@
#else
fprintf(stderr, "OK\n");
#endif
+ start_logging();
}
D("Event loop starting\n");
@@ -1628,24 +1773,6 @@
return -1;
}
-void update_enabled_flag() {
-#ifndef ADB_OVER_PCIE
-#ifdef ADB_SERVICE_ENABLE
- adb_service_enable = 1;
-#else
- char value[PROPERTY_VALUE_MAX] = "";
-
- property_get("service.adb.enable", value, "");
- if (sscanf(value, "%x", &adb_service_enable) != 1) {
- adb_service_enable = 0;
- } else if (adb_service_enable != 0) {
- adb_service_enable = 1;
- }
-#endif
-#endif
- printf("ADB service enabled status=%d\n", adb_service_enable);
-}
-
int main(int argc, char **argv)
{
#if ADB_HOST
@@ -1657,7 +1784,7 @@
/* If adbd runs inside the emulator this will enable adb tracing via
* adb-debug qemud service in the emulator. */
//adb_qemu_trace_init();
- DD("adb main()\n");
+ D("main()\n");
while(1) {
int c;
int option_index = 0;
@@ -1681,8 +1808,7 @@
}
start_device_log();
- update_enabled_flag();
- DD("Handling main()\n");
+ D("Handling main()\n");
return adb_main(0, DEFAULT_ADB_PORT);
#endif
}
diff --git a/src/devtools/adb/adb.h b/src/devtools/adb/adb.h
index f5b4aa0..84d55d8 100644
--- a/src/devtools/adb/adb.h
+++ b/src/devtools/adb/adb.h
@@ -324,9 +324,17 @@
asocket *host_service_to_socket(const char* name, const char *serial);
#endif
+#if !ADB_HOST
+int init_jdwp(void);
+asocket* create_jdwp_service_socket();
+asocket* create_jdwp_tracker_service_socket();
+int create_jdwp_connection_fd(int jdwp_pid);
+#endif
+
int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd);
#if !ADB_HOST
+void framebuffer_service(int fd, void *cookie);
void remount_service(int fd, void *cookie);
#endif
diff --git a/src/devtools/adb/adb_auth_client.c b/src/devtools/adb/adb_auth_client.c
new file mode 100644
index 0000000..4ce5d1e
--- /dev/null
+++ b/src/devtools/adb/adb_auth_client.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012 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 <string.h>
+#include <resolv.h>
+#include <cutils/list.h>
+#include <cutils/sockets.h>
+
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_auth.h"
+#include "fdevent.h"
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+
+#define TRACE_TAG TRACE_AUTH
+
+#ifdef __GLIBC__
+#ifdef b64_pton
+#undef b64_pton
+#endif
+#endif
+
+struct adb_public_key {
+ struct listnode node;
+ RSAPublicKey key;
+};
+
+static char *key_paths[] = {
+ "/adb_keys",
+ "/data/misc/adb/adb_keys",
+ NULL
+};
+
+static fdevent listener_fde;
+static int framework_fd = -1;
+
+static void usb_disconnected(void* unused, atransport* t);
+static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 };
+static atransport* usb_transport;
+static bool needs_retry = false;
+
+static void read_keys(const char *file, struct listnode *list)
+{
+ struct adb_public_key *key;
+ FILE *f;
+ char buf[MAX_PAYLOAD];
+ char *sep;
+ int ret;
+
+ f = fopen(file, "re");
+ if (!f) {
+ D("Can't open '%s'\n", file);
+ return;
+ }
+
+ while (fgets(buf, sizeof(buf), f)) {
+ /* Allocate 4 extra bytes to decode the base64 data in-place */
+ key = calloc(1, sizeof(*key) + 4);
+ if (!key) {
+ D("Can't malloc key\n");
+ break;
+ }
+
+ sep = strpbrk(buf, " \t");
+ if (sep)
+ *sep = '\0';
+
+ ret = b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
+ if (ret != sizeof(key->key)) {
+ D("%s: Invalid base64 data ret=%d\n", file, ret);
+ free(key);
+ continue;
+ }
+
+ if (key->key.len != RSANUMWORDS) {
+ D("%s: Invalid key len %d\n", file, key->key.len);
+ free(key);
+ continue;
+ }
+
+ list_add_tail(list, &key->node);
+ }
+
+ fclose(f);
+}
+
+static void free_keys(struct listnode *list)
+{
+ struct listnode *item;
+
+ while (!list_empty(list)) {
+ item = list_head(list);
+ list_remove(item);
+ free(node_to_item(item, struct adb_public_key, node));
+ }
+}
+
+static void load_keys(struct listnode *list)
+{
+ char *path;
+ char **paths = key_paths;
+ struct stat buf;
+
+ list_init(list);
+
+ while ((path = *paths++)) {
+ if (!stat(path, &buf)) {
+ D("Loading keys from '%s'\n", path);
+ read_keys(path, list);
+ }
+ }
+}
+
+int adb_auth_generate_token(void *token, size_t token_size)
+{
+ FILE *f;
+ int ret;
+
+ f = fopen("/dev/urandom", "re");
+ if (!f)
+ return 0;
+
+ ret = fread(token, token_size, 1, f);
+
+ fclose(f);
+ return ret * token_size;
+}
+
+int adb_auth_verify(void *token, void *sig, int siglen)
+{
+ struct listnode *item;
+ struct adb_public_key *key;
+ struct listnode key_list;
+ int ret = 0;
+
+ if (siglen != RSANUMBYTES)
+ return 0;
+
+ load_keys(&key_list);
+
+ list_for_each(item, &key_list) {
+ key = node_to_item(item, struct adb_public_key, node);
+ ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE);
+ if (ret)
+ break;
+ }
+
+ free_keys(&key_list);
+
+ return ret;
+}
+
+static void usb_disconnected(void* unused, atransport* t)
+{
+ D("USB disconnect\n");
+ remove_transport_disconnect(usb_transport, &usb_disconnect);
+ usb_transport = NULL;
+ needs_retry = false;
+}
+
+static void adb_auth_event(int fd, unsigned events, void *data)
+{
+ char response[2];
+ int ret;
+
+ if (events & FDE_READ) {
+ ret = unix_read(fd, response, sizeof(response));
+ if (ret <= 0) {
+ D("Framework disconnect\n");
+ if (usb_transport)
+ fdevent_remove(&usb_transport->auth_fde);
+ framework_fd = -1;
+ }
+ else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
+ if (usb_transport)
+ adb_auth_verified(usb_transport);
+ }
+ }
+}
+
+void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
+{
+ char msg[MAX_PAYLOAD];
+ int ret;
+
+ if (!usb_transport) {
+ usb_transport = t;
+ add_transport_disconnect(t, &usb_disconnect);
+ }
+
+ if (framework_fd < 0) {
+ D("Client not connected\n");
+ needs_retry = true;
+ return;
+ }
+
+ if (key[len - 1] != '\0') {
+ D("Key must be a null-terminated string\n");
+ return;
+ }
+
+ ret = snprintf(msg, sizeof(msg), "PK%s", key);
+ if (ret >= (signed)sizeof(msg)) {
+ D("Key too long. ret=%d", ret);
+ return;
+ }
+ D("Sending '%s'\n", msg);
+
+ ret = unix_write(framework_fd, msg, ret);
+ if (ret < 0) {
+ D("Failed to write PK, errno=%d\n", errno);
+ return;
+ }
+
+ fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);
+ fdevent_add(&t->auth_fde, FDE_READ);
+}
+
+static void adb_auth_listener(int fd, unsigned events, void *data)
+{
+ struct sockaddr addr;
+ socklen_t alen;
+ int s;
+
+ alen = sizeof(addr);
+
+ s = adb_socket_accept(fd, &addr, &alen);
+ if (s < 0) {
+ D("Failed to accept: errno=%d\n", errno);
+ return;
+ }
+
+ framework_fd = s;
+
+ if (needs_retry) {
+ needs_retry = false;
+ send_auth_request(usb_transport);
+ }
+}
+
+void adb_auth_init(void)
+{
+ int fd, ret;
+
+ fd = android_get_control_socket("adbd");
+ if (fd < 0) {
+ D("Failed to get adbd socket\n");
+ printf("Failed to get adbd socket\n");
+ return;
+ }
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ ret = listen(fd, 4);
+ if (ret < 0) {
+ D("Failed to listen on '%d'\n", fd);
+ return;
+ }
+
+ fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
+ fdevent_add(&listener_fde, FDE_READ);
+}
diff --git a/src/devtools/adb/adb_trace.h b/src/devtools/adb/adb_trace.h
index 2039dbe..32c3cc6 100644
--- a/src/devtools/adb/adb_trace.h
+++ b/src/devtools/adb/adb_trace.h
@@ -22,7 +22,7 @@
#endif
/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
-#define ADB_TRACE 1
+#define ADB_TRACE 0
/* IMPORTANT: if you change the following list, don't
* forget to update the corresponding 'tags' table in
@@ -41,7 +41,6 @@
TRACE_SERVICES,
TRACE_AUTH,
TRACE_FDEVENT,
- TRACE_LAST, /* 0x1000 */
} AdbTrace;
#if ADB_TRACE
diff --git a/src/devtools/adb/adb_trace.h.bak b/src/devtools/adb/adb_trace.h.bak
deleted file mode 100644
index d21a041..0000000
--- a/src/devtools/adb/adb_trace.h.bak
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2014 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 __ADB_TRACE_H
-#define __ADB_TRACE_H
-
-#if !ADB_HOST
-#include <android/log.h>
-#endif
-
-#include <syslog.h>
-
-#define LOG_ERR 1
-#define LOG_WARNING 2
-#define LOG_INFO 3
-#define LOG_DEBUG 4
-
-/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
-#define ADB_TRACE 1
-
-/* IMPORTANT: if you change the following list, don't
- * forget to update the corresponding 'tags' table in
- * the adb_trace_init() function implemented in adb.c
- */
-typedef enum {
- TRACE_ADB = 0, /* 0x001 */
- TRACE_SOCKETS,
- TRACE_PACKETS,
- TRACE_TRANSPORT,
- TRACE_RWX, /* 0x010 */
- TRACE_USB,
- TRACE_SYNC,
- TRACE_SYSDEPS,
- TRACE_JDWP, /* 0x100 */
- TRACE_SERVICES,
- TRACE_AUTH,
- TRACE_FDEVENT,
- TRACE_LAST, /* 0x1000 */
-} AdbTrace;
-
-#if ADB_TRACE
-
-#if !ADB_HOST
-/*
- * When running inside the emulator, guest's adbd can connect to 'adb-debug'
- * qemud service that can display adb trace messages (on condition that emulator
- * has been started with '-debug adb' option).
- */
-
-/* Delivers a trace message to the emulator via QEMU pipe. */
-void adb_qemu_trace(const char* fmt, ...);
-/* Macro to use to send ADB trace messages to the emulator. */
-#define DQ(...) adb_qemu_trace(__VA_ARGS__)
-#else
-#define DQ(...) ((void)0)
-#endif /* !ADB_HOST */
-
-extern int adb_trace_mask;
-extern unsigned char adb_trace_output_count;
-void adb_trace_init(void);
-
-# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
-
-
-/* you must define TRACE_TAG before using this macro */
-#if ADB_HOST
-# define D(...) \
- do { \
- if (ADB_TRACING) { \
- int save_errno = errno; \
- adb_mutex_lock(&D_lock); \
- fprintf(stderr, "%s::%s():", \
- __FILE__, __FUNCTION__); \
- errno = save_errno; \
- fprintf(stderr, __VA_ARGS__ ); \
- fflush(stderr); \
- adb_mutex_unlock(&D_lock); \
- errno = save_errno; \
- } \
- } while (0)
-# define DR(...) \
- do { \
- if (ADB_TRACING) { \
- int save_errno = errno; \
- adb_mutex_lock(&D_lock); \
- errno = save_errno; \
- fprintf(stderr, __VA_ARGS__ ); \
- fflush(stderr); \
- adb_mutex_unlock(&D_lock); \
- errno = save_errno; \
- } \
- } while (0)
-# define DD(...) \
- do { \
- int save_errno = errno; \
- adb_mutex_lock(&D_lock); \
- fprintf(stderr, "%s::%s():", \
- __FILE__, __FUNCTION__); \
- errno = save_errno; \
- fprintf(stderr, __VA_ARGS__ ); \
- fflush(stderr); \
- adb_mutex_unlock(&D_lock); \
- errno = save_errno; \
- } while (0)
-#else
-# define D(...) \
- do { \
- if (ADB_TRACING) { \
- __android_log_print( \
- ANDROID_LOG_INFO, \
- __FUNCTION__, \
- __VA_ARGS__ ); \
- } \
- } while (0)
-# define DR(...) \
- do { \
- if (ADB_TRACING) { \
- __android_log_print( \
- ANDROID_LOG_INFO, \
- __FUNCTION__, \
- __VA_ARGS__ ); \
- } \
- } while (0)
-# define DD(...) \
- do { \
- __android_log_print( \
- ANDROID_LOG_INFO, \
- __FUNCTION__, \
- __VA_ARGS__ ); \
- } while (0)
-#endif /* ADB_HOST */
-#else
-# define D(...) ((void)0)
-# define DR(...) ((void)0)
-# define DD(...) ((void)0)
-# define ADB_TRACING 0
-#endif /* ADB_TRACE */
-
-#endif /* __ADB_TRACE_H */
diff --git a/src/devtools/adb/adbd_pcie.init b/src/devtools/adb/adbd_pcie.init
index 078bd10..d8bf1af 100644
--- a/src/devtools/adb/adbd_pcie.init
+++ b/src/devtools/adb/adbd_pcie.init
@@ -7,10 +7,9 @@
start_service() {
echo "start adbd_pcie"
- procd_open_instance adbd_pcie
procd_set_param stdout 1
procd_set_param stderr 1
- procd_set_param env ADBD_TRACE=0
+ procd_open_instance adbd_pcie
procd_set_param command /sbin/adbd_pcie
procd_set_param respawn
procd_close_instance
diff --git a/src/devtools/adb/b64_pton.c b/src/devtools/adb/b64_pton.c
index 351309b..e5c3153 100644
--- a/src/devtools/adb/b64_pton.c
+++ b/src/devtools/adb/b64_pton.c
@@ -170,8 +170,7 @@
static int
b64_pton_do(char const *src, uint8_t *target, size_t targsize)
{
- int state;
- unsigned int tarindex, ch;
+ int tarindex, state, ch;
uint8_t ofs;
state = 0;
@@ -288,8 +287,7 @@
static int
b64_pton_len(char const *src)
{
- int tarindex, state;
- unsigned int ch;
+ int tarindex, state, ch;
uint8_t ofs;
state = 0;
diff --git a/src/devtools/adb/commandline.c b/src/devtools/adb/commandline.c
index 7a48c4c..1a85de2 100644
--- a/src/devtools/adb/commandline.c
+++ b/src/devtools/adb/commandline.c
@@ -41,6 +41,8 @@
static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
void get_my_path(char *s, size_t maxLen);
+int find_sync_dirs(const char *srcarg,
+ char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
int install_app(transport_type transport, char* serial, int argc, char** argv);
int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
@@ -1642,6 +1644,42 @@
return uninstall_app(ttype, serial, argc, argv);
}
+ if(!strcmp(argv[0], "sync")) {
+ char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
+ int listonly = 0;
+
+ int ret;
+ if(argc < 2) {
+ /* No local path was specified. */
+ srcarg = NULL;
+ } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
+ listonly = 1;
+ if (argc == 3) {
+ srcarg = argv[2];
+ } else {
+ srcarg = NULL;
+ }
+ } else if(argc == 2) {
+ /* A local path or "android"/"data" arg was specified. */
+ srcarg = argv[1];
+ } else {
+ return usage();
+ }
+ ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
+ if(ret != 0) return usage();
+
+ if(android_srcpath != NULL)
+ ret = do_sync_sync(android_srcpath, "/system", listonly);
+ if(ret == 0 && vendor_srcpath != NULL)
+ ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
+ if(ret == 0 && data_srcpath != NULL)
+ ret = do_sync_sync(data_srcpath, "/data", listonly);
+
+ free(android_srcpath);
+ free(vendor_srcpath);
+ free(data_srcpath);
+ return ret;
+ }
/* passthrough commands */
@@ -1689,6 +1727,18 @@
return restore(argc, argv);
}
+ if (!strcmp(argv[0], "jdwp")) {
+ int fd = adb_connect("jdwp");
+ if (fd >= 0) {
+ read_and_dump(fd);
+ adb_close(fd);
+ return 0;
+ } else {
+ fprintf(stderr, "error: %s\n", adb_error());
+ return -1;
+ }
+ }
+
/* "adb /?" is a common idiom under Windows */
if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
help();
@@ -1740,6 +1790,53 @@
return adb_commandline(argc, argv);
}
+int find_sync_dirs(const char *srcarg,
+ char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
+{
+ char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
+ struct stat st;
+
+ if(srcarg == NULL) {
+ android_srcdir = product_file("system");
+ data_srcdir = product_file("data");
+ vendor_srcdir = product_file("vendor");
+ /* Check if vendor partition exists */
+ if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
+ vendor_srcdir = NULL;
+ } else {
+ /* srcarg may be "data", "system" or NULL.
+ * if srcarg is NULL, then both data and system are synced
+ */
+ if(strcmp(srcarg, "system") == 0) {
+ android_srcdir = product_file("system");
+ } else if(strcmp(srcarg, "data") == 0) {
+ data_srcdir = product_file("data");
+ } else if(strcmp(srcarg, "vendor") == 0) {
+ vendor_srcdir = product_file("vendor");
+ } else {
+ /* It's not "system", "vendor", or "data".
+ */
+ return 1;
+ }
+ }
+
+ if(android_srcdir_out != NULL)
+ *android_srcdir_out = android_srcdir;
+ else
+ free(android_srcdir);
+
+ if(vendor_srcdir_out != NULL)
+ *vendor_srcdir_out = vendor_srcdir;
+ else
+ free(vendor_srcdir);
+
+ if(data_srcdir_out != NULL)
+ *data_srcdir_out = data_srcdir;
+ else
+ free(data_srcdir);
+ return 0;
+}
+
static int pm_command(transport_type transport, char* serial,
int argc, char** argv)
{
diff --git a/src/devtools/adb/console.c b/src/devtools/adb/console.c
new file mode 100644
index 0000000..b813d33
--- /dev/null
+++ b/src/devtools/adb/console.c
@@ -0,0 +1,45 @@
+#include "sysdeps.h"
+#include "adb.h"
+#include "adb_client.h"
+#include <stdio.h>
+
+static int connect_to_console(void)
+{
+ int fd, port;
+
+ port = adb_get_emulator_console_port();
+ if (port < 0) {
+ if (port == -2)
+ fprintf(stderr, "error: more than one emulator detected. use -s option\n");
+ else
+ fprintf(stderr, "error: no emulator detected\n");
+ return -1;
+ }
+ fd = socket_loopback_client( port, SOCK_STREAM );
+ if (fd < 0) {
+ fprintf(stderr, "error: could not connect to TCP port %d\n", port);
+ return -1;
+ }
+ return fd;
+}
+
+
+int adb_send_emulator_command(int argc, char** argv)
+{
+ int fd, nn;
+
+ fd = connect_to_console();
+ if (fd < 0)
+ return 1;
+
+#define QUIT "quit\n"
+
+ for (nn = 1; nn < argc; nn++) {
+ adb_write( fd, argv[nn], strlen(argv[nn]) );
+ adb_write( fd, (nn == argc-1) ? "\n" : " ", 1 );
+ }
+ adb_write( fd, QUIT, sizeof(QUIT)-1 );
+ adb_close(fd);
+
+ return 0;
+}
diff --git a/src/devtools/adb/file_sync_client.c b/src/devtools/adb/file_sync_client.c
index c37e321..ad59e81 100644
--- a/src/devtools/adb/file_sync_client.c
+++ b/src/devtools/adb/file_sync_client.c
@@ -1014,3 +1014,22 @@
}
}
+int do_sync_sync(const char *lpath, const char *rpath, int listonly)
+{
+ fprintf(stderr,"syncing %s...\n",rpath);
+
+ int fd = adb_connect("sync:");
+ if(fd < 0) {
+ fprintf(stderr,"error: %s\n", adb_error());
+ return 1;
+ }
+
+ BEGIN();
+ if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){
+ return 1;
+ } else {
+ END();
+ sync_quit(fd);
+ return 0;
+ }
+}
diff --git a/src/devtools/adb/file_sync_service.c b/src/devtools/adb/file_sync_service.c
index ba87c2c..b2a8bc6 100644
--- a/src/devtools/adb/file_sync_service.c
+++ b/src/devtools/adb/file_sync_service.c
@@ -111,7 +111,7 @@
struct dirent *de;
struct stat st;
syncmsg msg;
- unsigned int len;
+ int len;
char tmp[1024 + 256 + 1];
char *fname;
diff --git a/src/devtools/adb/framebuffer_service.c b/src/devtools/adb/framebuffer_service.c
new file mode 100644
index 0000000..1c5cd2f
--- /dev/null
+++ b/src/devtools/adb/framebuffer_service.c
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "fdevent.h"
+#include "adb.h"
+
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <cutils/fs.h>
+
+/* TODO:
+** - sync with vsync to avoid tearing
+*/
+/* This version number defines the format of the fbinfo struct.
+ It must match versioning in ddms where this data is consumed. */
+#define DDMS_RAWIMAGE_VERSION 1
+struct fbinfo {
+ unsigned int version;
+ unsigned int bpp;
+ unsigned int size;
+ unsigned int width;
+ unsigned int height;
+ unsigned int red_offset;
+ unsigned int red_length;
+ unsigned int blue_offset;
+ unsigned int blue_length;
+ unsigned int green_offset;
+ unsigned int green_length;
+ unsigned int alpha_offset;
+ unsigned int alpha_length;
+} __attribute__((packed));
+
+void framebuffer_service(int fd, void *cookie)
+{
+ struct fbinfo fbinfo;
+ unsigned int i, bsize;
+ char buf[640];
+ int fd_screencap;
+ int w, h, f;
+ int fds[2];
+
+ if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail;
+
+ pid_t pid = fork();
+ if (pid < 0) goto done;
+
+ if (pid == 0) {
+ dup2(fds[1], STDOUT_FILENO);
+ close(fds[0]);
+ close(fds[1]);
+ const char* command = "screencap";
+ const char *args[2] = {command, NULL};
+ execvp(command, (char**)args);
+ exit(1);
+ }
+
+ fd_screencap = fds[0];
+
+ /* read w, h & format */
+ if(readx(fd_screencap, &w, 4)) goto done;
+ if(readx(fd_screencap, &h, 4)) goto done;
+ if(readx(fd_screencap, &f, 4)) goto done;
+
+ fbinfo.version = DDMS_RAWIMAGE_VERSION;
+ /* see hardware/hardware.h */
+ switch (f) {
+ case 1: /* RGBA_8888 */
+ fbinfo.bpp = 32;
+ fbinfo.size = w * h * 4;
+ fbinfo.width = w;
+ fbinfo.height = h;
+ fbinfo.red_offset = 0;
+ fbinfo.red_length = 8;
+ fbinfo.green_offset = 8;
+ fbinfo.green_length = 8;
+ fbinfo.blue_offset = 16;
+ fbinfo.blue_length = 8;
+ fbinfo.alpha_offset = 24;
+ fbinfo.alpha_length = 8;
+ break;
+ case 2: /* RGBX_8888 */
+ fbinfo.bpp = 32;
+ fbinfo.size = w * h * 4;
+ fbinfo.width = w;
+ fbinfo.height = h;
+ fbinfo.red_offset = 0;
+ fbinfo.red_length = 8;
+ fbinfo.green_offset = 8;
+ fbinfo.green_length = 8;
+ fbinfo.blue_offset = 16;
+ fbinfo.blue_length = 8;
+ fbinfo.alpha_offset = 24;
+ fbinfo.alpha_length = 0;
+ break;
+ case 3: /* RGB_888 */
+ fbinfo.bpp = 24;
+ fbinfo.size = w * h * 3;
+ fbinfo.width = w;
+ fbinfo.height = h;
+ fbinfo.red_offset = 0;
+ fbinfo.red_length = 8;
+ fbinfo.green_offset = 8;
+ fbinfo.green_length = 8;
+ fbinfo.blue_offset = 16;
+ fbinfo.blue_length = 8;
+ fbinfo.alpha_offset = 24;
+ fbinfo.alpha_length = 0;
+ break;
+ case 4: /* RGB_565 */
+ fbinfo.bpp = 16;
+ fbinfo.size = w * h * 2;
+ fbinfo.width = w;
+ fbinfo.height = h;
+ fbinfo.red_offset = 11;
+ fbinfo.red_length = 5;
+ fbinfo.green_offset = 5;
+ fbinfo.green_length = 6;
+ fbinfo.blue_offset = 0;
+ fbinfo.blue_length = 5;
+ fbinfo.alpha_offset = 0;
+ fbinfo.alpha_length = 0;
+ break;
+ case 5: /* BGRA_8888 */
+ fbinfo.bpp = 32;
+ fbinfo.size = w * h * 4;
+ fbinfo.width = w;
+ fbinfo.height = h;
+ fbinfo.red_offset = 16;
+ fbinfo.red_length = 8;
+ fbinfo.green_offset = 8;
+ fbinfo.green_length = 8;
+ fbinfo.blue_offset = 0;
+ fbinfo.blue_length = 8;
+ fbinfo.alpha_offset = 24;
+ fbinfo.alpha_length = 8;
+ break;
+ default:
+ goto done;
+ }
+
+ /* write header */
+ if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
+
+ /* write data */
+ for(i = 0; i < fbinfo.size; i += bsize) {
+ bsize = sizeof(buf);
+ if (i + bsize > fbinfo.size)
+ bsize = fbinfo.size - i;
+ if(readx(fd_screencap, buf, bsize)) goto done;
+ if(writex(fd, buf, bsize)) goto done;
+ }
+
+done:
+ TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
+
+ close(fds[0]);
+ close(fds[1]);
+pipefail:
+ close(fd);
+}
diff --git a/src/devtools/adb/jdwp_service.c b/src/devtools/adb/jdwp_service.c
new file mode 100644
index 0000000..cd62b55
--- /dev/null
+++ b/src/devtools/adb/jdwp_service.c
@@ -0,0 +1,735 @@
+/* implement the "debug-ports" and "track-debug-ports" device services */
+#include "sysdeps.h"
+#define TRACE_TAG TRACE_JDWP
+#include "adb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* here's how these things work.
+
+ when adbd starts, it creates a unix server socket
+ named @vm-debug-control (@ is a shortcut for "first byte is zero"
+ to use the private namespace instead of the file system)
+
+ when a new JDWP daemon thread starts in a new VM process, it creates
+ a connection to @vm-debug-control to announce its availability.
+
+
+ JDWP thread @vm-debug-control
+ | |
+ |-------------------------------> |
+ | hello I'm in process <pid> |
+ | |
+ | |
+
+ the connection is kept alive. it will be closed automatically if
+ the JDWP process terminates (this allows adbd to detect dead
+ processes).
+
+ adbd thus maintains a list of "active" JDWP processes. it can send
+ its content to clients through the "device:debug-ports" service,
+ or even updates through the "device:track-debug-ports" service.
+
+ when a debugger wants to connect, it simply runs the command
+ equivalent to "adb forward tcp:<hostport> jdwp:<pid>"
+
+ "jdwp:<pid>" is a new forward destination format used to target
+ a given JDWP process on the device. when sutch a request arrives,
+ adbd does the following:
+
+ - first, it calls socketpair() to create a pair of equivalent
+ sockets.
+
+ - it attaches the first socket in the pair to a local socket
+ which is itself attached to the transport's remote socket:
+
+
+ - it sends the file descriptor of the second socket directly
+ to the JDWP process with the help of sendmsg()
+
+
+ JDWP thread @vm-debug-control
+ | |
+ | <----------------------|
+ | OK, try this file descriptor |
+ | |
+ | |
+
+ then, the JDWP thread uses this new socket descriptor as its
+ pass-through connection to the debugger (and receives the
+ JDWP-Handshake message, answers to it, etc...)
+
+ this gives the following graphics:
+ ____________________________________
+ | |
+ | ADB Server (host) |
+ | |
+ Debugger <---> LocalSocket <----> RemoteSocket |
+ | ^^ |
+ |___________________________||_______|
+ ||
+ Transport ||
+ (TCP for emulator - USB for device) ||
+ ||
+ ___________________________||_______
+ | || |
+ | ADBD (device) || |
+ | VV |
+ JDWP <======> LocalSocket <----> RemoteSocket |
+ | |
+ |____________________________________|
+
+ due to the way adb works, this doesn't need a special socket
+ type or fancy handling of socket termination if either the debugger
+ or the JDWP process closes the connection.
+
+ THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
+ TO HAVE A BETTER IDEA, LET ME KNOW - Digit
+
+**********************************************************************/
+
+/** JDWP PID List Support Code
+ ** for each JDWP process, we record its pid and its connected socket
+ **/
+
+#define MAX_OUT_FDS 4
+
+#if !ADB_HOST
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+typedef struct JdwpProcess JdwpProcess;
+struct JdwpProcess {
+ JdwpProcess* next;
+ JdwpProcess* prev;
+ int pid;
+ int socket;
+ fdevent* fde;
+
+ char in_buff[4]; /* input character to read PID */
+ int in_len; /* number from JDWP process */
+
+ int out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
+ int out_count; /* to send to the JDWP process */
+};
+
+static JdwpProcess _jdwp_list;
+
+static int
+jdwp_process_list( char* buffer, int bufferlen )
+{
+ char* end = buffer + bufferlen;
+ char* p = buffer;
+ JdwpProcess* proc = _jdwp_list.next;
+
+ for ( ; proc != &_jdwp_list; proc = proc->next ) {
+ int len;
+
+ /* skip transient connections */
+ if (proc->pid < 0)
+ continue;
+
+ len = snprintf(p, end-p, "%d\n", proc->pid);
+ if (p + len >= end)
+ break;
+ p += len;
+ }
+ p[0] = 0;
+ return (p - buffer);
+}
+
+
+static int
+jdwp_process_list_msg( char* buffer, int bufferlen )
+{
+ char head[5];
+ int len = jdwp_process_list( buffer+4, bufferlen-4 );
+ snprintf(head, sizeof head, "%04x", len);
+ memcpy(buffer, head, 4);
+ return len + 4;
+}
+
+
+static void jdwp_process_list_updated(void);
+
+static void
+jdwp_process_free( JdwpProcess* proc )
+{
+ if (proc) {
+ int n;
+
+ proc->prev->next = proc->next;
+ proc->next->prev = proc->prev;
+
+ if (proc->socket >= 0) {
+ adb_shutdown(proc->socket);
+ adb_close(proc->socket);
+ proc->socket = -1;
+ }
+
+ if (proc->fde != NULL) {
+ fdevent_destroy(proc->fde);
+ proc->fde = NULL;
+ }
+ proc->pid = -1;
+
+ for (n = 0; n < proc->out_count; n++) {
+ adb_close(proc->out_fds[n]);
+ }
+ proc->out_count = 0;
+
+ free(proc);
+
+ jdwp_process_list_updated();
+ }
+}
+
+
+static void jdwp_process_event(int, unsigned, void*); /* forward */
+
+
+static JdwpProcess*
+jdwp_process_alloc( int socket )
+{
+ JdwpProcess* proc = calloc(1,sizeof(*proc));
+
+ if (proc == NULL) {
+ D("not enough memory to create new JDWP process\n");
+ return NULL;
+ }
+
+ proc->socket = socket;
+ proc->pid = -1;
+ proc->next = proc;
+ proc->prev = proc;
+
+ proc->fde = fdevent_create( socket, jdwp_process_event, proc );
+ if (proc->fde == NULL) {
+ D("could not create fdevent for new JDWP process\n" );
+ free(proc);
+ return NULL;
+ }
+
+ proc->fde->state |= FDE_DONT_CLOSE;
+ proc->in_len = 0;
+ proc->out_count = 0;
+
+ /* append to list */
+ proc->next = &_jdwp_list;
+ proc->prev = proc->next->prev;
+
+ proc->prev->next = proc;
+ proc->next->prev = proc;
+
+ /* start by waiting for the PID */
+ fdevent_add(proc->fde, FDE_READ);
+
+ return proc;
+}
+
+
+static void
+jdwp_process_event( int socket, unsigned events, void* _proc )
+{
+ JdwpProcess* proc = _proc;
+
+ if (events & FDE_READ) {
+ if (proc->pid < 0) {
+ /* read the PID as a 4-hexchar string */
+ char* p = proc->in_buff + proc->in_len;
+ int size = 4 - proc->in_len;
+ char temp[5];
+ while (size > 0) {
+ int len = recv( socket, p, size, 0 );
+ if (len < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN)
+ return;
+ /* this can fail here if the JDWP process crashes very fast */
+ D("weird unknown JDWP process failure: %s\n",
+ strerror(errno));
+
+ goto CloseProcess;
+ }
+ if (len == 0) { /* end of stream ? */
+ D("weird end-of-stream from unknown JDWP process\n");
+ goto CloseProcess;
+ }
+ p += len;
+ proc->in_len += len;
+ size -= len;
+ }
+ /* we have read 4 characters, now decode the pid */
+ memcpy(temp, proc->in_buff, 4);
+ temp[4] = 0;
+
+ if (sscanf( temp, "%04x", &proc->pid ) != 1) {
+ D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
+ goto CloseProcess;
+ }
+
+ /* all is well, keep reading to detect connection closure */
+ D("Adding pid %d to jdwp process list\n", proc->pid);
+ jdwp_process_list_updated();
+ }
+ else
+ {
+ /* the pid was read, if we get there it's probably because the connection
+ * was closed (e.g. the JDWP process exited or crashed) */
+ char buf[32];
+
+ for (;;) {
+ int len = recv(socket, buf, sizeof(buf), 0);
+
+ if (len <= 0) {
+ if (len < 0 && errno == EINTR)
+ continue;
+ if (len < 0 && errno == EAGAIN)
+ return;
+ else {
+ D("terminating JDWP %d connection: %s\n", proc->pid,
+ strerror(errno));
+ break;
+ }
+ }
+ else {
+ D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
+ proc->pid, len );
+ }
+ }
+
+ CloseProcess:
+ if (proc->pid >= 0)
+ D( "remove pid %d to jdwp process list\n", proc->pid );
+ jdwp_process_free(proc);
+ return;
+ }
+ }
+
+ if (events & FDE_WRITE) {
+ D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
+ proc->pid, proc->out_count, proc->out_fds[0]);
+ if (proc->out_count > 0) {
+ int fd = proc->out_fds[0];
+ int n, ret;
+ struct cmsghdr* cmsg;
+ struct msghdr msg;
+ struct iovec iov;
+ char dummy = '!';
+ char buffer[sizeof(struct cmsghdr) + sizeof(int)];
+ int flags;
+
+ iov.iov_base = &dummy;
+ iov.iov_len = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = buffer;
+ msg.msg_controllen = sizeof(buffer);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = msg.msg_controllen;
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ ((int*)CMSG_DATA(cmsg))[0] = fd;
+
+ flags = fcntl(proc->socket,F_GETFL,0);
+
+ if (flags == -1) {
+ D("failed to get cntl flags for socket %d: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+
+ }
+
+ if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
+ D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
+
+ for (;;) {
+ ret = sendmsg(proc->socket, &msg, 0);
+ if (ret >= 0) {
+ adb_close(fd);
+ break;
+ }
+ if (errno == EINTR)
+ continue;
+ D("sending new file descriptor to JDWP %d failed: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
+
+ D("sent file descriptor %d to JDWP process %d\n",
+ fd, proc->pid);
+
+ for (n = 1; n < proc->out_count; n++)
+ proc->out_fds[n-1] = proc->out_fds[n];
+
+ if (fcntl(proc->socket, F_SETFL, flags) == -1) {
+ D("failed to set O_NONBLOCK flag for socket %d: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
+
+ if (--proc->out_count == 0)
+ fdevent_del( proc->fde, FDE_WRITE );
+ }
+ }
+}
+
+
+int
+create_jdwp_connection_fd(int pid)
+{
+ JdwpProcess* proc = _jdwp_list.next;
+
+ D("looking for pid %d in JDWP process list\n", pid);
+ for ( ; proc != &_jdwp_list; proc = proc->next ) {
+ if (proc->pid == pid) {
+ goto FoundIt;
+ }
+ }
+ D("search failed !!\n");
+ return -1;
+
+FoundIt:
+ {
+ int fds[2];
+
+ if (proc->out_count >= MAX_OUT_FDS) {
+ D("%s: too many pending JDWP connection for pid %d\n",
+ __FUNCTION__, pid);
+ return -1;
+ }
+
+ if (adb_socketpair(fds) < 0) {
+ D("%s: socket pair creation failed: %s\n",
+ __FUNCTION__, strerror(errno));
+ return -1;
+ }
+
+ proc->out_fds[ proc->out_count ] = fds[1];
+ if (++proc->out_count == 1)
+ fdevent_add( proc->fde, FDE_WRITE );
+
+ return fds[0];
+ }
+}
+
+/** VM DEBUG CONTROL SOCKET
+ **
+ ** we do implement a custom asocket to receive the data
+ **/
+
+/* name of the debug control Unix socket */
+#define JDWP_CONTROL_NAME "\0jdwp-control"
+#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME)-1)
+
+typedef struct {
+ int listen_socket;
+ fdevent* fde;
+
+} JdwpControl;
+
+
+static void
+jdwp_control_event(int s, unsigned events, void* user);
+
+
+static int
+jdwp_control_init( JdwpControl* control,
+ const char* sockname,
+ int socknamelen )
+{
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ int s;
+ int maxpath = sizeof(addr.sun_path);
+ int pathlen = socknamelen;
+
+ if (pathlen >= maxpath) {
+ D( "vm debug control socket name too long (%d extra chars)\n",
+ pathlen+1-maxpath );
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, sockname, socknamelen);
+
+ s = socket( AF_UNIX, SOCK_STREAM, 0 );
+ if (s < 0) {
+ D( "could not create vm debug control socket. %d: %s\n",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ addrlen = (pathlen + sizeof(addr.sun_family));
+
+ if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
+ D( "could not bind vm debug control socket: %d: %s\n",
+ errno, strerror(errno) );
+ adb_close(s);
+ return -1;
+ }
+
+ if ( listen(s, 4) < 0 ) {
+ D("listen failed in jdwp control socket: %d: %s\n",
+ errno, strerror(errno));
+ adb_close(s);
+ return -1;
+ }
+
+ control->listen_socket = s;
+
+ control->fde = fdevent_create(s, jdwp_control_event, control);
+ if (control->fde == NULL) {
+ D( "could not create fdevent for jdwp control socket\n" );
+ adb_close(s);
+ return -1;
+ }
+
+ /* only wait for incoming connections */
+ fdevent_add(control->fde, FDE_READ);
+ close_on_exec(s);
+
+ D("jdwp control socket started (%d)\n", control->listen_socket);
+ return 0;
+}
+
+
+static void
+jdwp_control_event( int s, unsigned events, void* _control )
+{
+ JdwpControl* control = (JdwpControl*) _control;
+
+ if (events & FDE_READ) {
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ int s = -1;
+ JdwpProcess* proc;
+
+ do {
+ s = adb_socket_accept( control->listen_socket, &addr, &addrlen );
+ if (s < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno == ECONNABORTED) {
+ /* oops, the JDWP process died really quick */
+ D("oops, the JDWP process died really quick\n");
+ return;
+ }
+ /* the socket is probably closed ? */
+ D( "weird accept() failed on jdwp control socket: %s\n",
+ strerror(errno) );
+ return;
+ }
+ }
+ while (s < 0);
+
+ proc = jdwp_process_alloc( s );
+ if (proc == NULL)
+ return;
+ }
+}
+
+
+static JdwpControl _jdwp_control;
+
+/** "jdwp" local service implementation
+ ** this simply returns the list of known JDWP process pids
+ **/
+
+typedef struct {
+ asocket socket;
+ int pass;
+} JdwpSocket;
+
+static void
+jdwp_socket_close( asocket* s )
+{
+ asocket* peer = s->peer;
+
+ remove_socket(s);
+
+ if (peer) {
+ peer->peer = NULL;
+ peer->close(peer);
+ }
+ free(s);
+}
+
+static int
+jdwp_socket_enqueue( asocket* s, apacket* p )
+{
+ /* you can't write to this asocket */
+ put_apacket(p);
+ s->peer->close(s->peer);
+ return -1;
+}
+
+
+static void
+jdwp_socket_ready( asocket* s )
+{
+ JdwpSocket* jdwp = (JdwpSocket*)s;
+ asocket* peer = jdwp->socket.peer;
+
+ /* on the first call, send the list of pids,
+ * on the second one, close the connection
+ */
+ if (jdwp->pass == 0) {
+ apacket* p = get_apacket();
+ p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);
+ peer->enqueue(peer, p);
+ jdwp->pass = 1;
+ }
+ else {
+ peer->close(peer);
+ }
+}
+
+asocket*
+create_jdwp_service_socket( void )
+{
+ JdwpSocket* s = calloc(sizeof(*s),1);
+
+ if (s == NULL)
+ return NULL;
+
+ install_local_socket(&s->socket);
+
+ s->socket.ready = jdwp_socket_ready;
+ s->socket.enqueue = jdwp_socket_enqueue;
+ s->socket.close = jdwp_socket_close;
+ s->pass = 0;
+
+ return &s->socket;
+}
+
+/** "track-jdwp" local service implementation
+ ** this periodically sends the list of known JDWP process pids
+ ** to the client...
+ **/
+
+typedef struct JdwpTracker JdwpTracker;
+
+struct JdwpTracker {
+ asocket socket;
+ JdwpTracker* next;
+ JdwpTracker* prev;
+ int need_update;
+};
+
+static JdwpTracker _jdwp_trackers_list;
+
+
+static void
+jdwp_process_list_updated(void)
+{
+ char buffer[1024];
+ int len;
+ JdwpTracker* t = _jdwp_trackers_list.next;
+
+ len = jdwp_process_list_msg(buffer, sizeof(buffer));
+
+ for ( ; t != &_jdwp_trackers_list; t = t->next ) {
+ apacket* p = get_apacket();
+ asocket* peer = t->socket.peer;
+ memcpy(p->data, buffer, len);
+ p->len = len;
+ peer->enqueue( peer, p );
+ }
+}
+
+static void
+jdwp_tracker_close( asocket* s )
+{
+ JdwpTracker* tracker = (JdwpTracker*) s;
+ asocket* peer = s->peer;
+
+ if (peer) {
+ peer->peer = NULL;
+ peer->close(peer);
+ }
+
+ remove_socket(s);
+
+ tracker->prev->next = tracker->next;
+ tracker->next->prev = tracker->prev;
+
+ free(s);
+}
+
+static void
+jdwp_tracker_ready( asocket* s )
+{
+ JdwpTracker* t = (JdwpTracker*) s;
+
+ if (t->need_update) {
+ apacket* p = get_apacket();
+ t->need_update = 0;
+ p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data));
+ s->peer->enqueue(s->peer, p);
+ }
+}
+
+static int
+jdwp_tracker_enqueue( asocket* s, apacket* p )
+{
+ /* you can't write to this socket */
+ put_apacket(p);
+ s->peer->close(s->peer);
+ return -1;
+}
+
+
+asocket*
+create_jdwp_tracker_service_socket( void )
+{
+ JdwpTracker* t = calloc(sizeof(*t),1);
+
+ if (t == NULL)
+ return NULL;
+
+ t->next = &_jdwp_trackers_list;
+ t->prev = t->next->prev;
+
+ t->next->prev = t;
+ t->prev->next = t;
+
+ install_local_socket(&t->socket);
+
+ t->socket.ready = jdwp_tracker_ready;
+ t->socket.enqueue = jdwp_tracker_enqueue;
+ t->socket.close = jdwp_tracker_close;
+ t->need_update = 1;
+
+ return &t->socket;
+}
+
+
+int
+init_jdwp(void)
+{
+ _jdwp_list.next = &_jdwp_list;
+ _jdwp_list.prev = &_jdwp_list;
+
+ _jdwp_trackers_list.next = &_jdwp_trackers_list;
+ _jdwp_trackers_list.prev = &_jdwp_trackers_list;
+
+ return jdwp_control_init( &_jdwp_control,
+ JDWP_CONTROL_NAME,
+ JDWP_CONTROL_NAME_LEN );
+}
+
+#endif /* !ADB_HOST */
+
diff --git a/src/devtools/adb/logd_write.c b/src/devtools/adb/logd_write.c
index 384f62e..b2668ce 100644
--- a/src/devtools/adb/logd_write.c
+++ b/src/devtools/adb/logd_write.c
@@ -403,8 +403,7 @@
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);
- printf("%s(): %s", tag, buf);
- return fflush(stdout);
+ return __android_log_write(prio, tag, buf);
}
int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
diff --git a/src/devtools/adb/properties.c b/src/devtools/adb/properties.c
index 520688b..20069b0 100644
--- a/src/devtools/adb/properties.c
+++ b/src/devtools/adb/properties.c
@@ -354,17 +354,12 @@
char ename[PROPERTY_KEY_MAX + 6];
char *p;
int len;
-
+
len = strlen(key);
if(len >= PROPERTY_KEY_MAX) return -1;
-
- if (strcmp(key, "persist.adb.trace_mask")) {
- memcpy(ename, "PROP_", 5);
- memcpy(ename + 5, key, len + 1);
- } else {
- memcpy(ename, "ADBD_TRACE", 11);
- }
-
+ memcpy(ename, "PROP_", 5);
+ memcpy(ename + 5, key, len + 1);
+
mutex_lock(&env_lock);
p = getenv(ename);
@@ -373,7 +368,7 @@
if(len >= PROPERTY_VALUE_MAX) {
len = PROPERTY_VALUE_MAX - 1;
}
-
+
if((len == 0) && default_value) {
len = strlen(default_value);
memcpy(value, default_value, len + 1);
@@ -424,7 +419,7 @@
return 0;
}
-#elif defined(UCI_PROPERTY_SUPPORT)
+#else
/* UCI configuration system implementation for OpenWrt */
#include <uci.h>
@@ -455,8 +450,7 @@
if (UCI_OK != uci_load(uciCtx, UCI_CONFIG_FILE, &pkg)) {
if (default_value) {
- unsigned int len = strlen(default_value);
- len = len < PROPERTY_VALUE_MAX ? len : PROPERTY_VALUE_MAX-1;
+ int len = strlen(default_value);
memcpy(value, default_value, len);
value[len] = '\0';
retValue = 1;
@@ -471,10 +465,7 @@
if (!strncmp(pValueData, ":empty", strlen(":empty"))) {
value[0] = '\0';
} else {
- unsigned int len = strlen(pValueData);
- len = len < PROPERTY_VALUE_MAX ? len : PROPERTY_VALUE_MAX-1;
- strncpy(value, pValueData, len);
- value[len] = '\0';
+ strncpy(value, pValueData, strlen(pValueData));
}
retValue = 1;
D("property_get, %s: %s\n", key, value);
@@ -482,8 +473,7 @@
}
if (!retValue) {
if (default_value) {
- unsigned int len = strlen(default_value);
- len = len < PROPERTY_VALUE_MAX ? len : PROPERTY_VALUE_MAX-1;
+ int len = strlen(default_value);
memcpy(value, default_value, len);
value[len] = '\0';
retValue = 1;
@@ -553,29 +543,4 @@
return 0;
}
-#else
-
-int property_get(const char *key, char *value, const char *default_value) {
- if (NULL == key || NULL == value) {
- return 0;
- }
- int retValue = 0;
-
- if (default_value) {
- int len = strlen(default_value);
- memcpy(value, default_value, len);
- value[len] = '\0';
- retValue = 1;
- }
- return retValue;
-}
-
-int property_set(const char *key, const char *new_value) {
- return 0;
-}
-
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
- void *cookie) {
- return 0;
-}
#endif
diff --git a/src/devtools/adb/rsa.c b/src/devtools/adb/rsa.c
new file mode 100644
index 0000000..171c437
--- /dev/null
+++ b/src/devtools/adb/rsa.c
@@ -0,0 +1,310 @@
+/* rsa.c
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
+
+// a[] -= mod
+static void subM(const RSAPublicKey* key,
+ uint32_t* a) {
+ int64_t A = 0;
+ int i;
+ for (i = 0; i < key->len; ++i) {
+ A += (uint64_t)a[i] - key->n[i];
+ a[i] = (uint32_t)A;
+ A >>= 32;
+ }
+}
+
+// return a[] >= mod
+static int geM(const RSAPublicKey* key,
+ const uint32_t* a) {
+ int i;
+ for (i = key->len; i;) {
+ --i;
+ if (a[i] < key->n[i]) return 0;
+ if (a[i] > key->n[i]) return 1;
+ }
+ return 1; // equal
+}
+
+// montgomery c[] += a * b[] / R % mod
+static void montMulAdd(const RSAPublicKey* key,
+ uint32_t* c,
+ const uint32_t a,
+ const uint32_t* b) {
+ uint64_t A = (uint64_t)a * b[0] + c[0];
+ uint32_t d0 = (uint32_t)A * key->n0inv;
+ uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+ int i;
+
+ for (i = 1; i < key->len; ++i) {
+ A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+ B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+ c[i - 1] = (uint32_t)B;
+ }
+
+ A = (A >> 32) + (B >> 32);
+
+ c[i - 1] = (uint32_t)A;
+
+ if (A >> 32) {
+ subM(key, c);
+ }
+}
+
+// montgomery c[] = a[] * b[] / R % mod
+static void montMul(const RSAPublicKey* key,
+ uint32_t* c,
+ const uint32_t* a,
+ const uint32_t* b) {
+ int i;
+ for (i = 0; i < key->len; ++i) {
+ c[i] = 0;
+ }
+ for (i = 0; i < key->len; ++i) {
+ montMulAdd(key, c, a[i], b);
+ }
+}
+
+// In-place public exponentiation.
+// Input and output big-endian byte array in inout.
+static void modpow(const RSAPublicKey* key,
+ uint8_t* inout) {
+ uint32_t a[RSANUMWORDS];
+ uint32_t aR[RSANUMWORDS];
+ uint32_t aaR[RSANUMWORDS];
+ uint32_t* aaa = 0;
+ int i;
+
+ // Convert from big endian byte array to little endian word array.
+ for (i = 0; i < key->len; ++i) {
+ uint32_t tmp =
+ (inout[((key->len - 1 - i) * 4) + 0] << 24) |
+ (inout[((key->len - 1 - i) * 4) + 1] << 16) |
+ (inout[((key->len - 1 - i) * 4) + 2] << 8) |
+ (inout[((key->len - 1 - i) * 4) + 3] << 0);
+ a[i] = tmp;
+ }
+
+ if (key->exponent == 65537) {
+ aaa = aaR; // Re-use location.
+ montMul(key, aR, a, key->rr); // aR = a * RR / R mod M
+ for (i = 0; i < 16; i += 2) {
+ montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M
+ montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M
+ }
+ montMul(key, aaa, aR, a); // aaa = aR * a / R mod M
+ } else if (key->exponent == 3) {
+ aaa = aR; // Re-use location.
+ montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
+ montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
+ montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
+ } else {
+ return; // avoid NULL aaa caused exceptions
+ }
+
+ // Make sure aaa < mod; aaa is at most 1x mod too large.
+ if (geM(key, aaa)) {
+ subM(key, aaa);
+ }
+
+ // Convert to bigendian byte array
+ for (i = key->len - 1; i >= 0; --i) {
+ uint32_t tmp = aaa[i];
+ *inout++ = tmp >> 24;
+ *inout++ = tmp >> 16;
+ *inout++ = tmp >> 8;
+ *inout++ = tmp >> 0;
+ }
+}
+
+// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
+// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
+// other flavor which omits the optional parameter entirely). This code does not
+// accept signatures without the optional parameter.
+
+/*
+static const uint8_t sha_padding[RSANUMBYTES] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
+ 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00, 0x04, 0x14,
+
+ // 20 bytes of hash go here.
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+*/
+
+// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
+ 0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
+ 0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
+ 0x7c, 0xfb, 0xf1, 0x67
+};
+
+/*
+static const uint8_t sha256_padding[RSANUMBYTES] = {
+ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
+ 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+ 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
+
+ // 32 bytes of hash go here.
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+*/
+
+// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
+ 0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
+ 0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
+ 0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
+ 0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
+};
+
+// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
+// Both e=3 and e=65537 are supported. hash_len may be
+// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
+// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other
+// values are supported.
+//
+// Returns 1 on successful verification, 0 on failure.
+int RSA_verify(const RSAPublicKey *key,
+ const uint8_t *signature,
+ const int len,
+ const uint8_t *hash,
+ const int hash_len) {
+ uint8_t buf[RSANUMBYTES];
+ int i;
+ const uint8_t* padding_hash;
+
+ if (key->len != RSANUMWORDS) {
+ return 0; // Wrong key passed in.
+ }
+
+ if (len != sizeof(buf)) {
+ return 0; // Wrong input length.
+ }
+
+ if (hash_len != SHA_DIGEST_SIZE &&
+ hash_len != SHA256_DIGEST_SIZE) {
+ return 0; // Unsupported hash.
+ }
+
+ if (key->exponent != 3 && key->exponent != 65537) {
+ return 0; // Unsupported exponent.
+ }
+
+ for (i = 0; i < len; ++i) { // Copy input to local workspace.
+ buf[i] = signature[i];
+ }
+
+ modpow(key, buf); // In-place exponentiation.
+
+ // Xor sha portion, so it all becomes 00 iff equal.
+ for (i = len - hash_len; i < len; ++i) {
+ buf[i] ^= *hash++;
+ }
+
+ // Hash resulting buf, in-place.
+ switch (hash_len) {
+ case SHA_DIGEST_SIZE:
+ padding_hash = kExpectedPadShaRsa2048;
+ SHA_hash(buf, len, buf);
+ break;
+ case SHA256_DIGEST_SIZE:
+ padding_hash = kExpectedPadSha256Rsa2048;
+ SHA256_hash(buf, len, buf);
+ break;
+ default:
+ return 0;
+ }
+
+ // Compare against expected hash value.
+ for (i = 0; i < hash_len; ++i) {
+ if (buf[i] != padding_hash[i]) {
+ return 0;
+ }
+ }
+
+ return 1; // All checked out OK.
+}
diff --git a/src/devtools/adb/services.c b/src/devtools/adb/services.c
index 1527ef8..1360782 100644
--- a/src/devtools/adb/services.c
+++ b/src/devtools/adb/services.c
@@ -440,6 +440,10 @@
#if !ADB_HOST
} else if(!strncmp("dev:", name, 4)) {
ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
+ } else if(!strncmp(name, "framebuffer:", 12)) {
+ ret = create_service_thread(framebuffer_service, 0);
+ } else if (!strncmp(name, "jdwp:", 5)) {
+ ret = create_jdwp_connection_fd(atoi(name+5));
} else if(!HOST && !strncmp(name, "shell:", 6)) {
ret = create_subproc_thread(name + 6, SUBPROC_PTY);
} else if(!HOST && !strncmp(name, "exec:", 5)) {
diff --git a/src/devtools/adb/sha.c b/src/devtools/adb/sha.c
index a637f24..5bef32e 100644
--- a/src/devtools/adb/sha.c
+++ b/src/devtools/adb/sha.c
@@ -105,7 +105,7 @@
void SHA_update(SHA_CTX* ctx, const void* data, int len) {
- unsigned int i = (unsigned int) (ctx->count & 63);
+ int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
diff --git a/src/devtools/adb/sha256.c b/src/devtools/adb/sha256.c
index 6086b08..eb6e308 100644
--- a/src/devtools/adb/sha256.c
+++ b/src/devtools/adb/sha256.c
@@ -134,7 +134,7 @@
void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
- unsigned int i = (unsigned int) (ctx->count & 63);
+ int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
diff --git a/src/devtools/adb/sockets.c b/src/devtools/adb/sockets.c
index e4e0df3..3c2773c 100644
--- a/src/devtools/adb/sockets.c
+++ b/src/devtools/adb/sockets.c
@@ -436,6 +436,14 @@
char debug[PROPERTY_VALUE_MAX];
#endif
+#if !ADB_HOST
+ if (!strcmp(name,"jdwp")) {
+ return create_jdwp_service_socket();
+ }
+ if (!strcmp(name,"track-jdwp")) {
+ return create_jdwp_tracker_service_socket();
+ }
+#endif
fd = service_to_fd(name);
if(fd < 0) return 0;
diff --git a/src/devtools/adb/test_track_jdwp.c b/src/devtools/adb/test_track_jdwp.c
new file mode 100644
index 0000000..8ecc6b8
--- /dev/null
+++ b/src/devtools/adb/test_track_jdwp.c
@@ -0,0 +1,97 @@
+/* a simple test program, connects to ADB server, and opens a track-devices session */
+#include <netdb.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <memory.h>
+
+static void
+panic( const char* msg )
+{
+ fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
+ exit(1);
+}
+
+static int
+unix_write( int fd, const char* buf, int len )
+{
+ int result = 0;
+ while (len > 0) {
+ int len2 = write(fd, buf, len);
+ if (len2 < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ result += len2;
+ len -= len2;
+ buf += len2;
+ }
+ return result;
+}
+
+static int
+unix_read( int fd, char* buf, int len )
+{
+ int result = 0;
+ while (len > 0) {
+ int len2 = read(fd, buf, len);
+ if (len2 < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ result += len2;
+ len -= len2;
+ buf += len2;
+ }
+ return result;
+}
+
+
+int main( void )
+{
+ int ret, s;
+ struct sockaddr_in server;
+ char buffer[1024];
+ const char* request = "track-jdwp";
+ int len;
+
+ memset( &server, 0, sizeof(server) );
+ server.sin_family = AF_INET;
+ server.sin_port = htons(5037);
+ server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ s = socket( PF_INET, SOCK_STREAM, 0 );
+ ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
+ if (ret < 0) panic( "could not connect to server" );
+
+ /* send the request */
+ len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
+ if (unix_write(s, buffer, len) < 0)
+ panic( "could not send request" );
+
+ /* read the OKAY answer */
+ if (unix_read(s, buffer, 4) != 4)
+ panic( "could not read request" );
+
+ printf( "server answer: %.*s\n", 4, buffer );
+
+ /* now loop */
+ for (;;) {
+ char head[5] = "0000";
+
+ if (unix_read(s, head, 4) < 0)
+ panic("could not read length");
+
+ if ( sscanf( head, "%04x", &len ) != 1 )
+ panic("could not decode length");
+
+ if (unix_read(s, buffer, len) != len)
+ panic("could not read data");
+
+ printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
+ }
+ close(s);
+}
diff --git a/src/devtools/adb/transport_pcie.c b/src/devtools/adb/transport_pcie.c
index e06ff2b..d677587 100644
--- a/src/devtools/adb/transport_pcie.c
+++ b/src/devtools/adb/transport_pcie.c
@@ -103,17 +103,18 @@
static void remote_close(atransport *t)
{
- D("remote_close\n");
+ struct pcie_handle *pcie = t->pcie;
+
+ unix_close(pcie->fd);
+ pcie->fd = -1;
}
static void remote_kick(atransport *t)
{
struct pcie_handle *pcie = t->pcie;
- if (pcie->kick) {
- D("Enter pcie->kick\n");
+ if (pcie->kick)
pcie->kick(pcie);
- }
}
void init_pcie_transport(atransport *t, struct pcie_handle *h, const char *devpath, int state)
@@ -163,6 +164,7 @@
{
struct pcie_handle *pcie = (struct pcie_handle *)x;
int fd = -1;
+ char *banner = "Start PCIe port\n";
while (1) {
adb_mutex_lock(&pcie->lock);
@@ -170,16 +172,15 @@
adb_cond_wait(&pcie->notify, &pcie->lock);
adb_mutex_unlock(&pcie->lock);
- D("Try open pcie adbd port~\n");
do {
fd = unix_open(PCIE_ADB_PATH, O_RDWR);
if (fd < 0) {
adb_sleep_ms(1000);
}
} while (fd < 0);
- D("Open pcie adbd port success~\n");
pcie->fd = fd;
+ adb_write(fd, banner, strlen(banner));
/* Get PCIe config information */
fd = unix_open(PCIE_INFO_ADB_PATH, O_RDONLY);
diff --git a/src/devtools/adb/transport_usb.c b/src/devtools/adb/transport_usb.c
index edc7620..3d19803 100644
--- a/src/devtools/adb/transport_usb.c
+++ b/src/devtools/adb/transport_usb.c
@@ -48,40 +48,28 @@
static int remote_read(apacket *p, atransport *t)
{
- int ret = 0;
- while (true) {
- ret = usb_read(t->usb, &p->msg, sizeof(amessage));
- if(ret < -1){
- D("remote usb: terminated (message) due to suspended, ret=%d, retry read\n", ret);
- continue;
- } else if (ret) { // not zero
- D("remote usb: read terminated (message)\n");
+ if(usb_read(t->usb, &p->msg, sizeof(amessage))){
+ D("remote usb: read terminated (message)\n");
+ return -1;
+ }
+
+ fix_endians(p);
+
+ if(check_header(p)) {
+ D("remote usb: check_header failed\n");
+ return -1;
+ }
+
+ if(p->msg.data_length) {
+ if(usb_read(t->usb, p->data, p->msg.data_length)){
+ D("remote usb: terminated (data)\n");
return -1;
}
+ }
- fix_endians(p);
-
- if(check_header(p)) {
- D("remote usb: check_header failed\n");
- return -1;
- }
-
- if(p->msg.data_length) {
- ret = usb_read(t->usb, p->data, p->msg.data_length);
- if(ret < -1){
- D("remote usb: terminated (data) due to suspended, ret=%d, retry read\n", ret);
- continue;
- } else if (ret) { // not zero
- D("remote usb: terminated (data)\n");
- return -1;
- }
- }
-
- if(check_data(p)) {
- D("remote usb: check_data failed\n");
- return -1;
- }
- break;
+ if(check_data(p)) {
+ D("remote usb: check_data failed\n");
+ return -1;
}
return 0;
diff --git a/src/devtools/adb/usb_linux_client.c b/src/devtools/adb/usb_linux_client.c
index da39951..2466275 100644
--- a/src/devtools/adb/usb_linux_client.c
+++ b/src/devtools/adb/usb_linux_client.c
@@ -58,15 +58,6 @@
#define FFS_CONTOL_MAX_EPOLL_EVENT 50
#define DEBUG 0
-#define USB_FFS_WAKE_LOCK_ID "usb_adbd_wakelock"
-#define USB_FFS_WAKE_LOCK_TIMEOUT (2 * 1000)
-
-static const char* sTag = "adbd_usb";
-adb_mutex_t g_wake_lock;
-timer_t g_wake_unlock_timer;
-bool g_wake_lock_acquired;
-typedef void (*timer_routine) (int id);
-
struct usb_handle
{
adb_cond_t notify;
@@ -84,7 +75,6 @@
int bulk_out; /* "out" from the host's perspective => source for adbd */
int bulk_in; /* "in" from the host's perspective => sink for adbd */
bool ffs_control_thread_created;
- bool ffs_control_suspend_mode;
};
static const struct {
@@ -322,12 +312,10 @@
h->bulk_out = -1;
h->control = -1;
h->ffs_control_thread_created = false;
- h->ffs_control_suspend_mode = false;
h->fd = -1;
adb_cond_init(&h->notify, 0);
adb_mutex_init(&h->lock, 0);
- adb_mutex_init(&g_wake_lock, 0);
// Open the file /dev/android_adb_enable to trigger
// the enabling of the adb USB function in the kernel.
@@ -347,94 +335,6 @@
}
}
-////////////////////// wake lock ///////////////////////////////
-timer_t timer_init(timer_routine cb, int id) {
- struct sigevent sevp;
- timer_t timerid;
-
- memset(&sevp, 0, sizeof(sevp));
- sevp.sigev_value.sival_int = id;
- sevp.sigev_notify = SIGEV_THREAD;
- sevp.sigev_notify_function = (void*)cb;
-
- if(timer_create(CLOCK_BOOTTIME, &sevp, &timerid) == -1) {
- D("timer_init() timer_create() failed, reason=[%s]%d",
- strerror(errno), errno);
- return NULL;
- }
- return timerid;
-}
-
-bool timer_start(timer_t timerid, int milliseconds) {
- struct itimerspec expire;
- expire.it_interval.tv_sec = 0;
- expire.it_interval.tv_nsec = 0;
- expire.it_value.tv_sec = milliseconds/1000;
- expire.it_value.tv_nsec = (milliseconds%1000)*1000000;
- if(timer_settime(timerid, 0, &expire, NULL) == -1) {
- D("timer_start() timer_settime() failed, reason=[%s]%d", strerror(errno), errno);
- return false;
- }
- return true;
-}
-
-bool timer_stop(timer_t timerid) {
- return timer_start(timerid, 0);
-}
-
-bool usb_ffs_wake_lock() {
-#if !defined(__LBS_OS_LINUX__) //no permission to open wake_lock on Linux
- int fd = adb_open("/sys/power/wake_lock", O_RDWR | O_NONBLOCK);
- if(fd == -1) {
- D("[%s] open() failed, reason=[%s]%d", sTag, strerror(errno), errno);
- return false;
- }
-
- int ret = adb_write(fd, USB_FFS_WAKE_LOCK_ID, strlen(USB_FFS_WAKE_LOCK_ID));
- if(ret == -1) {
- D("[%s] write() failed id=[%s], reason=[%s]%d", sTag, USB_FFS_WAKE_LOCK_ID, strerror(errno), errno);
- adb_close(fd);
- return false;
- }
-
- adb_close(fd);
-#endif
- return true;
-}
-
-bool usb_ffs_wake_unlock() {
-#if !defined(__LBS_OS_LINUX__) //no permission to open wake_lock on Linux
- int fd = adb_open("/sys/power/wake_unlock", O_RDWR | O_NONBLOCK);
- if(fd == -1) {
- D("[%s] open() failed, reason=[%s]%d", sTag, strerror(errno), errno);
- return false;
- }
-
- int ret = adb_write(fd, USB_FFS_WAKE_LOCK_ID, strlen(USB_FFS_WAKE_LOCK_ID));
- if(ret == -1) {
- D("[%s] write() failed id=[%s], reason=[%s]%d", sTag,
- USB_FFS_WAKE_LOCK_ID, strerror(errno), errno);
- adb_close(fd);
- return false;
- }
-
- adb_close(fd);
-#endif
- return true;
-}
-
-static void usb_ffs_timer_wake_unlock_routine(int id) {
- //do not use the internal msg or it will cause infinite loop in epoll_wait
- adb_mutex_lock(&g_wake_lock);
- if(g_wake_lock_acquired) {
- if(usb_ffs_wake_unlock()) {
- g_wake_lock_acquired = false;
- }
- }
- if (DEBUG) D("[%s] unlock wake_lock_acquired=[%d]", sTag, g_wake_lock_acquired);
- adb_mutex_unlock(&g_wake_lock);
-}
-
static void *ffs_control_read_msg_thread(void *_h)
{
usb_handle *h = _h;
@@ -504,13 +404,6 @@
D("event.type: %s\n", ffs_get_event_type_code(event.type));
switch (event.type) {
- case FUNCTIONFS_SUSPEND:
- D("received FUNCTIONFS_SUSPEND set suspend mode 1");
- h->ffs_control_suspend_mode = true;
- break;
- case FUNCTIONFS_RESUME:
- D("received FUNCTIONFS_RESUME");
- break;
case FUNCTIONFS_SETUP: {
D("received FUNCTIONFS_SETUP");
D("bRequestType = %d",(int)(event.u.setup.bRequestType));
@@ -567,7 +460,6 @@
int control_fd = h->control;
struct epoll_event events[FFS_CONTOL_MAX_EPOLL_EVENT];
- g_wake_unlock_timer = timer_init(usb_ffs_timer_wake_unlock_routine, 0);
int epfd = epoll_create(FFS_CONTOL_MAX_EPOLL_EVENT);
if(epfd == -1) {
D("ERR: epoll_create() fail reason=[%s]", strerror(errno));
@@ -583,14 +475,6 @@
D("Before ffs control thread epoll_wait");
n = epoll_wait(epfd, events, FFS_CONTOL_MAX_EPOLL_EVENT , -1);
- adb_mutex_lock(&g_wake_lock);
- timer_stop(g_wake_unlock_timer);
- if (!g_wake_lock_acquired) {
- g_wake_lock_acquired = usb_ffs_wake_lock();
- if (DEBUG) D("[%s] wake_lock_acquired=[%d]", sTag, g_wake_lock_acquired);
- }
- adb_mutex_unlock(&g_wake_lock);
-
for(i = 0; i < n; i++) {
if(events[i].data.fd == control_fd) {
if(events[i].events & EPOLLIN) {
@@ -599,8 +483,6 @@
}
}
}
-
- timer_start(g_wake_unlock_timer, USB_FFS_WAKE_LOCK_TIMEOUT);
}
}
@@ -764,22 +646,11 @@
D("about to read (fd=%d, len=%d)\n", h->bulk_out, len);
n = bulk_read(h->bulk_out, data, len);
- if (h->ffs_control_suspend_mode) {
- if (n < 0) {
- int ret_err = -1 * errno;
- D("Suspended bulk_read() ERROR: fd = %d, n = %d, errno = %d (%s) ret_err=%d\n",
- h->bulk_out, n, errno, strerror(errno), ret_err);
- return ret_err;
- } else {
- D("Suspended bulk_read: fd = %d, n = %d, errno = %d (%s) len:%d data:%s\n",
- h->bulk_out, n, errno, strerror(errno), len, data);
- }
- } else if (n != len) {
+ if (n != len) {
D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
h->bulk_out, n, errno, strerror(errno));
return -1;
}
- h->ffs_control_suspend_mode = false;
D("[ done fd=%d ]\n", h->bulk_out);
return 0;
}
@@ -834,7 +705,6 @@
adb_cond_init(&h->notify, 0);
adb_mutex_init(&h->lock, 0);
- adb_mutex_init(&g_wake_lock, 0);
D("[ usb_init - starting thread ]\n");
if (adb_thread_create(&tid, usb_ffs_open_thread, h)){