diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2125e60..fb61f03 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="org.onaips.vnc" android:versionCode="31" android:versionName="0.72"> diff --git a/bin/avnc.apk b/bin/avnc.apk index fd1effb..53aacc2 100644 Binary files a/bin/avnc.apk and b/bin/avnc.apk differ diff --git a/bin/classes.dex b/bin/classes.dex index c3e5a18..1582b15 100644 Binary files a/bin/classes.dex and b/bin/classes.dex differ diff --git a/bin/ndk/local/armeabi/androidvncserver b/bin/ndk/local/armeabi/androidvncserver index 2591a87..296e5a3 100755 Binary files a/bin/ndk/local/armeabi/androidvncserver and b/bin/ndk/local/armeabi/androidvncserver differ diff --git a/bin/ndk/local/armeabi/libjpeg.a b/bin/ndk/local/armeabi/libjpeg.a index 732f26a..e006ed8 100644 Binary files a/bin/ndk/local/armeabi/libjpeg.a and b/bin/ndk/local/armeabi/libjpeg.a differ diff --git a/bin/ndk/local/armeabi/objs/androidvncserver/LibVNCServer-0.9.7/libvncserver/scale.o b/bin/ndk/local/armeabi/objs/androidvncserver/LibVNCServer-0.9.7/libvncserver/scale.o index 50be177..1d2ca6c 100644 Binary files a/bin/ndk/local/armeabi/objs/androidvncserver/LibVNCServer-0.9.7/libvncserver/scale.o and b/bin/ndk/local/armeabi/objs/androidvncserver/LibVNCServer-0.9.7/libvncserver/scale.o differ diff --git a/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o b/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o index a658876..23b2119 100644 Binary files a/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o and b/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o differ diff --git a/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o.d b/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o.d index ec02279..75da2e6 100644 --- a/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o.d +++ b/bin/ndk/local/armeabi/objs/androidvncserver/fbvncserver.o.d @@ -90,6 +90,7 @@ /home/onaips/Desktop/android_dev/android-ndk-r4/build/platforms/android-5/arch-arm/usr/include/asm/signal.h \ /home/onaips/Desktop/android_dev/android-ndk-r4/build/platforms/android-5/arch-arm/usr/include/asm-generic/signal.h \ /home/onaips/Desktop/android_dev/android-ndk-r4/build/platforms/android-5/arch-arm/usr/include/sched.h \ + /home/onaips/Dropbox/projectos/workspace/avnc/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.h \ /home/onaips/Dropbox/projectos/workspace/avnc/jni/vnc/LibVNCServer-0.9.7/rfb/keysym.h \ /home/onaips/Dropbox/projectos/workspace/avnc/jni/vnc/suinput.h \ /home/onaips/Desktop/android_dev/android-ndk-r4/build/platforms/android-5/arch-arm/usr/include/linux/uinput.h \ @@ -275,6 +276,8 @@ /home/onaips/Desktop/android_dev/android-ndk-r4/build/platforms/android-5/arch-arm/usr/include/sched.h: +/home/onaips/Dropbox/projectos/workspace/avnc/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.h: + /home/onaips/Dropbox/projectos/workspace/avnc/jni/vnc/LibVNCServer-0.9.7/rfb/keysym.h: /home/onaips/Dropbox/projectos/workspace/avnc/jni/vnc/suinput.h: diff --git a/bin/org/onaips/vnc/MainActivity$1$1.class b/bin/org/onaips/vnc/MainActivity$1$1.class new file mode 100644 index 0000000..a8df503 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$1$1.class differ diff --git a/bin/org/onaips/vnc/MainActivity$1.class b/bin/org/onaips/vnc/MainActivity$1.class new file mode 100644 index 0000000..643661d Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$1.class differ diff --git a/bin/org/onaips/vnc/MainActivity$10.class b/bin/org/onaips/vnc/MainActivity$10.class new file mode 100644 index 0000000..a2ca853 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$10.class differ diff --git a/bin/org/onaips/vnc/MainActivity$11.class b/bin/org/onaips/vnc/MainActivity$11.class new file mode 100644 index 0000000..a2b8d09 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$11.class differ diff --git a/bin/org/onaips/vnc/MainActivity$12.class b/bin/org/onaips/vnc/MainActivity$12.class new file mode 100644 index 0000000..aaec6f2 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$12.class differ diff --git a/bin/org/onaips/vnc/MainActivity$2$1.class b/bin/org/onaips/vnc/MainActivity$2$1.class new file mode 100644 index 0000000..6806b90 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$2$1.class differ diff --git a/bin/org/onaips/vnc/MainActivity$2.class b/bin/org/onaips/vnc/MainActivity$2.class new file mode 100644 index 0000000..881d29b Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$2.class differ diff --git a/bin/org/onaips/vnc/MainActivity$3.class b/bin/org/onaips/vnc/MainActivity$3.class new file mode 100644 index 0000000..7bcf4f2 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$3.class differ diff --git a/bin/org/onaips/vnc/MainActivity$4.class b/bin/org/onaips/vnc/MainActivity$4.class new file mode 100644 index 0000000..56c024c Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$4.class differ diff --git a/bin/org/onaips/vnc/MainActivity$5$1.class b/bin/org/onaips/vnc/MainActivity$5$1.class new file mode 100644 index 0000000..e3ac8f4 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$5$1.class differ diff --git a/bin/org/onaips/vnc/MainActivity$5.class b/bin/org/onaips/vnc/MainActivity$5.class new file mode 100644 index 0000000..794c821 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$5.class differ diff --git a/bin/org/onaips/vnc/MainActivity$6.class b/bin/org/onaips/vnc/MainActivity$6.class new file mode 100644 index 0000000..5874091 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$6.class differ diff --git a/bin/org/onaips/vnc/MainActivity$7.class b/bin/org/onaips/vnc/MainActivity$7.class new file mode 100644 index 0000000..daadd61 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$7.class differ diff --git a/bin/org/onaips/vnc/MainActivity$8.class b/bin/org/onaips/vnc/MainActivity$8.class new file mode 100644 index 0000000..ae11590 Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$8.class differ diff --git a/bin/org/onaips/vnc/MainActivity$9.class b/bin/org/onaips/vnc/MainActivity$9.class new file mode 100644 index 0000000..6efcc6d Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity$9.class differ diff --git a/bin/org/onaips/vnc/MainActivity.class b/bin/org/onaips/vnc/MainActivity.class new file mode 100644 index 0000000..73ffffd Binary files /dev/null and b/bin/org/onaips/vnc/MainActivity.class differ diff --git a/bin/org/onaips/vnc/R$array.class b/bin/org/onaips/vnc/R$array.class new file mode 100644 index 0000000..935110b Binary files /dev/null and b/bin/org/onaips/vnc/R$array.class differ diff --git a/bin/org/onaips/vnc/R$attr.class b/bin/org/onaips/vnc/R$attr.class new file mode 100644 index 0000000..4131c26 Binary files /dev/null and b/bin/org/onaips/vnc/R$attr.class differ diff --git a/bin/org/onaips/vnc/R$drawable.class b/bin/org/onaips/vnc/R$drawable.class new file mode 100644 index 0000000..6b26f55 Binary files /dev/null and b/bin/org/onaips/vnc/R$drawable.class differ diff --git a/bin/org/onaips/vnc/R$id.class b/bin/org/onaips/vnc/R$id.class new file mode 100644 index 0000000..dc2c137 Binary files /dev/null and b/bin/org/onaips/vnc/R$id.class differ diff --git a/bin/org/onaips/vnc/R$layout.class b/bin/org/onaips/vnc/R$layout.class new file mode 100644 index 0000000..0bea272 Binary files /dev/null and b/bin/org/onaips/vnc/R$layout.class differ diff --git a/bin/org/onaips/vnc/R$menu.class b/bin/org/onaips/vnc/R$menu.class new file mode 100644 index 0000000..d70f9fe Binary files /dev/null and b/bin/org/onaips/vnc/R$menu.class differ diff --git a/bin/org/onaips/vnc/R$raw.class b/bin/org/onaips/vnc/R$raw.class new file mode 100644 index 0000000..c655ac9 Binary files /dev/null and b/bin/org/onaips/vnc/R$raw.class differ diff --git a/bin/org/onaips/vnc/R$string.class b/bin/org/onaips/vnc/R$string.class new file mode 100644 index 0000000..c1c3154 Binary files /dev/null and b/bin/org/onaips/vnc/R$string.class differ diff --git a/bin/org/onaips/vnc/R$styleable.class b/bin/org/onaips/vnc/R$styleable.class new file mode 100644 index 0000000..e5c5c8c Binary files /dev/null and b/bin/org/onaips/vnc/R$styleable.class differ diff --git a/bin/org/onaips/vnc/R$xml.class b/bin/org/onaips/vnc/R$xml.class new file mode 100644 index 0000000..06f4976 Binary files /dev/null and b/bin/org/onaips/vnc/R$xml.class differ diff --git a/bin/org/onaips/vnc/R.class b/bin/org/onaips/vnc/R.class new file mode 100644 index 0000000..151bceb Binary files /dev/null and b/bin/org/onaips/vnc/R.class differ diff --git a/bin/org/onaips/vnc/preferences.class b/bin/org/onaips/vnc/preferences.class new file mode 100644 index 0000000..818b744 Binary files /dev/null and b/bin/org/onaips/vnc/preferences.class differ diff --git a/bin/resources.ap_ b/bin/resources.ap_ index d8be64c..360a8e9 100644 Binary files a/bin/resources.ap_ and b/bin/resources.ap_ differ diff --git a/gen/org/onaips/vnc/R.java b/gen/org/onaips/vnc/R.java new file mode 100644 index 0000000..8a89aa3 --- /dev/null +++ b/gen/org/onaips/vnc/R.java @@ -0,0 +1,197 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package org.onaips.vnc; + +public final class R { + public static final class array { + public static final int rotation_values=0x7f070000; + public static final int scale_strings=0x7f070002; + public static final int scale_values=0x7f070001; + } + public static final class attr { + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int backgroundColor=0x7f010000; + /**

Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character. +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int keywords=0x7f010003; + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int primaryTextColor=0x7f010001; + /**

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int refreshInterval=0x7f010004; + /**

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static final int secondaryTextColor=0x7f010002; + } + public static final class drawable { + public static final int bg=0x7f020000; + public static final int btnstart=0x7f020001; + public static final int btnstart_normal=0x7f020002; + public static final int btnstart_pressed=0x7f020003; + public static final int btnstop=0x7f020004; + public static final int btnstop_normal=0x7f020005; + public static final int btnstop_pressed=0x7f020006; + public static final int droidvnclogo=0x7f020007; + public static final int icon=0x7f020008; + } + public static final class id { + public static final int Button01=0x7f090000; + public static final int Button02=0x7f090001; + public static final int TextView01=0x7f090002; + public static final int TextView02=0x7f090004; + public static final int banner_adview=0x7f090005; + public static final int preferences=0x7f090006; + public static final int stateLabel=0x7f090003; + } + public static final class layout { + public static final int main=0x7f030000; + } + public static final class menu { + public static final int menu=0x7f080000; + } + public static final class raw { + public static final int androidvncserver=0x7f050000; + public static final int indexvnc=0x7f050001; + public static final int vncviewer=0x7f050002; + } + public static final class string { + public static final int app_name=0x7f060000; + public static final int device_info_fmt=0x7f060002; + public static final int password=0x7f060001; + } + public static final class xml { + public static final int preferences=0x7f040000; + } + public static final class styleable { + /** Attributes that can be used with a com_admob_android_ads_AdView. +

Includes the following attributes:

+ + + + + + + + + +
AttributeDescription
{@link #com_admob_android_ads_AdView_backgroundColor org.onaips.vnc:backgroundColor}
{@link #com_admob_android_ads_AdView_keywords org.onaips.vnc:keywords}
{@link #com_admob_android_ads_AdView_primaryTextColor org.onaips.vnc:primaryTextColor}
{@link #com_admob_android_ads_AdView_refreshInterval org.onaips.vnc:refreshInterval}
{@link #com_admob_android_ads_AdView_secondaryTextColor org.onaips.vnc:secondaryTextColor}
+ @see #com_admob_android_ads_AdView_backgroundColor + @see #com_admob_android_ads_AdView_keywords + @see #com_admob_android_ads_AdView_primaryTextColor + @see #com_admob_android_ads_AdView_refreshInterval + @see #com_admob_android_ads_AdView_secondaryTextColor + */ + public static final int[] com_admob_android_ads_AdView = { + 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, + 0x7f010004 + }; + /** +

This symbol is the offset where the {@link org.onaips.vnc.R.attr#backgroundColor} + attribute's value can be found in the {@link #com_admob_android_ads_AdView} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:backgroundColor + */ + public static final int com_admob_android_ads_AdView_backgroundColor = 0; + /** +

This symbol is the offset where the {@link org.onaips.vnc.R.attr#keywords} + attribute's value can be found in the {@link #com_admob_android_ads_AdView} array. + + +

Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character. +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:keywords + */ + public static final int com_admob_android_ads_AdView_keywords = 3; + /** +

This symbol is the offset where the {@link org.onaips.vnc.R.attr#primaryTextColor} + attribute's value can be found in the {@link #com_admob_android_ads_AdView} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:primaryTextColor + */ + public static final int com_admob_android_ads_AdView_primaryTextColor = 1; + /** +

This symbol is the offset where the {@link org.onaips.vnc.R.attr#refreshInterval} + attribute's value can be found in the {@link #com_admob_android_ads_AdView} array. + + +

Must be an integer value, such as "100". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:refreshInterval + */ + public static final int com_admob_android_ads_AdView_refreshInterval = 4; + /** +

This symbol is the offset where the {@link org.onaips.vnc.R.attr#secondaryTextColor} + attribute's value can be found in the {@link #com_admob_android_ads_AdView} array. + + +

Must be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:secondaryTextColor + */ + public static final int com_admob_android_ads_AdView_secondaryTextColor = 2; + }; +} diff --git a/jni/vnc/Android.mk b/jni/vnc/Android.mk index 2bafae2..449093e 100755 --- a/jni/vnc/Android.mk +++ b/jni/vnc/Android.mk @@ -1,8 +1,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) - -LOCAL_CFLAGS := -DDONATE_VERSION +#LOCAL_CFLAGS += -DDONATE_VERSION +LOCAL_CFLAGS := -O3 -Wall LOCAL_SRC_FILES:= \ diff --git a/jni/vnc/Android.mk~ b/jni/vnc/Android.mk~ new file mode 100755 index 0000000..ae52dfc --- /dev/null +++ b/jni/vnc/Android.mk~ @@ -0,0 +1,54 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +#LOCAL_CFLAGS += -DDONATE_VERSION +LOCAL_CFLAGS := -O3 + + +LOCAL_SRC_FILES:= \ + fbvncserver.c \ + suinput.c \ + LibVNCServer-0.9.7/libvncserver/main.c \ + LibVNCServer-0.9.7/libvncserver/rfbserver.c \ + LibVNCServer-0.9.7/libvncserver/rfbregion.c \ + LibVNCServer-0.9.7/libvncserver/auth.c \ + LibVNCServer-0.9.7/libvncserver/sockets.c \ + LibVNCServer-0.9.7/libvncserver/stats.c \ + LibVNCServer-0.9.7/libvncserver/corre.c \ + LibVNCServer-0.9.7/libvncserver/hextile.c \ + LibVNCServer-0.9.7/libvncserver/rre.c \ + LibVNCServer-0.9.7/libvncserver/translate.c \ + LibVNCServer-0.9.7/libvncserver/cutpaste.c \ + LibVNCServer-0.9.7/libvncserver/httpd.c \ + LibVNCServer-0.9.7/libvncserver/cursor.c \ + LibVNCServer-0.9.7/libvncserver/font.c \ + LibVNCServer-0.9.7/libvncserver/draw.c \ + LibVNCServer-0.9.7/libvncserver/selbox.c \ + LibVNCServer-0.9.7/libvncserver/d3des.c \ + LibVNCServer-0.9.7/libvncserver/vncauth.c \ + LibVNCServer-0.9.7/libvncserver/cargs.c \ + LibVNCServer-0.9.7/libvncserver/minilzo.c \ + LibVNCServer-0.9.7/libvncserver/ultra.c \ + LibVNCServer-0.9.7/libvncserver/scale.c \ + LibVNCServer-0.9.7/libvncserver/zlib.c \ + LibVNCServer-0.9.7/libvncserver/zrle.c \ + LibVNCServer-0.9.7/libvncserver/zrleoutstream.c \ + LibVNCServer-0.9.7/libvncserver/zrlepalettehelper.c \ + LibVNCServer-0.9.7/libvncserver/zywrletemplate.c \ + LibVNCServer-0.9.7/libvncserver/tight.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/LibVNCServer-0.9.7/libvncserver \ + $(LOCAL_PATH)/LibVNCServer-0.9.7 \ + $(LOCAL_PATH)/../jpeg + + +LOCAL_STATIC_LIBRARIES := jpeg + +LOCAL_MODULE:= androidvncserver + +LOCAL_LDLIBS := -lz -llog + + +include $(BUILD_EXECUTABLE) \ No newline at end of file diff --git a/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c b/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c index 55598fa..45a7422 100755 --- a/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c +++ b/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c @@ -351,12 +351,12 @@ void rfbScalingSetup(rfbClientPtr cl, int width, int height) /* Update it! */ if (ptr->scaledScreenRefCount<1) rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); - /* - * rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n", - * cl->scaledScreen->width, cl->scaledScreen->height, - * cl->scaledScreen->scaledScreenRefCount, - * ptr->width, ptr->height, ptr->scaledScreenRefCount); - */ + + rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n", + cl->scaledScreen->width, cl->scaledScreen->height, + cl->scaledScreen->scaledScreenRefCount, + ptr->width, ptr->height, ptr->scaledScreenRefCount); + LOCK(cl->updateMutex); cl->scaledScreen->scaledScreenRefCount--; diff --git a/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c~ b/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c~ new file mode 100755 index 0000000..55598fa --- /dev/null +++ b/jni/vnc/LibVNCServer-0.9.7/libvncserver/scale.c~ @@ -0,0 +1,420 @@ +/* + * scale.c - deal with server-side scaling. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include "private.h" + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#ifdef WIN32 +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#endif +#endif + +#ifdef CORBA +#include +#endif + +#ifdef DEBUGPROTO +#undef DEBUGPROTO +#define DEBUGPROTO(x) x +#else +#define DEBUGPROTO(x) +#endif + +/****************************/ +#define CEIL(x) ( (double) ((int) (x)) == (x) ? \ + (double) ((int) (x)) : (double) ((int) (x) + 1) ) +#define FLOOR(x) ( (double) ((int) (x)) ) + + +int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x) +{ + if ((from==to) || (from==NULL) || (to==NULL)) return x; + return ((int)(((double) x / (double)from->width) * (double)to->width )); +} + +int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y) +{ + if ((from==to) || (from==NULL) || (to==NULL)) return y; + return ((int)(((double) y / (double)from->height) * (double)to->height )); +} + +/* So, all of the encodings point to the ->screen->frameBuffer, + * We need to change this! + */ +void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, char *function) +{ + double x1,y1,w1,h1, x2, y2, w2, h2; + double scaleW = ((double) to->width) / ((double) from->width); + double scaleH = ((double) to->height) / ((double) from->height); + + + /* + * rfbLog("rfbScaledCorrection(%p -> %p, %dx%d->%dx%d (%dXx%dY-%dWx%dH)\n", + * from, to, from->width, from->height, to->width, to->height, *x, *y, *w, *h); + */ + + /* If it's the original framebuffer... */ + if (from==to) return; + + x1 = ((double) *x) * scaleW; + y1 = ((double) *y) * scaleH; + w1 = ((double) *w) * scaleW; + h1 = ((double) *h) * scaleH; + + + /*cast from double to int is same as "*x = floor(x1);" */ + x2 = FLOOR(x1); + y2 = FLOOR(y1); + + /* include into W and H the jitter of scaling X and Y */ + w2 = CEIL(w1 + ( x1 - x2 )); + h2 = CEIL(h1 + ( y1 - y2 )); + + /* + * rfbLog("%s (%dXx%dY-%dWx%dH -> %fXx%fY-%fWx%fH) {%dWx%dH -> %dWx%dH}\n", + * function, *x, *y, *w, *h, x2, y2, w2, h2, + * from->width, from->height, to->width, to->height); + */ + + /* simulate ceil() without math library */ + *x = (int)x2; + *y = (int)y2; + *w = (int)w2; + *h = (int)h2; + + /* Small changes for a thumbnail may be scaled to zero */ + if (*w==0) (*w)++; + if (*h==0) (*h)++; + /* scaling from small to big may overstep the size a bit */ + if (*x+*w > to->width) *w=to->width - *x; + if (*y+*h > to->height) *h=to->height - *y; +} + +void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0) +{ + int x,y,w,v,z; + int x1, y1, w1, h1; + int bitsPerPixel, bytesPerPixel, bytesPerLine, areaX, areaY, area2; + unsigned char *srcptr, *dstptr; + + /* Nothing to do!!! */ + if (screen==ptr) return; + + x1 = x0; + y1 = y0; + w1 = w0; + h1 = h0; + + rfbScaledCorrection(screen, ptr, &x1, &y1, &w1, &h1, "rfbScaledScreenUpdateRect"); + x0 = ScaleX(ptr, screen, x1); + y0 = ScaleY(ptr, screen, y1); + w0 = ScaleX(ptr, screen, w1); + h0 = ScaleY(ptr, screen, h1); + + bitsPerPixel = screen->bitsPerPixel; + bytesPerPixel = bitsPerPixel / 8; + bytesPerLine = w1 * bytesPerPixel; + srcptr = (unsigned char *)(screen->frameBuffer + + (y0 * screen->paddedWidthInBytes + x0 * bytesPerPixel)); + dstptr = (unsigned char *)(ptr->frameBuffer + + ( y1 * ptr->paddedWidthInBytes + x1 * bytesPerPixel)); + /* The area of the source framebuffer for each destination pixel */ + areaX = ScaleX(ptr,screen,1); + areaY = ScaleY(ptr,screen,1); + area2 = areaX*areaY; + + + /* Ensure that we do not go out of bounds */ + if ((x1+w1) > (ptr->width)) + { + if (x1==0) w1=ptr->width; else x1 = ptr->width - w1; + } + if ((y1+h1) > (ptr->height)) + { + if (y1==0) h1=ptr->height; else y1 = ptr->height - h1; + } + /* + * rfbLog("rfbScaledScreenUpdateRect(%dXx%dY-%dWx%dH -> %dXx%dY-%dWx%dH <%dx%d>) {%dWx%dH -> %dWx%dH} 0x%p\n", + * x0, y0, w0, h0, x1, y1, w1, h1, areaX, areaY, + * screen->width, screen->height, ptr->width, ptr->height, ptr->frameBuffer); + */ + + if (screen->serverFormat.trueColour) { /* Blend neighbouring pixels together */ + unsigned char *srcptr2; + unsigned long pixel_value, red, green, blue; + unsigned int redShift = screen->serverFormat.redShift; + unsigned int greenShift = screen->serverFormat.greenShift; + unsigned int blueShift = screen->serverFormat.blueShift; + unsigned long redMax = screen->serverFormat.redMax; + unsigned long greenMax = screen->serverFormat.greenMax; + unsigned long blueMax = screen->serverFormat.blueMax; + + /* for each *destination* pixel... */ + for (y = 0; y < h1; y++) { + for (x = 0; x < w1; x++) { + red = green = blue = 0; + /* Get the totals for rgb from the source grid... */ + for (w = 0; w < areaX; w++) { + for (v = 0; v < areaY; v++) { + srcptr2 = &srcptr[(((x * areaX) + w) * bytesPerPixel) + + (v * screen->paddedWidthInBytes)]; + pixel_value = 0; + + + switch (bytesPerPixel) { + case 4: pixel_value = *((unsigned int *)srcptr2); break; + case 2: pixel_value = *((unsigned short *)srcptr2); break; + case 1: pixel_value = *((unsigned char *)srcptr2); break; + default: + /* fixme: endianess problem? */ + for (z = 0; z < bytesPerPixel; z++) + pixel_value += (srcptr2[z] << (8 * z)); + break; + } + /* + srcptr2 += bytesPerPixel; + */ + + red += ((pixel_value >> redShift) & redMax); + green += ((pixel_value >> greenShift) & greenMax); + blue += ((pixel_value >> blueShift) & blueMax); + + } + } + /* We now have a total for all of the colors, find the average! */ + red /= area2; + green /= area2; + blue /= area2; + /* Stuff the new value back into memory */ + pixel_value = ((red & redMax) << redShift) | ((green & greenMax) << greenShift) | ((blue & blueMax) << blueShift); + + switch (bytesPerPixel) { + case 4: *((unsigned int *)dstptr) = (unsigned int) pixel_value; break; + case 2: *((unsigned short *)dstptr) = (unsigned short) pixel_value; break; + case 1: *((unsigned char *)dstptr) = (unsigned char) pixel_value; break; + default: + /* fixme: endianess problem? */ + for (z = 0; z < bytesPerPixel; z++) + dstptr[z]=(pixel_value >> (8 * z)) & 0xff; + break; + } + dstptr += bytesPerPixel; + } + srcptr += (screen->paddedWidthInBytes * areaY); + dstptr += (ptr->paddedWidthInBytes - bytesPerLine); + } + } else + { /* Not truecolour, so we can't blend. Just use the top-left pixel instead */ + for (y = y1; y < (y1+h1); y++) { + for (x = x1; x < (x1+w1); x++) + memcpy (&ptr->frameBuffer[(y *ptr->paddedWidthInBytes) + (x * bytesPerPixel)], + &screen->frameBuffer[(y * areaY * screen->paddedWidthInBytes) + (x *areaX * bytesPerPixel)], bytesPerPixel); + } + } +} + +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2) +{ + /* ok, now the task is to update each and every scaled version of the framebuffer + * and we only have to do this for this specific changed rectangle! + */ + rfbScreenInfoPtr ptr; + int count=0; + + /* We don't point to cl->screen as it is the original */ + for (ptr=screen->scaledScreenNext;ptr!=NULL;ptr=ptr->scaledScreenNext) + { + /* Only update if it has active clients... */ + if (ptr->scaledScreenRefCount>0) + { + rfbScaledScreenUpdateRect(screen, ptr, x1, y1, x2-x1, y2-y1); + count++; + } + } +} + +/* Create a new scaled version of the framebuffer */ +rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + ptr = malloc(sizeof(rfbScreenInfo)); + if (ptr!=NULL) + { + /* copy *everything* (we don't use most of it, but just in case) */ + memcpy(ptr, cl->screen, sizeof(rfbScreenInfo)); + ptr->width = width; + ptr->height = height; + ptr->paddedWidthInBytes = (ptr->bitsPerPixel/8)*ptr->width; + + /* Need to by multiples of 4 for Sparc systems */ + ptr->paddedWidthInBytes += (ptr->paddedWidthInBytes % 4); + + /* Reset the reference count to 0! */ + ptr->scaledScreenRefCount = 0; + + ptr->sizeInBytes = ptr->paddedWidthInBytes * ptr->height; + ptr->serverFormat = cl->screen->serverFormat; + + ptr->frameBuffer = malloc(ptr->sizeInBytes); + if (ptr->frameBuffer!=NULL) + { + /* Reset to a known condition: scale the entire framebuffer */ + rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); + /* Now, insert into the chain */ + LOCK(cl->updateMutex); + ptr->scaledScreenNext = cl->screen->scaledScreenNext; + cl->screen->scaledScreenNext = ptr; + UNLOCK(cl->updateMutex); + } + else + { + /* Failed to malloc the new frameBuffer, cleanup */ + free(ptr); + ptr=NULL; + } + } + return ptr; +} + +/* Find an active scaled version of the framebuffer + * TODO: implement a refcount per scaled screen to prevent + * unreferenced scaled screens from hanging around + */ +rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + /* include the original in the search (ie: fine 1:1 scaled version of the frameBuffer) */ + for (ptr=cl->screen; ptr!=NULL; ptr=ptr->scaledScreenNext) + { + if ((ptr->width==width) && (ptr->height==height)) + return ptr; + } + return NULL; +} + +/* Future needs "scale to 320x240, as that's the client's screen size */ +void rfbScalingSetup(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + + ptr = rfbScalingFind(cl,width,height); + if (ptr==NULL) + ptr = rfbScaledScreenAllocate(cl,width,height); + /* Now, there is a new screen available (if ptr is not NULL) */ + if (ptr!=NULL) + { + /* Update it! */ + if (ptr->scaledScreenRefCount<1) + rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); + /* + * rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n", + * cl->scaledScreen->width, cl->scaledScreen->height, + * cl->scaledScreen->scaledScreenRefCount, + * ptr->width, ptr->height, ptr->scaledScreenRefCount); + */ + + LOCK(cl->updateMutex); + cl->scaledScreen->scaledScreenRefCount--; + ptr->scaledScreenRefCount++; + cl->scaledScreen=ptr; + cl->newFBSizePending = TRUE; + UNLOCK(cl->updateMutex); + + rfbLog("Scaling to %dx%d (refcount=%d)\n",width,height,ptr->scaledScreenRefCount); + } + else + rfbLog("Scaling to %dx%d failed, leaving things alone\n",width,height); +} + +int rfbSendNewScaleSize(rfbClientPtr cl) +{ + /* if the client supports newFBsize Encoding, use it */ + if (cl->useNewFBSize && cl->newFBSizePending) + return FALSE; + + LOCK(cl->updateMutex); + cl->newFBSizePending = FALSE; + UNLOCK(cl->updateMutex); + + if (cl->PalmVNC==TRUE) + { + rfbPalmVNCReSizeFrameBufferMsg pmsg; + pmsg.type = rfbPalmVNCReSizeFrameBuffer; + pmsg.pad1 = 0; + pmsg.desktop_w = Swap16IfLE(cl->screen->width); + pmsg.desktop_h = Swap16IfLE(cl->screen->height); + pmsg.buffer_w = Swap16IfLE(cl->scaledScreen->width); + pmsg.buffer_h = Swap16IfLE(cl->scaledScreen->height); + pmsg.pad2 = 0; + + rfbLog("Sending a response to a PalmVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); + if (rfbWriteExact(cl, (char *)&pmsg, sz_rfbPalmVNCReSizeFrameBufferMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return FALSE; + } + } + else + { + rfbResizeFrameBufferMsg rmsg; + rmsg.type = rfbResizeFrameBuffer; + rmsg.pad1=0; + rmsg.framebufferWidth = Swap16IfLE(cl->scaledScreen->width); + rmsg.framebufferHeigth = Swap16IfLE(cl->scaledScreen->height); + rfbLog("Sending a response to a UltraVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); + if (rfbWriteExact(cl, (char *)&rmsg, sz_rfbResizeFrameBufferMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return FALSE; + } + } + return TRUE; +} +/****************************/ diff --git a/jni/vnc/fbvncserver.c b/jni/vnc/fbvncserver.c index 1906c9d..b660d5a 100755 --- a/jni/vnc/fbvncserver.c +++ b/jni/vnc/fbvncserver.c @@ -21,7 +21,7 @@ #include #include #include - + #include #include #include @@ -36,10 +36,11 @@ #include #include //android log -#include +#include /* libvncserver */ #include "rfb/rfb.h" +#include "libvncserver/scale.h" #include "rfb/keysym.h" #include "suinput.h" @@ -58,47 +59,44 @@ static char VNC_PASSWORD[256] = ""; static struct fb_var_screeninfo scrinfo; +static struct fb_fix_screeninfo fscrinfo; static int fbfd = -1; static int inputfd = -1; static unsigned int *fbmmap = MAP_FAILED; static unsigned int *vncbuf; static unsigned int *cmpbuf; -static unsigned int *cmpbuf_rot; /* Android already has 5900 bound natively. */ #define VNC_PORT 5901 static rfbScreenInfoPtr vncscr; -int xmin, xmax; -int ymin, ymax; -int idle=0,standby=0; -int change=0; -static int rotation=0; +int idle=0,standby=0,change=0; +static int rotation=0,scaling=0; /*****************************************************************************/ static void (*update_screen)(void)=NULL; static void keyevent(rfbBool down, rfbKeySym key, rfbClientPtr cl); static void ptrevent(int buttonMask, int x, int y, rfbClientPtr cl); static void rotate(); - + /*****************************************************************************/ - -void update_fb_info() -{ - + +void update_fb_info() +{ + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &scrinfo) != 0) { __android_log_print(ANDROID_LOG_INFO,"VNC","ioctl error\n"); exit(EXIT_FAILURE); - } -} + } +} #define OUT 32 #include "update_screen.c" -#define OUT 8 -#include "update_screen.c" +#define OUT 8 +#include "update_screen.c" #define OUT 16 #include "update_screen.c" @@ -116,6 +114,12 @@ static void init_fb(void) update_fb_info(); + if (ioctl(fbfd, FBIOGET_FSCREENINFO, &fscrinfo) != 0) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","ioctl error\n"); + exit(EXIT_FAILURE); + } + pixels = scrinfo.xres * scrinfo.yres; bytespp = scrinfo.bits_per_pixel /CHAR_BIT; @@ -125,8 +129,9 @@ static void init_fb(void) (int)scrinfo.xoffset, (int)scrinfo.yoffset, (int)scrinfo.bits_per_pixel); - off_t o=0; +// off_t o=0; + //now handled with double buffer detection // if (scrinfo.xres==480 && scrinfo.yres==854 && scrinfo.xres_virtual==480 // && scrinfo.yres_virtual==854 && scrinfo.xoffset==448 && scrinfo.yoffset==1710) /*if (scrinfo.bits_per_pixel==32) @@ -141,11 +146,11 @@ static void init_fb(void) } */ - __android_log_print(ANDROID_LOG_INFO,"VNC","buffer offset=%d * %d\n",o,sysconf(_SC_PAGE_SIZE)); - - fbmmap = mmap(NULL, (scrinfo.xres_virtual*scrinfo.yres_virtual)* bytespp , PROT_READ|PROT_READ , MAP_PRIVATE , fbfd, o*sysconf(_SC_PAGE_SIZE)); - - printf("aki %d\n",o*sysconf(_SC_PAGE_SIZE)); +// __android_log_print(ANDROID_LOG_INFO,"VNC","buffer offset=%d * %d\n",o,(int)sysconf(_SC_PAGE_SIZE)); +// +// fbmmap = mmap(NULL, (scrinfo.xres_virtual*scrinfo.yres_virtual)* bytespp , PROT_READ|PROT_READ , MAP_PRIVATE , fbfd, o*sysconf(_SC_PAGE_SIZE)); + fbmmap = mmap(NULL, (scrinfo.xres_virtual*scrinfo.yres_virtual)* bytespp , PROT_READ|PROT_READ , MAP_PRIVATE , fbfd, 0); + if (fbmmap == MAP_FAILED) { @@ -187,32 +192,37 @@ static void cleanup_kbd() } /*****************************************************************************/ -/* response is cl->authChallenge vncEncrypted with passwd */ -static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len) + +static rfbNewClientHookPtr clientHook(rfbClientPtr cl) { - if (strcmp(response,VNC_PASSWORD)==0) - return (TRUE); - return(FALSE); + if (scaling!=0 && scaling!=100) + { + rfbScalingSetup(cl, vncscr->width*scaling/100.0, vncscr->height*scaling/100.0); + + } + + return RFB_CLIENT_ACCEPT; } static void init_fb_server(int argc, char **argv) -{ +{ + __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing server...\n"); vncbuf = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel/CHAR_BIT); cmpbuf = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel/CHAR_BIT); - cmpbuf_rot = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel/CHAR_BIT); assert(vncbuf != NULL); assert(cmpbuf != NULL); + - + if (rotation==0 || rotation==180) vncscr = rfbGetScreen(&argc, argv, scrinfo.xres, scrinfo.yres, 0 /* not used */ , 3, scrinfo.bits_per_pixel/CHAR_BIT); else vncscr = rfbGetScreen(&argc, argv, scrinfo.yres, scrinfo.xres, 0 /* not used */ , 3, scrinfo.bits_per_pixel/CHAR_BIT); - + assert(vncscr != NULL); vncscr->desktopName = "Android"; @@ -221,6 +231,7 @@ static void init_fb_server(int argc, char **argv) vncscr->kbdAddEvent = keyevent; vncscr->ptrAddEvent = ptrevent; + vncscr->newClientHook = clientHook; if (strcmp(VNC_PASSWORD,"")!=0) { @@ -232,9 +243,9 @@ static void init_fb_server(int argc, char **argv) } #ifdef DONATE_VERSION - vncscr->httpDir="/data/data/org.onaips.vnc/"; -#else vncscr->httpDir="/data/data/org.onaips.vnc_donate/"; +#else + vncscr->httpDir="/data/data/org.onaips.vnc/"; #endif vncscr->serverFormat.redShift=scrinfo.red.offset; vncscr->serverFormat.greenShift=scrinfo.green.offset; @@ -244,7 +255,7 @@ static void init_fb_server(int argc, char **argv) vncscr->serverFormat.greenMax=((1<serverFormat.blueMax=((1<alwaysShared = TRUE; + vncscr->alwaysShared = TRUE; vncscr->handleEventsEagerly = TRUE; vncscr->deferUpdateTime = 5; @@ -408,7 +419,7 @@ static int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, return 30; //A with acute -> a with ring above case 50089: case 233: (*alt)=1; return 18; //e with acute - case 50057: + case 50057: case 201:(*sh)=1; (*alt)=1; return 18; //E with acute case 50093: case 0xffbf: (*alt)=1; @@ -566,9 +577,6 @@ inline void transform_touch_coordinates(int *x, int *y) static void ptrevent(int buttonMask, int x, int y, rfbClientPtr cl) { - struct input_event ev; - - static int leftClicked=0,rightClicked=0,middleClicked=0; transform_touch_coordinates(&x,&y); @@ -635,7 +643,7 @@ void sigproc() exit(0); /* normal exit status */ } - + static void rotate() { @@ -657,19 +665,19 @@ static void rotate() vncscr->serverFormat.blueMax=((1<width, vncscr->height); - + } void print_usage(char **argv) { - __android_log_print(ANDROID_LOG_INFO,"VNC","%s [-p password] [-h]\n" + __android_log_print(ANDROID_LOG_INFO,"VNC","androidvncserver [-p password] [-h]\n" "-p password: Password to access server\n" "-r rotation: Screen rotation (degrees) (0,90,180,270)\n" + "-s screen scale: percentage (20,30,50,100,150)\n" "-h : print this help\n"); } - int main(int argc, char **argv) { signal(SIGINT, sigproc);//pipe signals @@ -688,18 +696,28 @@ int main(int argc, char **argv) { case 'h': print_usage(argv); - exit(0); + exit(0); break; case 'p': - i++; + i++; strcpy(VNC_PASSWORD,argv[i]); break; case 'r': - i++; + i++; r=atoi(argv[i]); if (r==0 || r==90 || r==180 || r==270) rotation=r; __android_log_print(ANDROID_LOG_INFO,"VNC","rotating to %d degrees\n",rotation); + break; + case 's': + i++; + r=atoi(argv[i]); + if (r>=1 && r <= 150) + scaling=r; + else + scaling=100; + __android_log_print(ANDROID_LOG_INFO,"VNC","scaling to %d percent\n",scaling); + break; } } i++; diff --git a/jni/vnc/fbvncserver.c~ b/jni/vnc/fbvncserver.c~ new file mode 100755 index 0000000..a287cc3 --- /dev/null +++ b/jni/vnc/fbvncserver.c~ @@ -0,0 +1,752 @@ +/* + * $Id$ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version.* + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * This project is an adaptation of the original fbvncserver for the iPAQ + * and Zaurus. + * + * This is a modification from letsgoustc source, to handle uinput events and more + * + */ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include /* For makedev() */ + +#include +#include +#include + +#include +#include +//android log +#include + +/* libvncserver */ +#include "rfb/rfb.h" +#include "libvncserver/scale.h" +#include "rfb/keysym.h" +#include "suinput.h" + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + + +#define BUS_VIRTUAL 0x06 + + +/*****************************************************************************/ +/* Android does not use /dev/fb0. */ +#define FB_DEVICE "/dev/graphics/fb0" +static char VNC_PASSWORD[256] = ""; + +static struct fb_var_screeninfo scrinfo; +static struct fb_fix_screeninfo fscrinfo; +static int fbfd = -1; +static int inputfd = -1; + +static unsigned int *fbmmap = MAP_FAILED; +static unsigned int *vncbuf; +static unsigned int *cmpbuf; + +/* Android already has 5900 bound natively. */ +#define VNC_PORT 5901 +static rfbScreenInfoPtr vncscr; + +int idle=0,standby=0,change=0; +static int rotation=0,scaling=0; +/*****************************************************************************/ + +static void (*update_screen)(void)=NULL; +static void keyevent(rfbBool down, rfbKeySym key, rfbClientPtr cl); +static void ptrevent(int buttonMask, int x, int y, rfbClientPtr cl); +static void rotate(); + +/*****************************************************************************/ + +void update_fb_info() +{ + + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &scrinfo) != 0) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","ioctl error\n"); + exit(EXIT_FAILURE); + } +} + + +#define OUT 32 +#include "update_screen.c" +#define OUT 8 +#include "update_screen.c" +#define OUT 16 +#include "update_screen.c" + +static void init_fb(void) +{ + size_t pixels; + size_t bytespp; + + if ((fbfd = open(FB_DEVICE, O_RDWR)) == -1) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","cannot open fb device %s\n", FB_DEVICE); + return; + // exit(EXIT_FAILURE); + } + + update_fb_info(); + + if (ioctl(fbfd, FBIOGET_FSCREENINFO, &fscrinfo) != 0) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","ioctl error\n"); + exit(EXIT_FAILURE); + } + + pixels = scrinfo.xres * scrinfo.yres; + bytespp = scrinfo.bits_per_pixel /CHAR_BIT; + + __android_log_print(ANDROID_LOG_INFO,"VNC", "xres=%d, yres=%d, xresv=%d, yresv=%d, xoffs=%d, yoffs=%d, bpp=%d\n", + (int)scrinfo.xres, (int)scrinfo.yres, + (int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual, + (int)scrinfo.xoffset, (int)scrinfo.yoffset, + (int)scrinfo.bits_per_pixel); + +// off_t o=0; + + //now handled with double buffer detection +// if (scrinfo.xres==480 && scrinfo.yres==854 && scrinfo.xres_virtual==480 +// && scrinfo.yres_virtual==854 && scrinfo.xoffset==448 && scrinfo.yoffset==1710) +/*if (scrinfo.bits_per_pixel==32) + // tweak for motorola droid + { + int off=scrinfo.xres*scrinfo.yres*scrinfo.bits_per_pixel/CHAR_BIT; + + int resto= off % sysconf(_SC_PAGE_SIZE); + o= off / sysconf(_SC_PAGE_SIZE); + if (resto) + o+=1; + + } */ + +// __android_log_print(ANDROID_LOG_INFO,"VNC","buffer offset=%d * %d\n",o,(int)sysconf(_SC_PAGE_SIZE)); +// +// fbmmap = mmap(NULL, (scrinfo.xres_virtual*scrinfo.yres_virtual)* bytespp , PROT_READ|PROT_READ , MAP_PRIVATE , fbfd, o*sysconf(_SC_PAGE_SIZE)); + fbmmap = mmap(NULL, (scrinfo.xres_virtual*scrinfo.yres_virtual)* bytespp , PROT_READ|PROT_READ , MAP_PRIVATE , fbfd, 0); + + + if (fbmmap == MAP_FAILED) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","mmap failed\n"); + exit(EXIT_FAILURE); + } +} + +static void cleanup_fb(void) +{ + if(fbfd != -1) + { + close(fbfd); + } +} + +static void init_input() +{ + struct input_id id = { + BUS_VIRTUAL, /* Bus type. */ + 1, /* Vendor id. */ + 1, /* Product id. */ + 1 /* Version id. */ + }; + + if((inputfd = suinput_open("qwerty", &id)) == -1) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","cannot create virtual kbd device.\n"); + // exit(EXIT_FAILURE); do not exit, so we still can see the framebuffer + } +} + +static void cleanup_kbd() +{ + if(inputfd != -1) + { + suinput_close(inputfd); + } +} + +/*****************************************************************************/ + +static rfbNewClientHookPtr clientHook(rfbClientPtr cl) +{ + if (scaling!=0 && scaling!=100) + { + rfbScalingSetup(cl, vncscr->width*scaling/100.0, vncscr->height*scaling/100.0); + rfbSendNewScaleSize(cl); + } + + return RFB_CLIENT_ACCEPT; +} + + +static void init_fb_server(int argc, char **argv) +{ + + __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing server...\n"); + + vncbuf = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel/CHAR_BIT); + cmpbuf = calloc(scrinfo.xres * scrinfo.yres, scrinfo.bits_per_pixel/CHAR_BIT); + + assert(vncbuf != NULL); + assert(cmpbuf != NULL); + + + + if (rotation==0 || rotation==180) + vncscr = rfbGetScreen(&argc, argv, scrinfo.xres, scrinfo.yres, 0 /* not used */ , 3, scrinfo.bits_per_pixel/CHAR_BIT); + else + vncscr = rfbGetScreen(&argc, argv, scrinfo.yres, scrinfo.xres, 0 /* not used */ , 3, scrinfo.bits_per_pixel/CHAR_BIT); + + assert(vncscr != NULL); + + vncscr->desktopName = "Android"; + vncscr->frameBuffer =(char *)vncbuf; + vncscr->port = VNC_PORT; + + vncscr->kbdAddEvent = keyevent; + vncscr->ptrAddEvent = ptrevent; + vncscr->newClientHook = clientHook; + + if (strcmp(VNC_PASSWORD,"")!=0) + { + char **passwords = (char **)malloc(2 * sizeof(char **)); + passwords[0] = VNC_PASSWORD; + passwords[1] = NULL; + vncscr->authPasswdData = passwords; + vncscr->passwordCheck = rfbCheckPasswordByList; + } + +#ifdef DONATE_VERSION + vncscr->httpDir="/data/data/org.onaips.vnc_donate/"; +#else + vncscr->httpDir="/data/data/org.onaips.vnc/"; +#endif + vncscr->serverFormat.redShift=scrinfo.red.offset; + vncscr->serverFormat.greenShift=scrinfo.green.offset; + vncscr->serverFormat.blueShift=scrinfo.blue.offset; + + vncscr->serverFormat.redMax=((1<serverFormat.greenMax=((1<serverFormat.blueMax=((1<alwaysShared = TRUE; + vncscr->handleEventsEagerly = TRUE; + vncscr->deferUpdateTime = 5; + + rfbInitServer(vncscr); + + //assign update_screen depending on bpp + if (vncscr->serverFormat.bitsPerPixel == 32) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","I'm on update_screen_32"); + update_screen=&CONCAT2E(update_screen_,32); + } + else if (vncscr->serverFormat.bitsPerPixel == 16) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","I'm on update_screen_16"); + update_screen=&CONCAT2E(update_screen_,16); + } + else if (vncscr->serverFormat.bitsPerPixel == 8) + { + __android_log_print(ANDROID_LOG_INFO,"VNC","I'm on update_screen_8"); + update_screen=&CONCAT2E(update_screen_,8); + } + else { + rfbErr("Unsupported pixel depth: %d\n", + vncscr->serverFormat.bitsPerPixel); + return; + } + + + /* Mark as dirty since we haven't sent any updates at all yet. */ + + rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.xres, scrinfo.yres); + rfbProcessEvents(vncscr, 100000); + +} + +static int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt); + + +static void keyevent(rfbBool down, rfbKeySym key, rfbClientPtr cl) +{ + int code; + + __android_log_print(ANDROID_LOG_INFO,"VNC","Got keysym: %04x (down=%d)\n", (unsigned int)key, (int)down); + + int sh = 0; + int alt = 0; + + if ((code = keysym2scancode(down, key, cl,&sh,&alt))) + { + + int ret; + + if (key && down) + { + if (sh) suinput_press(inputfd, 42); //left shift + if (alt) suinput_press(inputfd, 56); //left alt + + ret=suinput_press(inputfd,code); + ret=suinput_release(inputfd,code); + + if (alt) suinput_release(inputfd, 56); //left alt + if (sh) suinput_release(inputfd, 42); //left shift + } + else + ;//ret=suinput_release(inputfd,code); + + //__android_log_print(ANDROID_LOG_INFO,"VNC","injectKey (%d, %d) ret=%d\n", code , down,ret); + } +} + +// keyboard code modified from remote input by http://www.math.bme.hu/~morap/RemoteInput/ + +// q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m +int qwerty[] = {30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,19,31,20,22,47,17,45,21,44}; +// ,!,",#,$,%,&,',(,),*,+,,,-,.,/ +int spec1[] = {57,2,40,4,5,6,8,40,10,11,9,13,51,12,52,52}; +int spec1sh[] = {0,1,1,1,1,1,1,0,1,1,1,1,0,0,0,1}; +// :,;,<,=,>,?,@ +int spec2[] = {39,39,227,13,228,53,215}; +int spec2sh[] = {1,0,1,1,1,1,0}; +// [,\,],^,_,` +int spec3[] = {26,43,27,7,12,399}; +int spec3sh[] = {0,0,0,1,1,0}; +// {,|,},~ +int spec4[] = {26,43,27,215,14}; +int spec4sh[] = {1,1,1,1,0}; + +static int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt) +{ + int real=1; + if ('a' <= c && c <= 'z') + return qwerty[c-'a']; + if ('A' <= c && c <= 'Z') + { + (*sh)=1; + return qwerty[c-'A']; + } + if ('1' <= c && c <= '9') + return c-'1'+2; + if (c == '0') + return 11; + if (32 <= c && c <= 47) + { + (*sh) = spec1sh[c-32]; + return spec1[c-32]; + } + if (58 <= c && c <= 64) + { + (*sh) = spec2sh[c-58]; + return spec2[c-58]; + } + if (91 <= c && c <= 96) + { + (*sh) = spec3sh[c-91]; + return spec3[c-91]; + } + if (123 <= c && c <= 127) + { + (*sh) = spec4sh[c-123]; + return spec4[c-123]; + } + switch(c) + { + case 0xff08: return 14;// backspace + case 0xff09: return 15;// tab + case 1: (*alt)=1; return 34;// ctrl+a + case 3: (*alt)=1; return 46;// ctrl+c + case 4: (*alt)=1; return 32;// ctrl+d + case 18: (*alt)=1; return 31;// ctrl+r + case 0xff0D: return 28;// enter + case 0xff1B: return 158;// esc -> back + case 0xFF51: return 105;// left -> DPAD_LEFT + case 0xFF53: return 106;// right -> DPAD_RIGHT + case 0xFF54: return 108;// down -> DPAD_DOWN + case 0xFF52: return 103;// up -> DPAD_UP + // case 360: return 232;// end -> DPAD_CENTER (ball click) + case 0xff50: return KEY_HOME;// home + case 0xFFC8: rfbShutdownServer(cl->screen,TRUE); return 0; //F11 disconnect + case 0xFFC9: + __android_log_print(ANDROID_LOG_INFO,"VNC","F12 closing..."); + exit(0); //F10 closes daemon + break; + case 0xffc1: down?rotate():0; return 0; // F4 rotate + case 0xffff: return 158;// del -> back + case 0xff55: return 229;// PgUp -> menu + case 0xffcf: return 127;// F2 -> search + case 0xff56: return 61;// PgUp -> call + case 0xff57: return 107;// End -> endcall + case 0xffc2: return 211;// F5 -> focus + case 0xffc3: return 212;// F6 -> camera + case 0xffc4: return 150;// F7 -> explorer + case 0xffc5: return 155;// F8 -> envelope + + case 50081: + case 225: (*alt)=1; + if (real) return 48; //a with acute + return 30; //a with acute -> a with ring above + case 50049: + case 193:(*sh)=1; (*alt)=1; + if (real) return 48; //A with acute + return 30; //A with acute -> a with ring above + case 50089: + case 233: (*alt)=1; return 18; //e with acute + case 50057: + case 201:(*sh)=1; (*alt)=1; return 18; //E with acute + case 50093: + case 0xffbf: (*alt)=1; + if (real) return 36; //i with acute + return 23; //i with acute -> i with grave + case 50061: + case 205: (*sh)=1; (*alt)=1; + if (real) return 36; //I with acute + return 23; //I with acute -> i with grave + case 50099: + case 243:(*alt)=1; + if (real) return 16; //o with acute + return 24; //o with acute -> o with grave + case 50067: + case 211:(*sh)=1; (*alt)=1; + if (real) return 16; //O with acute + return 24; //O with acute -> o with grave + case 50102: + case 246: (*alt)=1; return 25; //o with diaeresis + case 50070: + case 214: (*sh)=1; (*alt)=1; return 25; //O with diaeresis + case 50577: + case 245:(*alt)=1; + if (real) return 19; //Hungarian o + return 25; //Hungarian o -> o with diaeresis + case 50576: + case 213: (*sh)=1; (*alt)=1; + if (real) return 19; //Hungarian O + return 25; //Hungarian O -> O with diaeresis + case 50106: + // case 0xffbe: (*alt)=1; + // if (real) return 17; //u with acute + // return 22; //u with acute -> u with grave + case 50074: + case 218: (*sh)=1; (*alt)=1; + if (real) return 17; //U with acute + return 22; //U with acute -> u with grave + case 50108: + case 252: (*alt)=1; return 47; //u with diaeresis + case 50076: + case 220:(*sh)=1; (*alt)=1; return 47; //U with diaeresis + case 50609: + case 251: (*alt)=1; + if (real) return 45; //Hungarian u + return 47; //Hungarian u -> u with diaeresis + case 50608: + case 219: (*sh)=1; (*alt)=1; + if (real) return 45; //Hungarian U + return 47; //Hungarian U -> U with diaeresis + + } + return 0; +} + +// old key code, i'll need it for some missing things +/* +static int _keysym2scancode(rfbBool down, rfbKeySym key, rfbClientPtr cl) +{ + int scancode = 0; + + int code = (int)key; + if (code>='0' && code<='9') { + + scancode = (code & 0xF) - 1; + if (scancode<0) scancode += 10; + scancode += KEY_1; + } else if (code>=0xFF50 && code<=0xFF58) { + static const uint16_t map[] = + { KEY_HOME, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN, + KEY_SOFT1, KEY_SOFT2, KEY_END, 0 }; + + scancode = map[code & 0xF]; + } else if (code>=0xFFE1 && code<=0xFFEE) { + + + static const uint16_t map[] = + { KEY_LEFTSHIFT, KEY_LEFTSHIFT, + KEY_COMPOSE, KEY_COMPOSE, + KEY_LEFTSHIFT, KEY_LEFTSHIFT, + 0,0, + KEY_LEFTALT, KEY_RIGHTALT, + 0, 0, 0, 0 }; + scancode = map[code & 0xF]; + } else if ((code>='A' && code<='Z') || (code>='a' && code<='z')) { + + static const uint16_t map[] = { + KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, + KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, + KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, + KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, + KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z }; + scancode = map[(code & 0x5F) - 'A']; + } else { + + switch (code) { + case 0x0003: scancode = KEY_CENTER; break; + case 0x0020: scancode = KEY_SPACE; break; + case 0x0023: scancode = KEY_SHARP; break; + case 0x0033: scancode = KEY_SHARP; break; + case 0x002C: scancode = KEY_COMMA; break; + case 0x003C: scancode = KEY_COMMA; break; + case 0x002E: scancode = KEY_DOT; break; + case 0x003E: scancode = KEY_DOT; break; + case 0x002F: scancode = KEY_SLASH; break; + case 0x003F: scancode = KEY_SLASH; break; + case 0x0032: scancode = KEY_EMAIL; break; + case 0x0040: scancode = KEY_EMAIL; break; + case 0xFF08: scancode = KEY_BACKSPACE; break; + case 0xFF1B: scancode = KEY_BACK; break; + case 0xFF09: scancode = KEY_TAB; break; + case 0xFF0D: scancode = KEY_ENTER; break; + case 0xFE51: scancode = 399; break; + case 0x002A: scancode = KEY_STAR; break; + case 0xFFBE: scancode = KEY_F1; break; // F1 + case 0xFFBF: scancode = KEY_F2; break; // F2 + case 0xFFC0: scancode = KEY_F3; break; // F3 + case 0xFFC1: down?rotate():0; break; // F4 rotate + case 0xFFC5: scancode = KEY_F4; break; // F8 + case 0xFFC8: rfbShutdownServer(cl->screen,TRUE); break; // F11 + } + } + + return scancode; +} +*/ + + +inline void transform_touch_coordinates(int *x, int *y) +{ + int scale=4096.0; + int old_x=*x,old_y=*y; + + if (rotation==0) + { + *x = old_x*scale/scrinfo.xres-scale/2.0; + *y = old_y*scale/scrinfo.yres-scale/2.0; + } + else if (rotation==90) + { + *x =old_y*scale/scrinfo.xres-scale/2.0; + *y = (scrinfo.yres - old_x)*scale/scrinfo.yres-scale/2.0; + } + else if (rotation==180) + { + *x =(scrinfo.xres - old_x)*scale/scrinfo.xres-scale/2.0; + *y =(scrinfo.yres - old_y)*scale/scrinfo.yres-scale/2.0; + } + else if (rotation==270) + { + *y =old_x*scale/scrinfo.yres-scale/2.0; + *x =(scrinfo.xres - old_y)*scale/scrinfo.xres-scale/2.0; + } + +} + +static void ptrevent(int buttonMask, int x, int y, rfbClientPtr cl) +{ + static int leftClicked=0,rightClicked=0,middleClicked=0; + + transform_touch_coordinates(&x,&y); + + if((buttonMask & 1)&& leftClicked) {//left btn clicked and moving + static int i=0; + i=i+1; + + if (i%10==1)//some tweak to not report every move event + { + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + } + } + else if (buttonMask & 1)//left btn clicked + { + leftClicked=1; + + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd,EV_KEY,BTN_TOUCH,1); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + + + } + else if (leftClicked)//left btn released + { + leftClicked=0; + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd,EV_KEY,BTN_TOUCH,0); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + } + + if (buttonMask & 4)//right btn clicked + { + rightClicked=1; + suinput_press(inputfd,158); //back key + } + else if (rightClicked)//right button released + { + rightClicked=0; + suinput_release(inputfd,158); + } + + if (buttonMask & 2)//mid btn clicked + { + middleClicked=1; + suinput_press( inputfd,KEY_END); + } + else if (middleClicked)// mid btn released + { + middleClicked=0; + suinput_release( inputfd,KEY_END); + } +} + +void sigproc() +{ + __android_log_print(ANDROID_LOG_INFO,"VNC","Cleaning up...\n"); + cleanup_fb(); + cleanup_kbd(); + exit(0); /* normal exit status */ +} + + + +static void rotate() +{ + rotation+=90; + rotation=rotation%360; + + + if (rotation==90 || rotation==270) + rfbNewFramebuffer(vncscr,(char*)vncbuf, scrinfo.yres, scrinfo.xres,0 /* not used */ , 3, scrinfo.bits_per_pixel/CHAR_BIT); + else + rfbNewFramebuffer(vncscr,(char*)vncbuf, scrinfo.xres, scrinfo.yres,0 /* not used */ , 3, scrinfo.bits_per_pixel/CHAR_BIT); + + vncscr->serverFormat.redShift=scrinfo.red.offset; + vncscr->serverFormat.greenShift=scrinfo.green.offset; + vncscr->serverFormat.blueShift=scrinfo.blue.offset; + + vncscr->serverFormat.redMax=((1<serverFormat.greenMax=((1<serverFormat.blueMax=((1<width, vncscr->height); + +} + +void print_usage(char **argv) +{ + __android_log_print(ANDROID_LOG_INFO,"VNC","androidvncserver [-p password] [-h]\n" + "-p password: Password to access server\n" + "-r rotation: Screen rotation (degrees) (0,90,180,270)\n" + "-s screen scale: percentage (20,30,50,100,150)\n" + "-h : print this help\n"); +} + + +int main(int argc, char **argv) +{ + signal(SIGINT, sigproc);//pipe signals + signal(SIGKILL, sigproc); + signal(SIGILL, sigproc); + + if(argc > 1) + { + int i=1; + int r; + while(i < argc) + { + if(*argv[i] == '-') + { + switch(*(argv[i] + 1)) + { + case 'h': + print_usage(argv); + exit(0); + break; + case 'p': + i++; + strcpy(VNC_PASSWORD,argv[i]); + break; + case 'r': + i++; + r=atoi(argv[i]); + if (r==0 || r==90 || r==180 || r==270) + rotation=r; + __android_log_print(ANDROID_LOG_INFO,"VNC","rotating to %d degrees\n",rotation); + break; + case 's': + i++; + r=atoi(argv[i]); + if (r>=1 && r <= 150) + scaling=r; + else + scaling=100; + __android_log_print(ANDROID_LOG_INFO,"VNC","scaling to %d percent\n",scaling); + break; + } + } + i++; + } + } + + __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing framebuffer device " FB_DEVICE "...\n"); + init_fb(); + + __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing virtual keyboard and touch device...\n"); + init_input(); + + __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing VNC server:\n"); + __android_log_print(ANDROID_LOG_INFO,"VNC"," width: %d\n", (int)scrinfo.xres); + __android_log_print(ANDROID_LOG_INFO,"VNC"," height: %d\n", (int)scrinfo.yres); + __android_log_print(ANDROID_LOG_INFO,"VNC"," bpp: %d\n", (int)scrinfo.bits_per_pixel); + __android_log_print(ANDROID_LOG_INFO,"VNC"," port: %d\n", (int)VNC_PORT); + init_fb_server(argc, argv); + + while (1) + { + + while (vncscr->clientHead == NULL) + rfbProcessEvents(vncscr, 100000); + + update_screen(); + } + + __android_log_print(ANDROID_LOG_INFO,"VNC","Cleaning up...\n"); + cleanup_fb(); + cleanup_kbd(); +} \ No newline at end of file diff --git a/jni/vnc/update_screen.c b/jni/vnc/update_screen.c index 3669c66..28c2829 100644 --- a/jni/vnc/update_screen.c +++ b/jni/vnc/update_screen.c @@ -5,14 +5,18 @@ void FUNCTION(void) { static int i,j,offset; - update_fb_info(); + update_fb_info(); - //detect active buffer - if (scrinfo.yoffset) - offset=scrinfo.xres*scrinfo.yres; - else - offset=0; +// // detect active buffer +// offset= (scrinfo.xoffset) * (scrinfo.bits_per_pixel/8) + +// (scrinfo.yoffset) * scrinfo.xres; +// if (scrinfo.yoffset) +// offset=scrinfo.xres*scrinfo.yoffset; +// else +// offset=0; + offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT; + OUT_T* a = (OUT_T*)cmpbuf; OUT_T* b = (OUT_T*)fbmmap; @@ -61,10 +65,12 @@ void FUNCTION(void) if (imax_x) - max_x=j; - if (j max_x) + max_x=scrinfo.yres-j; if (idle) idle=0; @@ -113,35 +119,39 @@ void FUNCTION(void) if (imax_x) - max_x=j; - if (j max_x) + max_x=scrinfo.yres-j; if (idle) idle=0; } } } - - } + +} memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); + if (min_x!=9999 && min_y!=9999 && max_x!=-1 && max_y!=-1) { - min_x--; - max_x++; - min_y--; - max_y++; +// min_x--; + max_x++; +// min_y--; + max_y++; rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, max_y); rfbProcessEvents(vncscr, 10000); - } + } -// rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.yres,scrinfo.xres); -// rfbProcessEvents(vncscr, 10000); +// rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.yres,scrinfo.xres); +// rfbProcessEvents(vncscr, 10000); + if (idle) { @@ -151,8 +161,8 @@ memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); rfbProcessEvents(vncscr, 1000000); else rfbProcessEvents(vncscr, 100000); - -// printf("standby %d xoff=%d yoff=%d\n",standby,scrinfo.xres,scrinfo.yres); + +// __android_log_print(ANDROID_LOG_INFO,"VNC","standby %d xoff=%d yoff=%d\n",standby,scrinfo.xoffset,scrinfo.yoffset); change=0; } else @@ -160,6 +170,6 @@ memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); change=change+1; standby=0; rfbProcessEvents(vncscr, 100000); -// printf("change %d\tmin_x=%d max_x=%d min_y=%d max_y=%d xoff=%d yoff=%d\n",change,min_x,max_x,min_y,max_y,scrinfo.xoffset,scrinfo.yoffset); +// __android_log_print(ANDROID_LOG_INFO,"VNC","change %d\tmin_x=%d max_x=%d min_y=%d max_y=%d xoff=%d yoff=%d\n",change,min_x,max_x,min_y,max_y,scrinfo.xoffset,scrinfo.yoffset); } } diff --git a/jni/vnc/update_screen.c~ b/jni/vnc/update_screen.c~ new file mode 100644 index 0000000..d8bedfb --- /dev/null +++ b/jni/vnc/update_screen.c~ @@ -0,0 +1,175 @@ +#define OUT_T CONCAT3E(uint,OUT,_t) +#define FUNCTION CONCAT2E(update_screen_,OUT) + +void FUNCTION(void) +{ + static int i,j,offset; + + update_fb_info(); + +// // detect active buffer +// offset= (scrinfo.xoffset) * (scrinfo.bits_per_pixel/8) + +// (scrinfo.yoffset) * scrinfo.xres; +// if (scrinfo.yoffset) +// offset=scrinfo.xres*scrinfo.yoffset; +// else +// offset=0; + + offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT; + + OUT_T* a = (OUT_T*)cmpbuf; + OUT_T* b = (OUT_T*)fbmmap; + + int max_x=-1,max_y=-1, min_x=9999, min_y=9999; + idle=1; + + if (rotation==0) + { + //memcpy(vncbuf,fbmmap,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); + for (j = 0; j < scrinfo.yres; j++) + { + for (i = 0; i < scrinfo.xres; i++) + { + if (a[i + j * scrinfo.xres]!=b[i + j * scrinfo.xres + offset ]) + { + a[i + j * scrinfo.xres]=b[i + j * scrinfo.xres + offset]; + + if (i>max_x) + max_x=i; + if (imax_y) + max_y=j; + if (jmax_y) + max_y=i; + if (i max_x) + max_x=scrinfo.yres-j; + + if (idle) + idle=0; + } + } + } + } + else if (rotation==180) + { + for (j = 0; j < scrinfo.yres; j++) + { + for (i = 0; i < scrinfo.xres; i++) + { + if (a[i + j * scrinfo.xres]!=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres ) + offset ]) + { + a[i + j * scrinfo.xres]=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres) + offset ]; + + if (i>max_x) + max_x=i; + if (imax_y) + max_y=j; + if (jmax_y) + max_y=i; + if (i max_x) + max_x=scrinfo.yres-j; + + if (idle) + idle=0; + } + } + } + +} + +memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); + + + + if (min_x!=9999 && min_y!=9999 && max_x!=-1 && max_y!=-1) + { +// min_x--; + max_x++; +// min_y--; + max_y++; + + rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, max_y); + rfbProcessEvents(vncscr, 10000); + } + +// rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.yres,scrinfo.xres); +// rfbProcessEvents(vncscr, 10000); + + + if (idle) + { + standby=standby+1; + + if (standby>30) + rfbProcessEvents(vncscr, 1000000); + else + rfbProcessEvents(vncscr, 100000); + + __android_log_print(ANDROID_LOG_INFO,"VNC","standby %d xoff=%d yoff=%d\n",standby,scrinfo.xoffset,scrinfo.yoffset); + change=0; + } + else + { + change=change+1; + standby=0; + rfbProcessEvents(vncscr, 100000); + __android_log_print(ANDROID_LOG_INFO,"VNC","change %d\tmin_x=%d max_x=%d min_y=%d max_y=%d xoff=%d yoff=%d\n",change,min_x,max_x,min_y,max_y,scrinfo.xoffset,scrinfo.yoffset); + } +} diff --git a/libs/armeabi/androidvncserver b/libs/armeabi/androidvncserver index 004f7c4..8bfbfcc 100755 Binary files a/libs/armeabi/androidvncserver and b/libs/armeabi/androidvncserver differ diff --git a/res/layout/main.xml b/res/layout/main.xml index 5386b86..5b51a40 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -53,10 +53,10 @@ - +/> diff --git a/res/raw/androidvncserver b/res/raw/androidvncserver index 004f7c4..8bfbfcc 100755 Binary files a/res/raw/androidvncserver and b/res/raw/androidvncserver differ diff --git a/res/values/strings.xml b/res/values/strings.xml index c2fad89..b209906 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7,6 +7,21 @@ 180 270 + +150 +100 +50 +30 +20 + + +150 % +100 % +50 % +30 % +20 % + + droid VNC version: %s\n Device model: %s\n diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 8fd5026..b1e5258 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -3,6 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android"> + diff --git a/src/org/onaips/vnc/MainActivity.java b/src/org/onaips/vnc/MainActivity.java new file mode 100644 index 0000000..3ffb58d --- /dev/null +++ b/src/org/onaips/vnc/MainActivity.java @@ -0,0 +1,713 @@ +/* + * 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. + */ +package org.onaips.vnc; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Color; +import android.net.DhcpInfo; +import android.net.Uri; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Html; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +public class MainActivity extends Activity +{ + private static final int MENU_QUIT = 0; + private static final int MENU_HELP = 1; + private static final int MENU_ONAIPS = 2; + private static final int MENU_SENDLOG = 3; + private static final String changelog="-PLEASE REPORT FEEDBACK! (send debug info in menu)
- [Add] Server-side screen scaling (change it in preferences - BETA)
- [Fix] Half-screen bug
New icon
Courtesy of Sandro Forbice (@sandroforbice)
- [Fix] Double buffering now supported
- [Add] Low CPU on idle screen while connected
- [Fix] Update while rotated"; + + + SharedPreferences preferences; + ProgressDialog dialog=null; + AlertDialog startDialog; + + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.main); + + + // Initialize preferences + preferences = PreferenceManager.getDefaultSharedPreferences(this); + + if (!hasRootPermission()) + { + Log.v("VNC","You don't have root permissions...!!!"); + showTextOnScreen("You don't have root permissions...Please ROOT your phone first!!!"); + //System.exit(-1); + } + + showInitialScreen(); + createBinary(); + + + boolean serverRunning=isAndroidServerRunning(); + + setStateLabel(serverRunning); + TextView t=(TextView)findViewById(R.id.TextView01); + + if (serverRunning) + t.setText("Connect to:\n" + getIpAddress()+":5901" + "\nor\nhttp://" + getIpAddress() + ":5801"); + else + t.setText(""); + + + findViewById(R.id.Button01).setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + Thread t=new Thread(){ + public void run() + { + startServerButtonClicked(); + + } + }; + t.start(); + + try { + Thread.sleep(1000); + for (int i=0;i<5;i++) + { + + if (!isAndroidServerRunning()) + Thread.sleep(1000); + else + break; + } + } catch (InterruptedException e) { + // TODO Auto-generated catch block + Log.v("VNC","Button01_click:"+ e.getMessage()); + } + + boolean s=isAndroidServerRunning(); + if (!s) + showTextOnScreen("Couldn't start VNC Server"); + //setStateLabel(s); + return; + } + }) ; + findViewById(R.id.Button02).setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + + Thread t=new Thread(){ + public void run() + { + stopServer(); + + } + }; + t.start(); + + try { + Thread.sleep(1000); + + + for (int i=0;i<5;i++) + { + if (isAndroidServerRunning()) + Thread.sleep(1000); + else + break; + } + } catch (InterruptedException e) { + Log.v("VNC","Button02_click:"+ e.getMessage()); + + } + boolean s=isAndroidServerRunning(); + if (s) + showTextOnScreen("Couldn't Stop VNC Server\nTry hitting F12 on a connected client"); + //setStateLabel(s); + return; + } + }); + + } + + public String packageVersion() + { + String version = ""; + try { + PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0); + version = pi.versionName; + } catch (NameNotFoundException e) { + // TODO Auto-generated catch block + Log.v("VNC","onOptionsItemSelected: "+ e.getMessage()); + }; + return version; + } + + public boolean free_version() + { + return getPackageName().equals("org.onaips.vnc"); + } + + public void showInitialScreen() + { + // Initialize preferences + preferences = PreferenceManager.getDefaultSharedPreferences(this ); + SharedPreferences.Editor editor = preferences.edit(); + + String message="Changelog:

