- [Add] Start daemon on boot (set on prefs)<br>-[Add] Change port on preferences<br>- [Add] Changelog on menu<br>- [Add] Dynamic network state detection<br>- [Fix] HTTP client now working again<br>- [Rem] Initial screen is only showed on new versions<br>- [Add] Don't let device sleep (set on prefs)<br>- [Fix] Better start/stop handling"

This commit is contained in:
Jose Pereira 2010-09-16 02:39:31 +01:00
parent ff3dae2152
commit 07d442b9fc
58 changed files with 2392 additions and 225 deletions

View File

@ -1,28 +1,48 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.onaips.vnc" android:versionCode="31" android:versionName="0.72"> android:versionName="0.89" android:versionCode="40" package="org.onaips.vnc_donate">
<uses-sdk android:minSdkVersion="4" /> <uses-sdk android:minSdkVersion="3" />
<application android:debuggable="false" android:icon="@drawable/icon" android:label="droid VNC server"> <application android:debuggable="false" android:icon="@drawable/icon"
<activity android:name=".MainActivity" android:label="@string/app_name" android:icon="@drawable/icon" android:launchMode="singleInstance" android:screenOrientation="portrait"> android:label="droid VNC server">
<intent-filter> <activity android:name=".MainActivity" android:label="@string/app_name"
<action android:name="android.intent.action.MAIN" /> android:icon="@drawable/icon" android:launchMode="singleInstance"
<category android:name="android.intent.category.LAUNCHER" /> android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="preferences" android:label="Preferences"></activity> <activity android:name="preferences" android:label="Preferences"></activity>
<meta-data android:name="com.mobclix.APPLICATION_ID" android:value="1F34160B-63BB-4854-BDB7-D46B7EADBF06"/> <meta-data android:name="com.mobclix.APPLICATION_ID"
<activity android:name="com.mobclix.android.sdk.MobclixBrowserActivity"/> android:value="1F34160B-63BB-4854-BDB7-D46B7EADBF06" />
<activity android:name="com.mobclix.android.sdk.MobclixBrowserActivity" />
</application> <service android:name="StartAtBootService">
<intent-filter>
<action android:name="org.onaips.vnc_donate.StartAtBootService"></action>
</intent-filter>
</service>
<uses-permission android:name="android.permission.ACCESS_SUPERUSER"></uses-permission> <receiver android:name="StartAtBootServiceReceiver">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <intent-filter>
<uses-permission android:name="android.permission.INTERNET"></uses-permission> <action android:name="android.intent.action.BOOT_COMPLETED">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> </action>
<uses-permission android:name="android.permission.GET_TASKS"></uses-permission> <category android:name="android.intent.category.HOME">
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> </category>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_SUPERUSER"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.GET_TASKS"></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
</manifest> </manifest>

Binary file not shown.

BIN
bin/avnc_signed.apk Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,198 @@
/* 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_donate;
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 int sleep_strings=0x7f070003;
public static final int startonboot_values=0x7f070004;
}
public static final class attr {
/** <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
*/
public static final int backgroundColor=0x7f010000;
/** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
*/
public static final int keywords=0x7f010003;
/** <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
*/
public static final int primaryTextColor=0x7f010001;
/** <p>Must be an integer value, such as "<code>100</code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
*/
public static final int refreshInterval=0x7f010004;
/** <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
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 preferences=0x7f090005;
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=0x7f060001;
public static final int package_name=0x7f060002;
}
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.
<p>Includes the following attributes:</p>
<table>
<colgroup align="left" />
<colgroup align="left" />
<tr><th>Attribute</th><th>Description</th></tr>
<tr><td><code>{@link #com_admob_android_ads_AdView_backgroundColor org.onaips.vnc_donate:backgroundColor}</code></td><td></td></tr>
<tr><td><code>{@link #com_admob_android_ads_AdView_keywords org.onaips.vnc_donate:keywords}</code></td><td></td></tr>
<tr><td><code>{@link #com_admob_android_ads_AdView_primaryTextColor org.onaips.vnc_donate:primaryTextColor}</code></td><td></td></tr>
<tr><td><code>{@link #com_admob_android_ads_AdView_refreshInterval org.onaips.vnc_donate:refreshInterval}</code></td><td></td></tr>
<tr><td><code>{@link #com_admob_android_ads_AdView_secondaryTextColor org.onaips.vnc_donate:secondaryTextColor}</code></td><td></td></tr>
</table>
@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
};
/**
<p>This symbol is the offset where the {@link org.onaips.vnc_donate.R.attr#backgroundColor}
attribute's value can be found in the {@link #com_admob_android_ads_AdView} array.
<p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
@attr name android:backgroundColor
*/
public static final int com_admob_android_ads_AdView_backgroundColor = 0;
/**
<p>This symbol is the offset where the {@link org.onaips.vnc_donate.R.attr#keywords}
attribute's value can be found in the {@link #com_admob_android_ads_AdView} array.
<p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
@attr name android:keywords
*/
public static final int com_admob_android_ads_AdView_keywords = 3;
/**
<p>This symbol is the offset where the {@link org.onaips.vnc_donate.R.attr#primaryTextColor}
attribute's value can be found in the {@link #com_admob_android_ads_AdView} array.
<p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
@attr name android:primaryTextColor
*/
public static final int com_admob_android_ads_AdView_primaryTextColor = 1;
/**
<p>This symbol is the offset where the {@link org.onaips.vnc_donate.R.attr#refreshInterval}
attribute's value can be found in the {@link #com_admob_android_ads_AdView} array.
<p>Must be an integer value, such as "<code>100</code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
@attr name android:refreshInterval
*/
public static final int com_admob_android_ads_AdView_refreshInterval = 4;
/**
<p>This symbol is the offset where the {@link org.onaips.vnc_donate.R.attr#secondaryTextColor}
attribute's value can be found in the {@link #com_admob_android_ads_AdView} array.
<p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
<p>This may also be a reference to a resource (in the form
"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
theme attribute (in the form
"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
containing a value of this type.
@attr name android:secondaryTextColor
*/
public static final int com_admob_android_ads_AdView_secondaryTextColor = 2;
};
}