" + changelog; + + String version=packageVersion(); + + if (!free_version()) + { + if (version.equals(preferences.getString("version", ""))) + return; + editor.putString("version", version); + editor.commit(); + } + + + startDialog = new AlertDialog.Builder(this).create(); + startDialog.setTitle("droid VNC Server " + version); + startDialog.setMessage(Html.fromHtml(message)); + startDialog.setIcon(R.drawable.icon); + + if (free_version()) + { + startDialog.setButton(AlertDialog.BUTTON1,"Wait...", new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface arg0, int arg1) { + startDialog.dismiss(); + } + }); + + + + startDialog.setButton2("Donate Version", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=org.onaips.vnc_donate")); + startActivity(myIntent); + + } + }); + + startDialog.setCancelable(false); + startDialog.show(); + + Button b=(Button)startDialog.getButton(AlertDialog.BUTTON1); + b.setEnabled(false); + + Timer t1=new Timer(); + t1.schedule(new TimerTask() { + @Override + public void run() { + runOnUiThread(new Runnable(){ + public void run() { + // ((DialogInterface) startDialog).dismiss(); + Button b=(Button)startDialog.getButton(AlertDialog.BUTTON1); + b.setEnabled(true); + b.setText("OK"); + } + }); + } + }, (long)10000); + } + else + startDialog.show(); + } + + static void writeCommand(OutputStream os, String command) throws Exception + { + os.write((command + "\n").getBytes("ASCII")); + } + + + + public void showTextOnScreen(final String t) + { + runOnUiThread(new Runnable(){ + public void run() { + Toast.makeText(MainActivity.this,t,Toast.LENGTH_LONG).show(); + } + }); + } + + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu, menu); + + menu.add(0,MENU_SENDLOG,0,"Send debug info"); + menu.add(0,MENU_ONAIPS,0,"About"); + menu.add(0, MENU_HELP, 0, "Help"); + menu.add(0, MENU_QUIT, 0, "Close"); + + return true; + } + + public void setStateLabel(boolean state) + { + TextView stateLabel=(TextView)findViewById(R.id.stateLabel); + stateLabel.setText(state?"Running":"Stopped"); + stateLabel.setTextColor(state?Color.GREEN:Color.RED); + } + + public String getIpAddress() + { + WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); + DhcpInfo dhcpInfo = wifiManager.getDhcpInfo(); + + + return intToIp(dhcpInfo.ipAddress); + } + + boolean wifiConnected() + { + WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + + return info.getBSSID()!=null; + } + + private String intToIp(int i) { + return ( i & 0xFF) + "." + ((i >> 8 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >> 24 ) & 0xFF); + } + + public void stopServer() + { + try{ + Process sh; + + sh = Runtime.getRuntime().exec("su"); + OutputStream os = sh.getOutputStream(); + writeCommand(os, "killall androidvncserver"); + writeCommand(os, "killall -KILL androidvncserver"); + writeCommand(os, "exit"); + + os.flush(); + os.close(); + } catch (IOException e) { + showTextOnScreen("stopServer()" + e.getMessage()); + Log.v("VNC","stopServer()" + e.getMessage()); + } catch (Exception e) { + Log.v("VNC","stopServer()" + e.getMessage()); + } + + } + + public void startServerButtonClicked() + { + if (isAndroidServerRunning()) + { + new AlertDialog.Builder(this) + .setTitle("Alert") + .setMessage(Html.fromHtml("There is another daemon already running, do you want to kill it?")) + .setPositiveButton("Yes", new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface arg0, int arg1) { + stopServer(); + startServer(); + } + }) + .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + return; + } + }) + .show(); + } + else + startServer(); + } + + + public void startServer() + { + try{ + Process sh; + + String password=preferences.getString("password", ""); + String password_check=""; + if (!password.equals("")) + password_check="-p " + password; + + + String rotation=preferences.getString("rotation", "0"); + rotation="-r " + rotation; + + String scaling=preferences.getString("scale", "100"); + String scaling_string=""; + if (!scaling.equals("0")) + scaling_string="-s " + scaling; + + + sh = Runtime.getRuntime().exec("su"); + OutputStream os = sh.getOutputStream(); + writeCommand(os, "chmod 777 /data/data/"+getPackageName()+"/androidvncserver"); + writeCommand(os, "/data/data/"+getPackageName()+"/androidvncserver "+ password_check + " " + rotation + " " + scaling_string); + + + } catch (IOException e) { + Log.v("VNC","startServer():" + e.getMessage()); + showTextOnScreen("startServer():" + e.getMessage()); + } catch (Exception e) { + Log.v("VNC","startServer():" + e.getMessage()); + showTextOnScreen("startServer():" + e.getMessage()); + } + + } + + + + public void copyBinary(int id,String path) + { + try { + InputStream ins = getResources().openRawResource(id); + int size = ins.available(); + + // Read the entire resource into a local byte buffer. + byte[] buffer = new byte[size]; + ins.read(buffer); + ins.close(); + + FileOutputStream fos = new FileOutputStream(path); + fos.write(buffer); + fos.close(); + } + catch (Exception e) + { + Log.v("VNC","public void createBinary(): " + e.getMessage()); + } + + + } + public void createBinary() + { + copyBinary(R.raw.androidvncserver, "/data/data/" + getPackageName() + "/androidvncserver"); + copyBinary(R.raw.vncviewer, "/data/data/"+getPackageName()+"/VncViewer.jar"); + copyBinary(R.raw.indexvnc, "/data/data/"+getPackageName()+"/index.vnc"); + } + + public void showHelp() + { + new AlertDialog.Builder(this) + .setTitle("Help") + .setMessage(Html.fromHtml("Mouse Mappings:

Right Click -> Back
Middle Click -> End Call
Left Click -> Touch

Keyboard Mappings

" + + "Home Key -> Home
Escape -> Back
Page Up ->Menu
Left Ctrl -> Search
PgDown -> Start Call
" + + "End Key -> End Call
F4 -> Rotate
F11 -> Disconnect Server
F12 -> Stop Server Daemon")) + .setPositiveButton("Fechar", null) + .setNegativeButton("Open Website", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://onaips.blogspot.com")); + startActivity(myIntent); + } + }) + .show(); + } + + // This method is called once the menu is selected + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + // We have only one menu option + case R.id.preferences: + // Launch Preference activity + Intent i = new Intent(MainActivity.this, preferences.class); + startActivity(i); + + showTextOnScreen("Don't forget to stop/start the server after changes"); + + break; + case MENU_QUIT: + System.exit(1); + break; + case MENU_HELP: + showHelp(); + break; + case MENU_SENDLOG: + collectAndSendLog(); + break; + case MENU_ONAIPS: + + new AlertDialog.Builder(this) + .setTitle("About") + .setMessage(Html.fromHtml("version " + packageVersion() + "

developed by oNaiPs

Graphics: Sandro Forbice (@sandroforbice)

Open-Source Software")) + .setPositiveButton("Close", null) + .setNegativeButton("Open Website", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://onaips.blogspot.com")); + startActivity(myIntent); + + } + }) + .show(); + } + return true; + } + + public boolean isAndroidServerRunning() + { + String result=""; + Process sh; + try { + sh = Runtime.getRuntime().exec("ps"); + + + InputStream is=sh.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + + while ((line = br.readLine()) != null) { + result+=line; + if (result.indexOf("androidvncserver")>0) + return true; + } + OutputStream os = sh.getOutputStream(); + writeCommand(os, "exit"); + os.flush(); + os.close(); + } catch (IOException e) { + Log.v("VNC"," isAndroidServerRunning():" + e.getMessage()); + } catch (Exception e) { + Log.v("VNC"," isAndroidServerRunning():" + e.getMessage()); + } + + //Log.v("VNC",result); + + return false; + } + + + public boolean hasRootPermission() { + boolean rooted = true; + try { + File su = new File("/system/bin/su"); + if (su.exists() == false) { + su = new File("/system/xbin/su"); + if (su.exists() == false) { + rooted = false; + } + } + } catch (Exception e) { + Log.v("VNC", "Can't obtain root - Here is what I know: "+e.getMessage()); + rooted = false; + } + Process sh; + try { + String result=""; + + sh = Runtime.getRuntime().exec("whoami"); + + InputStream is=sh.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + + while ((line = br.readLine()) != null) { + result+=line; + if (result.indexOf("androidvncserver")>0) + return true; + } + + Process sh1=Runtime.getRuntime().exec("su"); + + //Log.v("aaaaaa","chgrp -R " + result + " /data/data/org.onaips.vnc/"); + + OutputStream os = sh1.getOutputStream(); + + writeCommand(os, "chown -R " + result + " /data/data/" + getPackageName() + "/"); + writeCommand(os, "chgrp -R " + result + " /data/data/" + getPackageName() + "/"); + os.flush(); + os.close(); + isr.close(); + is.close(); + + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return rooted; + } + + public static final String LOG_COLLECTOR_PACKAGE_NAME = "com.xtralogic.android.logcollector";//$NON-NLS-1$ + public static final String ACTION_SEND_LOG = "com.xtralogic.logcollector.intent.action.SEND_LOG";//$NON-NLS-1$ + public static final String EXTRA_SEND_INTENT_ACTION = "com.xtralogic.logcollector.intent.extra.SEND_INTENT_ACTION";//$NON-NLS-1$ + public static final String EXTRA_DATA = "com.xtralogic.logcollector.intent.extra.DATA";//$NON-NLS-1$ + public static final String EXTRA_ADDITIONAL_INFO = "com.xtralogic.logcollector.intent.extra.ADDITIONAL_INFO";//$NON-NLS-1$ + public static final String EXTRA_SHOW_UI = "com.xtralogic.logcollector.intent.extra.SHOW_UI";//$NON-NLS-1$ + public static final String EXTRA_FILTER_SPECS = "com.xtralogic.logcollector.intent.extra.FILTER_SPECS";//$NON-NLS-1$ + public static final String EXTRA_FORMAT = "com.xtralogic.logcollector.intent.extra.FORMAT";//$NON-NLS-1$ + public static final String EXTRA_BUFFER = "com.xtralogic.logcollector.intent.extra.BUFFER";//$NON-NLS-1$ + + void collectAndSendLog(){ + final PackageManager packageManager = getPackageManager(); + final Intent intent = new Intent(ACTION_SEND_LOG); + List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + final boolean isInstalled = list.size() > 0; + + if (!isInstalled){ + new AlertDialog.Builder(this) + .setTitle(getString(R.string.app_name)) + .setIcon(android.R.drawable.ic_dialog_info) + .setMessage("Please install Log Collector application to collect the device log and send it to dev.") + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + public void onClick(DialogInterface dialog, int whichButton){ + Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:" + LOG_COLLECTOR_PACKAGE_NAME)); + marketIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(marketIntent); + } + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + } + else{ + new AlertDialog.Builder(this) + .setTitle(getString(R.string.app_name)) + .setIcon(android.R.drawable.ic_dialog_info) + .setMessage("Do you want to send debug info to the dev? Please specify what problem is ocurring.\n\nMake sure you started/stopped the server before submitting") + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + public void onClick(DialogInterface dialog, int whichButton){ + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRA_SEND_INTENT_ACTION, Intent.ACTION_SENDTO); + final String email = "onaips@gmail.com"; + intent.putExtra(EXTRA_DATA, Uri.parse("mailto:" + email)); + intent.putExtra(EXTRA_ADDITIONAL_INFO,"Problem Description: \n\n\n\n---------DEBUG--------\n" + getString(R.string.device_info_fmt,getVersionNumber(getApplicationContext()),Build.MODEL,Build.VERSION.RELEASE, getFormattedKernelVersion(), Build.DISPLAY)); + + intent.putExtra(Intent.EXTRA_SUBJECT, "droid VNC server: Debug Info"); + + intent.putExtra(EXTRA_FORMAT, "time"); + + //The log can be filtered to contain data relevant only to your app + String[] filterSpecs = new String[4]; + filterSpecs[0] = "VNC:I"; + filterSpecs[1] = "VNC:D"; + filterSpecs[2] = "VNC:V"; + filterSpecs[3] = "*:S"; + intent.putExtra(EXTRA_FILTER_SPECS, filterSpecs); + + startActivity(intent); + } + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + } + } + + private String getFormattedKernelVersion() + { + String procVersionStr; + + try { + BufferedReader reader = new BufferedReader(new FileReader("/proc/version"), 256); + try { + procVersionStr = reader.readLine(); + } finally { + reader.close(); + } + + final String PROC_VERSION_REGEX = + "\\w+\\s+" + /* ignore: Linux */ + "\\w+\\s+" + /* ignore: version */ + "([^\\s]+)\\s+" + /* group 1: 2.6.22-omap1 */ + "\\(([^\\s@]+(?:@[^\\s.]+)?)[^)]*\\)\\s+" + /* group 2: (xxxxxx@xxxxx.constant) */ + "\\([^)]+\\)\\s+" + /* ignore: (gcc ..) */ + "([^\\s]+)\\s+" + /* group 3: #26 */ + "(?:PREEMPT\\s+)?" + /* ignore: PREEMPT (optional) */ + "(.+)"; /* group 4: date */ + + Pattern p = Pattern.compile(PROC_VERSION_REGEX); + Matcher m = p.matcher(procVersionStr); + + if (!m.matches()) { + Log.e("VNC", "Regex did not match on /proc/version: " + procVersionStr); + return "Unavailable"; + } else if (m.groupCount() < 4) { + Log.e("VNC", "Regex match on /proc/version only returned " + m.groupCount() + + " groups"); + return "Unavailable"; + } else { + return (new StringBuilder(m.group(1)).append("\n").append( + m.group(2)).append(" ").append(m.group(3)).append("\n") + .append(m.group(4))).toString(); + } + } catch (IOException e) { + Log.e("VNC", "IO Exception when getting kernel version for Device Info screen", e); + + return "Unavailable"; + } + } + + private static String getVersionNumber(Context context) + { + String version = "?"; + try + { + PackageInfo packagInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + version = packagInfo.versionName; + } + catch (PackageManager.NameNotFoundException e){}; + + return version; + } +} + diff --git a/src/org/onaips/vnc/preferences.java b/src/org/onaips/vnc/preferences.java new file mode 100644 index 0000000..f3443f6 --- /dev/null +++ b/src/org/onaips/vnc/preferences.java @@ -0,0 +1,18 @@ +package org.onaips.vnc; + + + + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class preferences extends PreferenceActivity { + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.preferences); + } +}