View File

@ -1,8 +1,8 @@
LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
#LOCAL_CFLAGS += -DDONATE_VERSION LOCAL_CFLAGS += -DDONATE_VERSION
LOCAL_CFLAGS := -O3 -Wall LOCAL_CFLAGS += -Wall
LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES:= \

View File

@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
#LOCAL_CFLAGS += -DDONATE_VERSION #LOCAL_CFLAGS += -DDONATE_VERSION
LOCAL_CFLAGS := -O3 LOCAL_CFLAGS += -Wall
LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES:= \

View File

@ -1,19 +1,33 @@
#define OUT_T CONCAT3E(uint,OUT,_t) #define OUT_T CONCAT3E(uint,OUT,_t)
#define FUNCTION CONCAT2E(FUNCNAME,OUT) #define FUNCTION CONCAT2E(FUNCNAME,OUT)
static void rfbRotate(rfbScreenInfoPtr vncbuf,rfbScreenInfoPtr fbmmap) static void FUNCTION(rfbScreenInfoPtr screen)
{ {
uint_32_t * buffer = (uint_32_t*)screen->frameBuffer; OUT_T* buffer = (OUT_T*)screen->frameBuffer;
int i, j, w = screen->width, h = screen->height; int i, j, w = screen->width, h = screen->height;
uint_32_t * newBuffer = (uint_32_t*)malloc(w * h * sizeof(uint_32_t)); OUT_T* newBuffer = (OUT_T*)malloc(w * h * sizeof(OUT_T));
for (j = 0; j < h; j++) for (j = 0; j < h; j++)
for (i = 0; i < w; i++) for (i = 0; i < w; i++)
newBuffer[(h - 1 - j + i * h)] = buffer[i + j * w]; newBuffer[FUNC(i, j)] = buffer[i + j * w];
memcpy(buffer, newBuffer, w * h * sizeof(uint_32_t)); memcpy(buffer, newBuffer, w * h * sizeof(OUT_T));
free(newBuffer); free(newBuffer);
#ifdef SWAPDIMENSIONS
screen->width = h;
screen->paddedWidthInBytes = h * OUT / 8;
screen->height = w;
{
rfbClientIteratorPtr iterator;
rfbClientPtr cl;
iterator = rfbGetClientIterator(screen);
while ((cl = rfbClientIteratorNext(iterator)) != NULL)
cl->newFBSizePending = 1;
}
#endif
rfbMarkRectAsModified(screen, 0, 0, screen->width, screen->height); rfbMarkRectAsModified(screen, 0, 0, screen->width, screen->height);
} }

View File

@ -1,7 +1,7 @@
#define OUT_T CONCAT3E(uint,OUT,_t) #define OUT_T CONCAT3E(uint,OUT,_t)
#define FUNCTION CONCAT2E(FUNCNAME,OUT) #define FUNCTION CONCAT2E(FUNCNAME,OUT)
static void rfbRotate(rfbScreenInfoPtr vncbuf,rfbScreenInfoPtr screen) static void rfbRotate(rfbScreenInfoPtr vncbuf,rfbScreenInfoPtr fbmmap)
{ {
uint_32_t * buffer = (uint_32_t*)screen->frameBuffer; uint_32_t * buffer = (uint_32_t*)screen->frameBuffer;
int i, j, w = screen->width, h = screen->height; int i, j, w = screen->width, h = screen->height;

761
jni/vnc/fbvncserver.1c Normal file
View File

@ -0,0 +1,761 @@
/*
* $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 <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h> /* For makedev() */
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/input.h>
#include <assert.h>
#include <errno.h>
//android log
#include <android/log.h>
/* 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);
}
}
int aki(int i,int j)
{
return (j+scrinfo.yoffset)*scrinfo.xres_virtual+i+scrinfo.xoffset;
}
#define PIXEL_TO_VIRTUALPIXEL(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i+scrinfo.xoffset)
#define ROTATE90
#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", "line_lenght=%d xres=%d, yres=%d, xresv=%d, yresv=%d, xoffs=%d, yoffs=%d, bpp=%d\n",
(int)fscrinfo.line_length,(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);
}
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<<scrinfo.red.length)-1);
vncscr->serverFormat.greenMax=((1<<scrinfo.green.length)-1);
vncscr->serverFormat.blueMax=((1<<scrinfo.blue.length)-1);
vncscr->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<<scrinfo.red.length)-1);
vncscr->serverFormat.greenMax=((1<<scrinfo.green.length)-1);
vncscr->serverFormat.blueMax=((1<<scrinfo.blue.length)-1);
rfbMarkRectAsModified(vncscr, 0, 0, vncscr->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();
}

View File

@ -52,11 +52,12 @@
#define BUS_VIRTUAL 0x06 #define BUS_VIRTUAL 0x06
/*****************************************************************************/ /*****************************************************************************/
/* Android does not use /dev/fb0. */ /* Android does not use /dev/fb0. */
#define FB_DEVICE "/dev/graphics/fb0"
static char VNC_PASSWORD[256] = ""; char VNC_PASSWORD[256] = "";
char framebuffer_device[256] = "/dev/graphics/fb0";
int VNC_PORT=5901;
static struct fb_var_screeninfo scrinfo; static struct fb_var_screeninfo scrinfo;
static struct fb_fix_screeninfo fscrinfo; static struct fb_fix_screeninfo fscrinfo;
@ -68,9 +69,10 @@ static unsigned int *vncbuf;
static unsigned int *cmpbuf; static unsigned int *cmpbuf;
/* Android already has 5900 bound natively. */ /* Android already has 5900 bound natively. */
#define VNC_PORT 5901
static rfbScreenInfoPtr vncscr; static rfbScreenInfoPtr vncscr;
int idle=0,standby=0,change=0; int idle=0,standby=0,change=0;
static int rotation=0,scaling=0; static int rotation=0,scaling=0;
/*****************************************************************************/ /*****************************************************************************/
@ -93,6 +95,9 @@ void update_fb_info()
} }
#define PIXEL_TO_VIRTUALPIXEL(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i)
// #define PIXEL_TO_VIRTUALPIXEL(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i+scrinfo.xoffset)
#define OUT 32 #define OUT 32
#include "update_screen.c" #include "update_screen.c"
#define OUT 8 #define OUT 8
@ -100,14 +105,19 @@ void update_fb_info()
#define OUT 16 #define OUT 16
#include "update_screen.c" #include "update_screen.c"
inline size_t roundUpToPageSize(size_t x) {
return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
}
static void init_fb(void) static void init_fb(void)
{ {
size_t pixels; size_t pixels;
size_t bytespp; size_t bytespp;
if ((fbfd = open(FB_DEVICE, O_RDWR)) == -1) if ((fbfd = open(framebuffer_device, O_RDWR)) == -1)
{ {
__android_log_print(ANDROID_LOG_INFO,"VNC","cannot open fb device %s\n", FB_DEVICE); __android_log_print(ANDROID_LOG_INFO,"VNC","cannot open fb device %s\n", framebuffer_device);
return; return;
// exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} }
@ -123,33 +133,17 @@ static void init_fb(void)
pixels = scrinfo.xres * scrinfo.yres; pixels = scrinfo.xres * scrinfo.yres;
bytespp = scrinfo.bits_per_pixel /CHAR_BIT; 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", __android_log_print(ANDROID_LOG_INFO,"VNC", "line_lenght=%d xres=%d, yres=%d, xresv=%d, yresv=%d, xoffs=%d, yoffs=%d, bpp=%d\n",
(int)scrinfo.xres, (int)scrinfo.yres, (int)fscrinfo.line_length,(int)scrinfo.xres, (int)scrinfo.yres,
(int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual, (int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual,
(int)scrinfo.xoffset, (int)scrinfo.yoffset, (int)scrinfo.xoffset, (int)scrinfo.yoffset,
(int)scrinfo.bits_per_pixel); (int)scrinfo.bits_per_pixel);
// off_t o=0; printf("AKII\n");
//now handled with double buffer detection size_t fbSize = roundUpToPageSize(fscrinfo.line_length * scrinfo.yres_virtual);
// 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); fbmmap = mmap(NULL, fbSize , PROT_READ|PROT_WRITE , MAP_SHARED , fbfd, 0);
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) if (fbmmap == MAP_FAILED)
@ -233,6 +227,7 @@ static void init_fb_server(int argc, char **argv)
vncscr->ptrAddEvent = ptrevent; vncscr->ptrAddEvent = ptrevent;
vncscr->newClientHook = clientHook; vncscr->newClientHook = clientHook;
if (strcmp(VNC_PASSWORD,"")!=0) if (strcmp(VNC_PASSWORD,"")!=0)
{ {
char **passwords = (char **)malloc(2 * sizeof(char **)); char **passwords = (char **)malloc(2 * sizeof(char **));
@ -287,8 +282,6 @@ static void init_fb_server(int argc, char **argv)
/* Mark as dirty since we haven't sent any updates at all yet. */ /* Mark as dirty since we haven't sent any updates at all yet. */
rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.xres, scrinfo.yres); 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 int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt);
@ -670,11 +663,12 @@ static void rotate()
void print_usage(char **argv) void print_usage(char **argv)
{ {
__android_log_print(ANDROID_LOG_INFO,"VNC","androidvncserver [-p password] [-h]\n" printf("androidvncserver [-p password] [-h]\n"
"-p password: Password to access server\n" "-p password: Password to access server\n"
"-r rotation: Screen rotation (degrees) (0,90,180,270)\n" "-r rotation: Screen rotation (degrees) (0,90,180,270)\n"
"-s screen scale: percentage (20,30,50,100,150)\n" "-s screen scale: percentage (20,30,50,100,150)\n"
"-h : print this help\n"); "-h : print this help\n"
"-f <device> select framebuffer device\n;");
} }
@ -702,6 +696,14 @@ int main(int argc, char **argv)
i++; i++;
strcpy(VNC_PASSWORD,argv[i]); strcpy(VNC_PASSWORD,argv[i]);
break; break;
case 'f':
i++;
strcpy(framebuffer_device,argv[i]);
break;
case 'P':
i++;
VNC_PORT=atoi(argv[i]);
break;
case 'r': case 'r':
i++; i++;
r=atoi(argv[i]); r=atoi(argv[i]);
@ -724,7 +726,7 @@ int main(int argc, char **argv)
} }
} }
__android_log_print(ANDROID_LOG_INFO,"VNC","Initializing framebuffer device " FB_DEVICE "...\n"); __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing framebuffer device...\n");
init_fb(); init_fb();
__android_log_print(ANDROID_LOG_INFO,"VNC","Initializing virtual keyboard and touch device...\n"); __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing virtual keyboard and touch device...\n");
@ -736,16 +738,43 @@ int main(int argc, char **argv)
__android_log_print(ANDROID_LOG_INFO,"VNC"," bpp: %d\n", (int)scrinfo.bits_per_pixel); __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); __android_log_print(ANDROID_LOG_INFO,"VNC"," port: %d\n", (int)VNC_PORT);
init_fb_server(argc, argv); init_fb_server(argc, argv);
/*
rfbRunEventLoop(vncscr,-1,TRUE);
while (1) while (1)
{ {
while (vncscr->clientHead == NULL)
sleep(1);
while (vncscr->clientHead == NULL) if (standby>60)
sleep(2);
else if (standby>30)
sleep(1);
else
usleep(100000);
update_screen();
}*/
while (1)
{
while (vncscr->clientHead == NULL)
rfbProcessEvents(vncscr, 100000); rfbProcessEvents(vncscr, 100000);
update_screen(); rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height);
if (standby>60)
rfbProcessEvents(vncscr, 200000);
else if (standby>30)
rfbProcessEvents(vncscr, 100000);
else
rfbProcessEvents(vncscr, 10000);
update_screen();
} }
__android_log_print(ANDROID_LOG_INFO,"VNC","Cleaning up...\n"); __android_log_print(ANDROID_LOG_INFO,"VNC","Cleaning up...\n");
cleanup_fb(); cleanup_fb();
cleanup_kbd(); cleanup_kbd();

View File

@ -52,11 +52,12 @@
#define BUS_VIRTUAL 0x06 #define BUS_VIRTUAL 0x06
/*****************************************************************************/ /*****************************************************************************/
/* Android does not use /dev/fb0. */ /* Android does not use /dev/fb0. */
#define FB_DEVICE "/dev/graphics/fb0"
static char VNC_PASSWORD[256] = ""; char VNC_PASSWORD[256] = "";
char framebuffer_device[256] = "/dev/graphics/fb0";
char VNC_PORT[10]="5901";
static struct fb_var_screeninfo scrinfo; static struct fb_var_screeninfo scrinfo;
static struct fb_fix_screeninfo fscrinfo; static struct fb_fix_screeninfo fscrinfo;
@ -68,9 +69,10 @@ static unsigned int *vncbuf;
static unsigned int *cmpbuf; static unsigned int *cmpbuf;
/* Android already has 5900 bound natively. */ /* Android already has 5900 bound natively. */
#define VNC_PORT 5901
static rfbScreenInfoPtr vncscr; static rfbScreenInfoPtr vncscr;
int idle=0,standby=0,change=0; int idle=0,standby=0,change=0;
static int rotation=0,scaling=0; static int rotation=0,scaling=0;
/*****************************************************************************/ /*****************************************************************************/
@ -93,6 +95,9 @@ void update_fb_info()
} }
#define PIXEL_TO_VIRTUALPIXEL(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i)
// #define PIXEL_TO_VIRTUALPIXEL(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i+scrinfo.xoffset)
#define OUT 32 #define OUT 32
#include "update_screen.c" #include "update_screen.c"
#define OUT 8 #define OUT 8
@ -100,14 +105,19 @@ void update_fb_info()
#define OUT 16 #define OUT 16
#include "update_screen.c" #include "update_screen.c"
inline size_t roundUpToPageSize(size_t x) {
return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
}
static void init_fb(void) static void init_fb(void)
{ {
size_t pixels; size_t pixels;
size_t bytespp; size_t bytespp;
if ((fbfd = open(FB_DEVICE, O_RDWR)) == -1) if ((fbfd = open(framebuffer_device, O_RDWR)) == -1)
{ {
__android_log_print(ANDROID_LOG_INFO,"VNC","cannot open fb device %s\n", FB_DEVICE); __android_log_print(ANDROID_LOG_INFO,"VNC","cannot open fb device %s\n", framebuffer_device);
return; return;
// exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} }
@ -123,33 +133,17 @@ static void init_fb(void)
pixels = scrinfo.xres * scrinfo.yres; pixels = scrinfo.xres * scrinfo.yres;
bytespp = scrinfo.bits_per_pixel /CHAR_BIT; 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", __android_log_print(ANDROID_LOG_INFO,"VNC", "line_lenght=%d xres=%d, yres=%d, xresv=%d, yresv=%d, xoffs=%d, yoffs=%d, bpp=%d\n",
(int)scrinfo.xres, (int)scrinfo.yres, (int)fscrinfo.line_length,(int)scrinfo.xres, (int)scrinfo.yres,
(int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual, (int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual,
(int)scrinfo.xoffset, (int)scrinfo.yoffset, (int)scrinfo.xoffset, (int)scrinfo.yoffset,
(int)scrinfo.bits_per_pixel); (int)scrinfo.bits_per_pixel);
// off_t o=0; printf("AKII\n");
//now handled with double buffer detection size_t fbSize = roundUpToPageSize(fscrinfo.line_length * scrinfo.yres_virtual);
// 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); fbmmap = mmap(NULL, fbSize , PROT_READ|PROT_WRITE , MAP_SHARED , fbfd, 0);
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) if (fbmmap == MAP_FAILED)
@ -198,7 +192,7 @@ static rfbNewClientHookPtr clientHook(rfbClientPtr cl)
if (scaling!=0 && scaling!=100) if (scaling!=0 && scaling!=100)
{ {
rfbScalingSetup(cl, vncscr->width*scaling/100.0, vncscr->height*scaling/100.0); rfbScalingSetup(cl, vncscr->width*scaling/100.0, vncscr->height*scaling/100.0);
rfbSendNewScaleSize(cl);
} }
return RFB_CLIENT_ACCEPT; return RFB_CLIENT_ACCEPT;
@ -233,6 +227,7 @@ static void init_fb_server(int argc, char **argv)
vncscr->ptrAddEvent = ptrevent; vncscr->ptrAddEvent = ptrevent;
vncscr->newClientHook = clientHook; vncscr->newClientHook = clientHook;
if (strcmp(VNC_PASSWORD,"")!=0) if (strcmp(VNC_PASSWORD,"")!=0)
{ {
char **passwords = (char **)malloc(2 * sizeof(char **)); char **passwords = (char **)malloc(2 * sizeof(char **));
@ -287,8 +282,6 @@ static void init_fb_server(int argc, char **argv)
/* Mark as dirty since we haven't sent any updates at all yet. */ /* Mark as dirty since we haven't sent any updates at all yet. */
rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.xres, scrinfo.yres); 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 int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt);
@ -670,11 +663,12 @@ static void rotate()
void print_usage(char **argv) void print_usage(char **argv)
{ {
__android_log_print(ANDROID_LOG_INFO,"VNC","androidvncserver [-p password] [-h]\n" printf("androidvncserver [-p password] [-h]\n"
"-p password: Password to access server\n" "-p password: Password to access server\n"
"-r rotation: Screen rotation (degrees) (0,90,180,270)\n" "-r rotation: Screen rotation (degrees) (0,90,180,270)\n"
"-s screen scale: percentage (20,30,50,100,150)\n" "-s screen scale: percentage (20,30,50,100,150)\n"
"-h : print this help\n"); "-h : print this help\n"
"-f <device> select framebuffer device\n;");
} }
@ -702,6 +696,14 @@ int main(int argc, char **argv)
i++; i++;
strcpy(VNC_PASSWORD,argv[i]); strcpy(VNC_PASSWORD,argv[i]);
break; break;
case 'f':
i++;
strcpy(framebuffer_device,argv[i]);
break;
case 'P':
i++;
VNC_PORT=atoi(argv[i]);
break;
case 'r': case 'r':
i++; i++;
r=atoi(argv[i]); r=atoi(argv[i]);
@ -724,7 +726,7 @@ int main(int argc, char **argv)
} }
} }
__android_log_print(ANDROID_LOG_INFO,"VNC","Initializing framebuffer device " FB_DEVICE "...\n"); __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing framebuffer device...\n");
init_fb(); init_fb();
__android_log_print(ANDROID_LOG_INFO,"VNC","Initializing virtual keyboard and touch device...\n"); __android_log_print(ANDROID_LOG_INFO,"VNC","Initializing virtual keyboard and touch device...\n");
@ -736,16 +738,43 @@ int main(int argc, char **argv)
__android_log_print(ANDROID_LOG_INFO,"VNC"," bpp: %d\n", (int)scrinfo.bits_per_pixel); __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); __android_log_print(ANDROID_LOG_INFO,"VNC"," port: %d\n", (int)VNC_PORT);
init_fb_server(argc, argv); init_fb_server(argc, argv);
/*
rfbRunEventLoop(vncscr,-1,TRUE);
while (1) while (1)
{ {
while (vncscr->clientHead == NULL)
sleep(1);
while (vncscr->clientHead == NULL) if (standby>60)
sleep(2);
else if (standby>30)
sleep(1);
else
usleep(100000);
update_screen();
}*/
while (1)
{
while (vncscr->clientHead == NULL)
rfbProcessEvents(vncscr, 100000); rfbProcessEvents(vncscr, 100000);
update_screen(); rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height);
if (standby>60)
rfbProcessEvents(vncscr, 200000);
else if (standby>30)
rfbProcessEvents(vncscr, 100000);
else
rfbProcessEvents(vncscr, 10000);
update_screen();
} }
__android_log_print(ANDROID_LOG_INFO,"VNC","Cleaning up...\n"); __android_log_print(ANDROID_LOG_INFO,"VNC","Cleaning up...\n");
cleanup_fb(); cleanup_fb();
cleanup_kbd(); cleanup_kbd();

View File

@ -1,9 +1,12 @@
#define OUT_T CONCAT3E(uint,OUT,_t) #define OUT_T CONCAT3E(uint,OUT,_t)
#define FUNCTION CONCAT2E(update_screen_,OUT) #define FUNCTION CONCAT2E(update_screen_,OUT)
void FUNCTION(void) void FUNCTION(void)
{ {
static int i,j,offset; static int i,j;
update_fb_info(); update_fb_info();
@ -14,8 +17,8 @@ void FUNCTION(void)
// offset=scrinfo.xres*scrinfo.yoffset; // offset=scrinfo.xres*scrinfo.yoffset;
// else // else
// offset=0; // offset=0;
// offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT;
offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT;
OUT_T* a = (OUT_T*)cmpbuf; OUT_T* a = (OUT_T*)cmpbuf;
OUT_T* b = (OUT_T*)fbmmap; OUT_T* b = (OUT_T*)fbmmap;
@ -30,9 +33,9 @@ void FUNCTION(void)
{ {
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if (a[i + j * scrinfo.xres]!=b[i + j * scrinfo.xres + offset ]) if (a[i + j * scrinfo.xres]!=b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[i + j * scrinfo.xres]=b[i + j * scrinfo.xres + offset]; a[i + j * scrinfo.xres]=b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_x) if (i>max_x)
max_x=i; max_x=i;
@ -56,9 +59,9 @@ void FUNCTION(void)
{ {
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if (a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[i + j * scrinfo.xres + offset]) if (a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[i + j * scrinfo.xres + offset ]; a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_y) if (i>max_y)
max_y=i; max_y=i;
@ -84,19 +87,22 @@ void FUNCTION(void)
{ {
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if (a[i + j * scrinfo.xres]!=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres ) + offset ]) if (a[((scrinfo.xres - 1 - i) + (scrinfo.yres - 1 - j) * scrinfo.xres)]!=b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[i + j * scrinfo.xres]=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres) + offset ]; a[((scrinfo.xres - 1 - i) + (scrinfo.yres - 1 - j) * scrinfo.xres)]=b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_x) if (i>max_x)
max_x=i; max_x=i;
if (i<min_x) if (i<min_x)
min_x=i; min_x=i;
if (j>max_y) int h=scrinfo.yres-j;
max_y=j;
if (j<min_y) if (h < min_y)
min_y=j; min_y=scrinfo.yres-j;
if (h > max_y)
max_y=scrinfo.yres-j;
if (idle) if (idle)
idle=0; idle=0;
@ -111,20 +117,19 @@ void FUNCTION(void)
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if(a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ]) if(a[j + (scrinfo.xres - 1 - i) * scrinfo.yres] != b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ]; a[j + (scrinfo.xres - 1 - i) * scrinfo.yres] = b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_y) if (i>max_y)
max_y=i; max_y=i;
if (i<min_y) if (i<min_y)
min_y=i; min_y=i;
int h=scrinfo.yres-j; if (j < min_x)
min_x=j;
if (h < min_x) if (j > max_x)
min_x=scrinfo.yres-j; max_x=j;
if (h > max_x)
max_x=scrinfo.yres-j;
if (idle) if (idle)
idle=0; idle=0;
@ -136,40 +141,25 @@ void FUNCTION(void)
memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); 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) if (min_x!=9999 && min_y!=9999 && max_x!=-1 && max_y!=-1)
{ {
// min_x--;
max_x++; max_x++;
// min_y--;
max_y++; max_y++;
rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, 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) if (idle)
{ {
standby=standby+1; standby=standby+1;
//__android_log_print(ANDROID_LOG_INFO,"VNC","standby %d xoff=%d yoff=%d offset=%d\n",standby,scrinfo.xoffset,scrinfo.yoffset,PIXEL_TO_VIRTUALPIXEL(i,j));
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; change=0;
} }
else else
{ {
change=change+1; change=change+1;
standby=0; 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 offset=%d\n",change,min_x,max_x,min_y,max_y,scrinfo.xoffset,scrinfo.yoffset,PIXEL_TO_VIRTUALPIXEL(i,j));
// __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);
} }
} }

View File

@ -1,9 +1,12 @@
#define OUT_T CONCAT3E(uint,OUT,_t) #define OUT_T CONCAT3E(uint,OUT,_t)
#define FUNCTION CONCAT2E(update_screen_,OUT) #define FUNCTION CONCAT2E(update_screen_,OUT)
void FUNCTION(void) void FUNCTION(void)
{ {
static int i,j,offset; static int i,j;
update_fb_info(); update_fb_info();
@ -14,8 +17,8 @@ void FUNCTION(void)
// offset=scrinfo.xres*scrinfo.yoffset; // offset=scrinfo.xres*scrinfo.yoffset;
// else // else
// offset=0; // offset=0;
// offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT;
offset = scrinfo.xres * scrinfo.yoffset + scrinfo.xoffset * scrinfo.bits_per_pixel / CHAR_BIT;
OUT_T* a = (OUT_T*)cmpbuf; OUT_T* a = (OUT_T*)cmpbuf;
OUT_T* b = (OUT_T*)fbmmap; OUT_T* b = (OUT_T*)fbmmap;
@ -30,9 +33,9 @@ void FUNCTION(void)
{ {
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if (a[i + j * scrinfo.xres]!=b[i + j * scrinfo.xres + offset ]) if (a[i + j * scrinfo.xres]!=b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[i + j * scrinfo.xres]=b[i + j * scrinfo.xres + offset]; a[i + j * scrinfo.xres]=b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_x) if (i>max_x)
max_x=i; max_x=i;
@ -56,9 +59,9 @@ void FUNCTION(void)
{ {
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if (a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[i + j * scrinfo.xres + offset]) if (a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[i + j * scrinfo.xres + offset ]; a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_y) if (i>max_y)
max_y=i; max_y=i;
@ -84,19 +87,22 @@ void FUNCTION(void)
{ {
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if (a[i + j * scrinfo.xres]!=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres ) + offset ]) if (a[((scrinfo.xres - 1 - i) + (scrinfo.yres - 1 - j) * scrinfo.xres)]!=b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[i + j * scrinfo.xres]=b[scrinfo.yres*scrinfo.xres - (i + j * scrinfo.xres) + offset ]; a[((scrinfo.xres - 1 - i) + (scrinfo.yres - 1 - j) * scrinfo.xres)]=b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_x) if (i>max_x)
max_x=i; max_x=i;
if (i<min_x) if (i<min_x)
min_x=i; min_x=i;
if (j>max_y) int h=scrinfo.yres-j;
max_y=j;
if (j<min_y) if (h < min_y)
min_y=j; min_y=scrinfo.yres-j;
if (h > max_y)
max_y=scrinfo.yres-j;
if (idle) if (idle)
idle=0; idle=0;
@ -111,20 +117,19 @@ void FUNCTION(void)
for (i = 0; i < scrinfo.xres; i++) for (i = 0; i < scrinfo.xres; i++)
{ {
if(a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ]) if(a[j + (scrinfo.xres - 1 - i) * scrinfo.yres] != b[PIXEL_TO_VIRTUALPIXEL(i,j)])
{ {
a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ]; a[j + (scrinfo.xres - 1 - i) * scrinfo.yres] = b[PIXEL_TO_VIRTUALPIXEL(i,j)];
if (i>max_y) if (i>max_y)
max_y=i; max_y=i;
if (i<min_y) if (i<min_y)
min_y=i; min_y=i;
int h=scrinfo.yres-j; if (j < min_x)
min_x=j;
if (h < min_x) if (j > max_x)
min_x=scrinfo.yres-j; max_x=j;
if (h > max_x)
max_x=scrinfo.yres-j;
if (idle) if (idle)
idle=0; idle=0;
@ -136,40 +141,25 @@ void FUNCTION(void)
memcpy(vncbuf,a,vncscr->width*vncscr->height*scrinfo.bits_per_pixel/CHAR_BIT); 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) if (min_x!=9999 && min_y!=9999 && max_x!=-1 && max_y!=-1)
{ {
// min_x--;
max_x++; max_x++;
// min_y--;
max_y++; max_y++;
rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, max_y); rfbMarkRectAsModified(vncscr, min_x, min_y, max_x, max_y);
rfbProcessEvents(vncscr, 10000); rfbProcessEvents(vncscr, 100000);
} }
// rfbMarkRectAsModified(vncscr, 0, 0, scrinfo.yres,scrinfo.xres);
// rfbProcessEvents(vncscr, 10000);
if (idle) if (idle)
{ {
standby=standby+1; standby=standby+1;
//__android_log_print(ANDROID_LOG_INFO,"VNC","standby %d xoff=%d yoff=%d offset=%d\n",standby,scrinfo.xoffset,scrinfo.yoffset,PIXEL_TO_VIRTUALPIXEL(i,j));
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; change=0;
} }
else else
{ {
change=change+1; change=change+1;
standby=0; 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 offset=%d\n",change,min_x,max_x,min_y,max_y,scrinfo.xoffset,scrinfo.yoffset,PIXEL_TO_VIRTUALPIXEL(i,j));
__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);
} }
} }

175
jni/vnc/update_screen1.c Normal file
View File

@ -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 (i<min_x)
min_x=i;
if (j>max_y)
max_y=j;
if (j<min_y)
min_y=j;
if (idle)
idle=0;
}
}
}
}
else if (rotation==90)
{
for (j = 0; j < scrinfo.yres; j++)
{
for (i = 0; i < scrinfo.xres; i++)
{
if (a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[i + j * scrinfo.xres + offset])
{
a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[i + j * scrinfo.xres + offset ];
if (i>max_y)
max_y=i;
if (i<min_y)
min_y=i;
int h=scrinfo.yres-j;
if (h < min_x)
min_x=scrinfo.yres-j;
if (h > 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 (i<min_x)
min_x=i;
if (j>max_y)
max_y=j;
if (j<min_y)
min_y=j;
if (idle)
idle=0;
}
}
}
}
else if (rotation==270)
{
for (j = 0; j < scrinfo.yres; j++)
{
for (i = 0; i < scrinfo.xres; i++)
{
if(a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] != b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ])
{
a[(scrinfo.yres - 1 - j + i * scrinfo.yres)] = b[ scrinfo.yres * scrinfo.xres - (i + j * scrinfo.xres) + offset ];
if (i>max_y)
max_y=i;
if (i<min_y)
min_y=i;
int h=scrinfo.yres-j;
if (h < min_x)
min_x=scrinfo.yres-j;
if (h > 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);
}
}

Binary file not shown.

Binary file not shown.

View File

@ -8,8 +8,9 @@
<LinearLayout <LinearLayout
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical" android:layout_height="fill_parent"
android:gravity="center_horizontal" android:orientation="vertical"
android:gravity="center_horizontal"
> >
<ImageView <ImageView
@ -46,14 +47,16 @@
android:shadowRadius="0.5" android:shadowRadius="0.5"
android:shadowColor="#111"> android:shadowColor="#111">
</TextView> </TextView>
<TextView android:textSize="18sp" android:text="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/TextView01" android:paddingTop="10dp" <TextView android:textSize="15sp" android:text="@+id/TextView02" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="10dp"
android:shadowDy="1.0" android:shadowDy="1.0"
android:shadowRadius="0.5" android:shadowRadius="0.5"
android:shadowColor="#111"> android:shadowColor="#111"
android:gravity="center"
>
</TextView> </TextView>
</LinearLayout> </LinearLayout>
<!--
<TextView <TextView
android:textSize="15sp" android:textSize="15sp"
android:text="Click on ad to support project" android:text="Click on ad to support project"
@ -71,5 +74,5 @@ android:layout_height="50dip"
android:layout_width="320dip" android:layout_width="320dip"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
/> /> -->
</RelativeLayout> </RelativeLayout>

Binary file not shown.

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">droid VNC server</string> <string name="app_name">droid VNC server</string>
<string name="password"></string>
<string-array name="rotation_values"><item>0</item> <string-array name="rotation_values"><item>0</item>
<item>90</item> <item>90</item>
<item>180</item> <item>180</item>
@ -21,7 +20,14 @@
<item>30 %</item> <item>30 %</item>
<item>20 %</item> <item>20 %</item>
</string-array> </string-array>
<string-array name="sleep_strings">
<item>On</item>
<item>Off</item>
</string-array>
<string-array name="startonboot_values">
<item>True</item>
<item>False</item>
</string-array>
<string name="device_info_fmt"> <string name="device_info_fmt">
droid VNC version: <xliff:g id="application_version">%s</xliff:g>\n droid VNC version: <xliff:g id="application_version">%s</xliff:g>\n
Device model: <xliff:g id="device_model">%s</xliff:g>\n Device model: <xliff:g id="device_model">%s</xliff:g>\n
@ -29,4 +35,5 @@ Firmware version: <xliff:g id="firmware_revision">%s</xliff:g>\n
Kernel version: <xliff:g id="kernel_version">%s</xliff:g>\n Kernel version: <xliff:g id="kernel_version">%s</xliff:g>\n
Build number: <xliff:g id="build_number">%s</xliff:g>\n Build number: <xliff:g id="build_number">%s</xliff:g>\n
</string> </string>
<string name="package_name">org.onaips.vnc</string>
</resources> </resources>

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference android:key="password" android:title="VNC password"></EditTextPreference> <EditTextPreference android:key="password" android:title="VNC password" android:password="true" android:summary="Protect your VNC connection"></EditTextPreference>
<ListPreference android:key="rotation" android:title="Rotation" android:entries="@array/rotation_values" android:entryValues="@array/rotation_values"></ListPreference> <ListPreference android:key="rotation" android:title="Rotation" android:entries="@array/rotation_values" android:entryValues="@array/rotation_values" android:summary="Rotate screen if you like"></ListPreference>
<ListPreference android:key="scale" android:title="Scale Screen" android:entries="@array/scale_strings" android:entryValues="@array/scale_values"></ListPreference> <ListPreference android:key="scale" android:title="Scale Screen" android:entries="@array/scale_strings" android:entryValues="@array/scale_values" android:summary="Only 50% working for now"></ListPreference>
<ListPreference android:key="sleep" android:title="Don't let screen turn off" android:entries="@array/sleep_strings" android:entryValues="@array/sleep_strings"></ListPreference>
<EditTextPreference android:key="port" android:title="VNC port" android:summary="Note: It will not show error if cannot bind port"></EditTextPreference>
<ListPreference android:key="startonboot" android:title="Start server on boot" android:entryValues="@array/startonboot_values" android:entries="@array/startonboot_values" android:summary="Warning! Just activate if you have your daemon running fine."></ListPreference>
</PreferenceScreen> </PreferenceScreen>

View File

@ -0,0 +1,821 @@
/*
* 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_donate;
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.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
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.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
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.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
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 int MENU_CHANGELOG = 4;
private static final String changelog="-PLEASE GIVE FEEDBACK! (send debug info in menu)<br><br>- [Add] Start daemon on boot (set on prefs)<br>-[Add] Change port on preferences<br>- [Add] Changelog on menu<br>- [Add] Dynamic network state detection<br>- [Fix] HTTP client now working again<br>- [Rem] Initial screen is only showed on new versions<br>- [Add] Don't let device sleep (set on prefs)<br>- [Fix] Better start/stop handling";
private PowerManager.WakeLock wakeLock = null;
private Timer watchdogTimer=null;
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 (watchdogTimer!=null)
watchdogTimer.cancel();
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);
}
if (!hasBusybox())
{
showTextOnScreen("I didn't find busybox, you may not be able to close server");
}
showInitialScreen(false);
createBinary();
boolean serverRunning=isAndroidServerRunning();
if (("On".equals(preferences.getString("sleep", "Off"))) && serverRunning)
{
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,"droid VNC");
wakeLock.acquire();
}
else
{
if (wakeLock!=null)
wakeLock.release();
}
// register wifi event receiver
mReceiver receiver=new mReceiver();
this.registerReceiver(receiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
findViewById(R.id.Button01).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startServerButtonClicked();
return;
}
}) ;
findViewById(R.id.Button02).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (!isAndroidServerRunning())
{
showTextOnScreen("Server is not running");
return;
}
prepareWatchdog("Stopping server. Please wait...","Couldn't Stop server",false);
Thread t=new Thread(){
public void run()
{
stopServer();
}
};
t.start();
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(boolean forceShow)
{
// Initialize preferences
preferences = PreferenceManager.getDefaultSharedPreferences(this );
SharedPreferences.Editor editor = preferences.edit();
String version=packageVersion();
{
if (forceShow)
;
else if (version.equals(preferences.getString("version", "")))
return;
editor.putString("version", version);
editor.commit();
}
startDialog = new AlertDialog.Builder(this).create();
startDialog.setTitle("Changelog");
startDialog.setMessage(Html.fromHtml(changelog));
startDialog.setIcon(R.drawable.icon);
if (free_version())
{
startDialog.setButton(AlertDialog.BUTTON1,"OK", 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.show();
}
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_CHANGELOG,0,"Changelog");
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 prepareWatchdog(final String s1,final String s2, final boolean running)
{
dialog=ProgressDialog.show(MainActivity.this, "",s1, true);
watchdogTimer=new Timer();
watchdogTimer.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable(){
public void run() {
if (isAndroidServerRunning() == (running==false))
{
try {
dialog.dismiss();
}
catch(IllegalArgumentException a)
{
Log.v("VNC","IllegalArgumentException, should be avoided");
}
showTextOnScreen(s2);
}
}
});
}
}, (long)5000);
}
public void setStateLabels(boolean state)
{
TextView stateLabel=(TextView)findViewById(R.id.stateLabel);
stateLabel.setText(state?"Running":"Stopped");
stateLabel.setTextColor(state?Color.GREEN:Color.RED);
TextView t=(TextView)findViewById(R.id.TextView01);
if (state)
{
String port=preferences.getString("port", "5901");
String httpport;
try
{
int port1=Integer.parseInt(port);
port=String.valueOf(port1);
httpport=String.valueOf(port1-100);
}
catch(NumberFormatException e)
{
port="5901";
httpport="5801";
}
String ip=getIpAddress();
if (ip.equals(""))
t.setText("Not connected to a network");
else
t.setText(Html.fromHtml("<font align=\"center\">Connect to:<br>" + getIpAddress()+":" + port + "<br>or<br>http://" + getIpAddress() + ":" + httpport + "</font>"));
}
else
t.setText("");
}
public String getIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
Log.e("VNC", ex.toString());
}
return "";
}
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();
if (hasBusybox())
{
writeCommand(os, "busybox killall androidvncserver");
writeCommand(os, "busybox killall -KILL androidvncserver");
}
else
{
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())
{
showTextOnScreen("Server is already running, stop it first");
}
else
{
prepareWatchdog("Starting server. Please wait...","Couldn't Start server", true);
Thread t=new Thread(){
public void run()
{
startServer();
}
};
t.start();
}
}
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;
String port=preferences.getString("port", "5901");
try
{
int port1=Integer.parseInt(port);
port=String.valueOf(port1);
}
catch(NumberFormatException e)
{
port="5901";
}
String port_string="-P " + port;
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 + " " + port_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:<br><br>Right Click -> Back<br>Middle Click -> End Call<br>Left Click -> Touch<br><br>Keyboard Mappings<br><br>" +
"Home Key -> Home<br>Escape -> Back<br>Page Up ->Menu<br>Left Ctrl -> Search<br>PgDown -> Start Call<br>" +
"End Key -> End Call<br>F4 -> Rotate<br>F11 -> Disconnect Server<br>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_CHANGELOG:
showInitialScreen(true);
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() + "<br><br>developed by oNaiPs<br><br>Graphics: Sandro Forbice (@sandroforbice)<br><br>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 {
if (hasBusybox())
sh = Runtime.getRuntime().exec("busybox ps");
else
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 static boolean hasBusybox()
{
boolean has = true;
try {
File su = new File("/system/bin/busybox");
if (su.exists() == false) {
su = new File("/system/xbin/busybox");
if (su.exists() == false) {
has = false;
}
}
} catch (Exception e) {
Log.v("VNC", "I didn't find busybox, you may not be able to close server - Here is what I know: "+e.getMessage());
has = false;
}
return has;
}
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();
if (hasBusybox())
{
writeCommand(os, "busybox chown -R " + result + " /data/data/" + getPackageName() + "/");
writeCommand(os, "busybox chgrp -R " + result + " /data/data/" + getPackageName() + "/");
}
else
{
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<ResolveInfo> 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;
}
class mReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (info.getType() == ConnectivityManager.TYPE_MOBILE || info.getType()==ConnectivityManager.TYPE_WIFI) {
setStateLabels(isAndroidServerRunning());
}
}
};
}

View File

@ -0,0 +1,91 @@
package org.onaips.vnc_donate;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
public class StartAtBootService extends Service {
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
startServer();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
public void startServer()
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
//Lets see if i need to boot daemon...
String startOnBoot=preferences.getString("startonboot", "False");
if (startOnBoot.equals("False"))
return;
//this code is redundant, how to merge it?
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;
String port=preferences.getString("port", "5901");
try
{
int port1=Integer.parseInt(port);
port=String.valueOf(port1);
}
catch(NumberFormatException e)
{
port="5901";
}
String port_string="-P " + port;
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 + " " + port_string);
} catch (IOException e) {
Log.v("VNC","startServer():" + e.getMessage());
} catch (Exception e) {
Log.v("VNC","startServer():" + e.getMessage());
}
}
static void writeCommand(OutputStream os, String command) throws Exception
{
os.write((command + "\n").getBytes("ASCII"));
}
}

View File

@ -0,0 +1,18 @@
package org.onaips.vnc_donate;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class StartAtBootServiceReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i = new Intent();
i.setAction(context.getPackageName() + ".StartAtBootService");
context.startService(i);
}
}
}

View File

@ -0,0 +1,19 @@
package org.onaips.vnc_donate;
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);
}
}