Monday, December 27, 2010

GATT related dbus API

After trying gatttool, I am trying how to use this new attribute dbus api in bluez. I find there is an "attrib/example.c" and it would create some service records to demo GATT. When we create a device to bluez, it would detect the device type. If it's a LE device, it would run to "attrib_client_register", then register Primary and Characteristics services. We can use d-feet to see these interfaces. Also, bluez will write some data files to "/var/lib/bluetooth/". When we restart bluez, it can create these interfaces without discovering the remote device again.


Primary Service
We can know what kind of services this remote BT device has from 'UUIDs' value. For example, "0x1801" is GENERIC_ATTRIB_SVCLASS_ID and "0x1800" is GENERIC_ACCESS_PROFILE_ID. 'Services' value is the object path of all primary services.

erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52 org.bluez.Device.GetProperties


method return sender=:1.93 -> dest=:1.96 reply_serial=2
array [
dict entry(
string "Address"
variant string "78:DD:08:A3:A7:52"
)
dict entry(
string "Name"
variant string ""
)
dict entry(
string "Alias"
variant string "78-DD-08-A3-A7-52"
)
dict entry(
string "Paired"
variant boolean true
)
dict entry(
string "Trusted"
variant boolean false
)
dict entry(
string "Blocked"
variant boolean false
)
dict entry(
string "Connected"
variant boolean false
)
dict entry(
string "UUIDs"
variant array [
string "00001105-0000-1000-8000-00805f9b34fb"
string "00001106-0000-1000-8000-00805f9b34fb"
string "0000110a-0000-1000-8000-00805f9b34fb"
string "0000110c-0000-1000-8000-00805f9b34fb"
string "0000110e-0000-1000-8000-00805f9b34fb"
string "00001112-0000-1000-8000-00805f9b34fb"
string "0000111f-0000-1000-8000-00805f9b34fb"
string "00001800-0000-1000-8000-00805f9b34fb"
string "00001801-0000-1000-8000-00805f9b34fb"
string "0000a002-0000-1000-8000-00805f9b34fb"
string "0000a004-0000-1000-8000-00805f9b34fb"
string "4f0ac096-35d4-4911-9631-dea8dc74eefe"
]
)
dict entry(
string "Services"
variant array [
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0001"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0010"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0100"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0200"
object path "/org/bluez/5444/hci0/dev_78_DD_08_A3_A7_52/service0680"
]
)
dict entry(
string "Adapter"
variant object path "/org/bluez/5444/hci0"
)
]


Characteristics Service
We can also discover what kind of characteristics service this BT device has. It would like use gatttool to run "--characteristics" and it would register related interfaces like below:

erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200 org.bluez.Characteristic.Discover
method return sender=:1.107 -> dest=:1.112 reply_serial=2


erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200 org.bluez.Characteristic.GetProperties


method return sender=:1.107 -> dest=:1.117 reply_serial=2
array [
dict entry(
string "Characteristics"
variant array [
object path "/org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0204"
object path "/org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0212"
]
)
]

Attribute Value - READ
From example.c, we know "0xA006" is TEMPERATURE_UUID. We can call below dbus method to retrieve its properties. This "Value" property is an array of bytes and it could have format, value and representation to describe the exact value meaning.


erin@sundays:~$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0204 org.bluez.Characteristic.GetProperties


method return sender=:1.107 -> dest=:1.118 reply_serial=2
array [
dict entry(
string "UUID"
variant string "0000a006-0000-1000-8000-00805f9b34fb"
)
dict entry(
string "Name"
variant string ""
)
dict entry(
string "Description"
variant string "Outside Temperature"
)
dict entry(
string "Value"
variant array of bytes [
8a 02
]
)
]


Bluez Data Files
GATT related files in /var/lib/bluetooth

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/primary
78:DD:08:A3:A7:52 0001#0006#00001800-0000-1000-8000-00805f9b34fb 0010#0012#00001801-0000-1000-8000-00805f9b34fb 0100#0111#0000a002-0000-1000-8000-00805f9b34fb 0200#0214#0000a004-0000-1000-8000-00805f9b34fb 0680#0685#4f0ac096-35d4-4911-9631-dea8dc74eefe

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/characteristic
78:DD:08:A3:A7:52#0001 0006#02#0006#00002a00-0000-1000-8000-00805f9b34fb 0006#02#0006#00002a00-0000-1000-8000-00805f9b34fb
78:DD:08:A3:A7:52#0010 0012#02#0012#0000a001-0000-1000-8000-00805f9b34fb
78:DD:08:A3:A7:52#0200 0204#02#0210#0000a006-0000-1000-8000-00805f9b34fb 0212#02#0214#0000a009-0000-1000-8000-00805f9b34fb

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/attributes
78:DD:08:A3:A7:52#0205 00002904-0000-1000-8000-00805f9b34fb#0EFE07A00108A0
78:DD:08:A3:A7:52#0206 00002901-0000-1000-8000-00805f9b34fb#4F7574736964652054656D706572617475726500
78:DD:08:A3:A7:52#0213 00002904-0000-1000-8000-00805f9b34fb#04000AA00BA008
78:DD:08:A3:A7:52#0214 00002901-0000-1000-8000-00805f9b34fb#4F7574736964652052656C61746976652048756D696400

erin@sundays:~$ cat /var/lib/bluetooth/00\:1B\:DC\:02\:86\:C5/profiles
78:DD:08:A3:A7:52 00001105-0000-1000-8000-00805f9b34fb 00001106-0000-1000-8000-00805f9b34fb 0000110a-0000-1000-8000-00805f9b34fb 0000110c-0000-1000-8000-00805f9b34fb 0000110e-0000-1000-8000-00805f9b34fb 00001112-0000-1000-8000-00805f9b34fb 0000111f-0000-1000-8000-00805f9b34fb 00001801-0000-1000-8000-00805f9b34fb


Attribute Value - WRITE
How to change a characteristic value? I really don't know how to send a value like "variant array of bytes [8a 02]". Then, I use ipython to send this dbus method, then I can rewrite its value.


In [1]: import dbus
In [2]: bus_name="org.bluez"
In [3]: obj_path="/org/bluez/5612/hci0/dev_78_DD_08_A3_A7_52/service0200/characteristic0204"
In [4]: bus = dbus.SystemBus()
In [5]: proxy = bus.get_object(bus_name,obj_path)
In [6]: char = dbus.Interface(proxy, dbus_interface="org.bluez.Characteristic")
In [7]: properties = char.GetProperties()
In [8]: print properties
dbus.Dictionary({dbus.String(u'Description'): dbus.String(u'Outside Temperature', variant_level=1), dbus.String(u'UUID'): dbus.String(u'0000a006-0000-1000-8000-00805f9b34fb', variant_level=1), dbus.String(u'Value'): dbus.Array([dbus.Byte(128), dbus.Byte(110)], signature=dbus.Signature('y'), variant_level=1), dbus.String(u'Name'): dbus.String(u'', variant_level=1)}, signature=dbus.Signature('sv'))
In [9]: result = char.SetProperty("Value", dbus.Array([dbus.Byte(77), dbus.Byte(22)]))
In [10]: properties = char.GetProperties()
In [11]: print properties
dbus.Dictionary({dbus.String(u'Description'): dbus.String(u'Outside Temperature', variant_level=1), dbus.String(u'UUID'): dbus.String(u'0000a006-0000-1000-8000-00805f9b34fb', variant_level=1), dbus.String(u'Value'): dbus.Array([dbus.Byte(77), dbus.Byte(22)], signature=dbus.Signature('y'), variant_level=1), dbus.String(u'Name'): dbus.String(u'', variant_level=1)}, signature=dbus.Signature('sv'))

Tuesday, December 21, 2010

gatttool in bluez over BR/EDR

Recently, I am studying Bluetooth 4.0 (Low Energy) core spec and checking the latest bluez code about LE stuff. Here is my working notes and how I use 'gatttool' to verify Generic Attribute Profile (GATT) features. We can check this feature over BR/EDR first, not use real LE device yet. My working machine is Ubuntu 10.10.

Set up Bluez part

retrieve latest bluez code, configure it with enable-attrib, and compile it
# git clone git://git.kernel.org/pub/scm/bluetooth/bluez.git
# cd bluez
# autoreconf -vifs
# ./configure --prefix=/usr --mandir=/usr/share/man \
--sysconfdir=/etc --localstatedir=/var --libexecdir=/lib --enable-attrib
# make && sudo make install

modify main.conf, enable LE and attribute-server

diff --git a/src/main.conf b/src/main.conf
index c03f135..121ee9b 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -58,9 +58,9 @@ DebugKeys = false

# Enable Low Energy support if the dongle supports. Default is false.
# Enable/Disable interleave discovery and attribute server over LE.
-EnableLE = false
+EnableLE = true

# Enable the GATT Attribute Server. Default is false, because it is only
# useful for testing. Attribute server is not enabled over LE if EnableLE
# is false.
-AttributeServer = false
+AttributeServer = true

start bluetooth daemon in foreground with debug information

# sudo /usr/sbin/bluetoothd -n -d

Play with gatttool

Since we configured Bluez with enable-attrib, we will start an attribute-server from running bluetooth daemon. It would add some attribute records for GATT service, and it's created from attrib/example.c file. Also, we will add a GAP service like below.


erin@sundays:~/project/bluez$ sdptool browse local
Browsing FF:FF:FF:00:00:00 ...
Service Name: Generic Attribute Profile
Service Provider: BlueZ
Service RecHandle: 0x10000
Service Class ID List:
"Generic Attribute" (0x1801)
Protocol Descriptor List:
"L2CAP" (0x0100)
PSM: 31
"ATT" (0x1801)
uint16: 0x1
uint16: 0xffff
Profile Descriptor List:
"Generic Attribute" (0x1801)
Version: 0x0100

Below GATT features are from BT 4.0 core spec Volume 3 Part G.

Primary Service Discovery
This procedure is used by a client to discover primary services on a server. Once the primary services are discovered, additional information about the primary services can be accessed using other procedures, including characteristic discovery and relationship discovery to find other related primary and secondary services.

a. Discover all primary services ==> "Read By Group Type Request"
b. Discover primary service by service UUID ==> "Find By Type Value Request"



gatt_discover_primary(attrib, opt_start, opt_end, opt_uuid, primary_by_uuid_cb, attrib);

erin@sundays:~$ sudo gatttool -b 78:DD:08:A3:A7:52 --primary --psm=31 --mtu=48
attr handle = 0x0001, end grp handle = 0x0006, attr value (UUID) = 1800
attr handle = 0x0010, end grp handle = 0x0012, attr value (UUID) = 1801
attr handle = 0x0100, end grp handle = 0x0111, attr value (UUID) = a002
attr handle = 0x0200, end grp handle = 0x0214, attr value (UUID) = a004
attr handle = 0x0680, end grp handle = 0x0685, attr value (UUID) = 4f0ac096-35d4-4911-9631-dea8dc74eefe

erin@autumn:~/project/bluez$ gatttool -b 78:DD:08:A3:A7:52 --primary --uuid=1801
Starting handle: 0010 Ending handle: 0012

erin@autumn:~/project/bluez$ gatttool -b 78:DD:08:A3:A7:52 --primary --uuid=1800
Starting handle: 0001 Ending handle: 0006


Characteristic Discovery
This procedure is used by a client to discover service characteristics on a server. Once the characteristics are discovered additional information about the characteristics can be discovered or accessed using other procedures.

a. Discover all characteristics of a Service ==> "Read By Type Request"
b. Discover characteristics by UUID ==> "Read By Type Request"



gatt_discover_char(attrib, opt_start, opt_end, char_discovered_cb, char_data);
gatt_read_char_by_uuid(attrib, start, end, &uuid, func, user_data);

erin@sundays:~$ sudo gatttool -b 78:DD:08:A3:A7:52 --characteristics --psm=31 --mtu=48
handle = 0x0004, char properties = 0x02, char value handle = 0x0006, uuid = 2a00
handle = 0x0011, char properties = 0x02, char value handle = 0x0012, uuid = a001
handle = 0x0106, char properties = 0x02, char value handle = 0x0110, uuid = a003
handle = 0x0203, char properties = 0x02, char value handle = 0x0204, uuid = a006
handle = 0x0210, char properties = 0x02, char value handle = 0x0212, uuid = a009
handle = 0x0501, char properties = 0x02, char value handle = 0x0502, uuid = a00c
handle = 0x0503, char properties = 0x02, char value handle = 0x0504, uuid = a00d
handle = 0x0506, char properties = 0x02, char value handle = 0x0507, uuid = a00c
handle = 0x0508, char properties = 0x02, char value handle = 0x0509, uuid = a00d
handle = 0x0560, char properties = 0x02, char value handle = 0x0568, uuid = a00f
handle = 0x0682, char properties = 0x02, char value handle = 0x0683, uuid = 8088f218-902c-450b-b6c4-62891e8c25e9

erin@autumn:~/project/bluez$ gatttool -b 78:DD:08:A3:A7:52 --characteristics --start=0x0001 --end=0x0100
handle = 0x0004, char properties = 0x02, char value handle = 0x0006, uuid = 2a00
handle = 0x0011, char properties = 0x02, char value handle = 0x0012, uuid = a001


Characteristic Descriptor Discovery
This procedure is used by a client to discover characteristic descriptors of a characteristic. Once the characteristic descriptors are discovered additional information about the characteristic descriptors can be accessed using other procedures.

a. Discover All Characteristic Descriptors ==> "Find Information Request"



gatt_find_info(attrib, opt_start, opt_end, char_desc_cb, NULL);
erin@sundays:~$ sudo gatttool -b 78:DD:08:A3:A7:52 --char-desc --psm=31
handle = 0x0001, uuid = 2800
handle = 0x0004, uuid = 2803
handle = 0x0006, uuid = 2a00
handle = 0x0010, uuid = 2800
handle = 0x0011, uuid = 2803

erin@autumn:~/project/bluez$ gatttool -b 78:DD:08:A3:A7:52 --char-desc --start=0x0001 --end=0x0010
handle = 0x0001, uuid = 2800
handle = 0x0004, uuid = 2803
handle = 0x0006, uuid = 2a00
handle = 0x0010, uuid = 2800
erin@autumn:~/project/bluez$ gatttool -b 78:DD:08:A3:A7:52 --char-desc --start=0x0001 --end=0x0005
handle = 0x0001, uuid = 2800
handle = 0x0004, uuid = 2803


Characteristic Value Read
This procedure is used to read a Characteristic Value from a server.

a. Read characteristic value
b. Read using characteristic UUID
c. Read long characteristic values (not implement)
d. Read multiple characteristic values (not implement)



gatt_read_char(attrib, opt_handle, char_read_cb, attrib);
==> g_attrib_send(attrib, ATT_OP_READ_REQ, pdu, plen, func, user_data, NULL);

gatt_read_char_by_uuid(attrib, opt_start, opt_end, opt_uuid, char_read_by_uuid_cb, char_data);
==> g_attrib_send(attrib, ATT_OP_READ_BY_TYPE_REQ, pdu, plen, func, user_data, NULL);

erin@sundays:~$ sudo gatttool -b 78:DD:08:A3:A7:52 --char-read --uuid=2800
handle: 0x0001 value: 00 18
handle: 0x0010 value: 01 18
handle: 0x0100 value: 02 a0
handle: 0x0200 value: 04 a0
handle: 0x0680 value: 4f 0a c0 96 35 d4 49 11 96 31 de a8 dc 74 ee fe

erin@sundays:~$ sudo gatttool -b 78:DD:08:A3:A7:52 --char-read --handle=0x0001
Characteristic value/descriptor: 00 18

erin@autumn:~/project/bluez$ gatttool -b 78:DD:08:A3:A7:52 --char-read --uuid=a00d
handle: 0x0504 value: 32 33 37 34 39 35 2d 33 32 38 32 2d 41
handle: 0x0509 value: 31 31 32 36 37 2d 32 33 32 37 41 30 30 32 33 39


Characteristic value write
This procedure is used to write a Characteristic Value to a server.

a. Write without response
b. Signed write without response (not check yet)
c. Write characteristic value
d. Write long charcharacteristic values (not check yet)
e. Reliable writes (not check yet)



erin@sundays:~$ gatttool -b 78:DD:08:A3:A7:52 --char-write --psm=31 --mtu=48 --handle=0x0001 --value=0x0011
erin@sundays:~$ gatttool -b 78:DD:08:A3:A7:52 --char-read --psm=31 --mtu=48 --handle=0x0001
Characteristic value/descriptor: 00 00 11

Sunday, October 24, 2010

Tips for Transmission in Android


use Transmission Web UI


1. set environment variable TRANSMISSION_WEB_HOME to "/etc/transmission/web"

diff --git a/external/transmission/libtransmission/platform.c b/external/transmission/libtransmission/platform.c
index d3493ae..e7d6ab8 100644
--- a/external/transmission/libtransmission/platform.c
+++ b/external/transmission/libtransmission/platform.c
@@ -27,6 +27,10 @@
#include
#endif

+#ifndef TRANSMISSION_WEB_HOME
+ #define TRANSMISSION_WEB_HOME "/etc/transmission/web"
+#endif
+
#include
#include
#include
@@ -615,7 +619,10 @@ tr_getWebClientDir( const tr_session * session UNUSED )
s = NULL;
}
}
-
+#elif defined( TRANSMISSION_WEB_HOME )
+ {
+ s = tr_strdup( TRANSMISSION_WEB_HOME );
+ }
#else /* everyone else, follow the XDG spec */



2. copy its Web UI to rootdir

diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index e91bad2..2f0ff12 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -5,6 +5,43 @@ include $(CLEAR_VARS)

copy_from := \
etc/dbus.conf \
+ etc/transmission/web/stylesheets/common.css \
+ etc/transmission/web/stylesheets/iphone.css \
+ etc/transmission/web/stylesheets/ie7.css \
+ etc/transmission/web/stylesheets/ie6.css \
+ etc/transmission/web/javascript/menu.js \
+ etc/transmission/web/javascript/common.js \
+ etc/transmission/web/javascript/torrent.js \
+ etc/transmission/web/javascript/transmission.remote.js \
+ etc/transmission/web/javascript/jquery \
+ etc/transmission/web/javascript/jquery/jquery.form.min.js \
+ etc/transmission/web/javascript/jquery/jquery.contextmenu.min.js \
+ etc/transmission/web/javascript/jquery/json.min.js \
+ etc/transmission/web/javascript/jquery/jquery.min.js \
+ etc/transmission/web/javascript/jquery/jquery.transmenu.min.js \
+ etc/transmission/web/javascript/dialog.js \
+ etc/transmission/web/javascript/transmission.js \
+ etc/transmission/web/index.html \
+ etc/transmission/web/images/favicon.ico \
+ etc/transmission/web/images/favicon.png \
+ etc/transmission/web/images/graphics/logo.png \
+ etc/transmission/web/images/graphics/filter_icon.png \
+ etc/transmission/web/images/graphics/chrome.png \
+ etc/transmission/web/images/graphics/iphone_chrome.png \
+ etc/transmission/web/images/graphics/transfer_arrows.png \
+ etc/transmission/web/images/graphics/filter_bar.png \
+ etc/transmission/web/images/progress/progress.png \
+ etc/transmission/web/images/buttons/cancel.png \
+ etc/transmission/web/images/buttons/info_activity.png \
+ etc/transmission/web/images/buttons/info_files.png \
+ etc/transmission/web/images/buttons/tab_backgrounds.png \
+ etc/transmission/web/images/buttons/torrent_buttons.png \
+ etc/transmission/web/images/buttons/toolbar_buttons.png \
+ etc/transmission/web/images/buttons/file_wanted_buttons.png \
+ etc/transmission/web/images/buttons/info_trackers.png \
+ etc/transmission/web/images/buttons/file_priority_buttons.png \
+ etc/transmission/web/images/buttons/info_general.png \
+ etc/transmission/web/images/webclip-icon.png \
etc/hosts


3. write transmission-daemon as a service in init.rc

diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3011bf6..a3c45f8 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -361,6 +361,12 @@ service dbus /system/bin/dbus-daemon --system --nofork
user bluetooth
group bluetooth net_bt_admin

+service tr-daemon /system/bin/transmission-daemon -g /data/transmission -w /data/transmission/ -c /data/transmission/
+ user root
+ group net_admin system
+ disabled
+ oneshot
+
service bluetoothd /system/bin/bluetoothd -n
socket bluetooth stream 660 bluetooth bluetooth
socket dbus_bluetooth stream 660 bluetooth bluetooth


4. Some important arguments for transmission-daemon


-g --config-dir directory
Where to look for configuration files. When it stars to run, it would
write a settings.json file to this folder. It stores all config values.

-c directory
Directory to watch for new .torrent files to be added. If you push
torrent files to this directory, the daemon will load them into
Transmission automatically.

-w --download-dir
Where to store downloaded data.



5. add Transmission site "http://localhost:9091" to default Bookmark list in Browser

diff --git a/packages/apps/Browser/res/values/strings.xml b/packages/apps/Browser/res/values/strings.xml
index 18a2144..1824664 100644
--- a/packages/apps/Browser/res/values/strings.xml
+++ b/packages/apps/Browser/res/values/strings.xml
@@ -675,6 +675,8 @@
http://www.weather.com/
BBC
http://www.bbc.co.uk/
+ Transmission
+ http://localhost:9091/


Friday, September 10, 2010

use Transmission in Android

Recently, I am checking how to use BitTorrent function in Android. There are lots of BitTorrent tools in Internet. Based on my common user experiences, I was using BitComet in Windows machine, Transmission in Ubuntu laptop, Vuze in Mac mini, and rTorrent in Debian server. I also found there are some BitTorrent remote management applications in Android market, but it's for controlling remote torrents, not directly download files via BT.

After making a survey of these BitTorrent tools, I choose Transmission, since I think porting it in Android is with less effort and more simple. I didn't build related GTK or QT code for Transmission. I'd like to use it without its own GUI. It has 'transmission-daemon' and 'transmission-remote' command line tools. I can use both of them to use Transmission without a GUI. Furthermore, it comes with a WEB UI. It means I can control BitTorrent from a browser. Therefore, I don't need to write Java UI application for it.


# export TRANSMISSION_WEB_HOME=/etc/web/transmission
# transmission-daemon -f -g /sdcard/transmission -w /sdcard/transmission --incomplete-dir /sdcard/transmission
[11:48:07.715] Transmission 2.04 (11151) started (external/transmission/libtransmission/session.c:622)
[11:48:07.727] RPC Server Adding address to whitelist: 127.0.0.1 (external/transmission/libtransmission/rpc-server.c:767)
[11:48:07.727] RPC Server Serving RPC and Web requests on port 9091 (external/transmission/libtransmission/rpc-server.c:940)
[11:48:07.727] RPC Server Whitelist enabled (external/transmission/libtransmission/rpc-server.c:944)
[11:48:07.728] DHT Generating new id (external/transmission/libtransmission/tr-dht.c:378)
[11:48:07.728] Using settings from "/sdcard/transmission" (external/transmission/daemon/daemon.c:443)
[11:48:07.728] disable save setting here! (external/transmission/daemon/daemon.c:444)
[11:48:07.728] Loaded 2 torrents (external/transmission/libtransmission/session.c:1743)
[11:48:07.728] Port Forwarding (NAT-PMP) initnatpmp succeeded (0) (external/transmission/libtransmission/natpmp.c:67)
[11:48:07.729] Port Forwarding (NAT-PMP) sendpublicaddressrequest succeeded (2) (external/transmission/libtransmission/natpmp.c:67)

I verified it in Android emulator (froyo), coz it can use local machine network. I run Transmission-daemon from the terminal. Then, I open Android Web browser and type this URL http://localhost:9091. It would go to Transmission Web UI. I can control torrent from it. Like add a BT torrent, delete torrent, pause it, check current status. The Web UI looks nice and easy to use.

How about make it more straight? I would like to search BitTorrent from application UI, not from Web browser. Then I can save some time on typing. I find a very comprehensive BitTorrent tool Transdroid in Android market . It can control remote BitTorrent and it supports Transmission too. I use it to connect my local one. It has a search function and you can also set the BitTorrent searching engine from the menu. It makes thing easier, search something, pick up a torrent, download it, and see it. There is a help guide in their web site.


These screenshots are copied from my office machine. The network environment here is bad. I cannot see good downloading speed. But I verified few torrents at my home machine, the downloading speed was over 500 KB. Also, the download speed depends on the content you are downloading too. If you search some very hot or popular things, the download speed would be very high!

I created a project android-transmission in gitoriou. If you have interests, you could use my works there.

Monday, August 2, 2010

0xdroid release beagle-eclair-0x5, devkit8k-eclair-0x5 (with/without SGX)

0xlab team is glad to announce the fifth release of 0xdroid. 0xdroid is community-developed Android distribution by 0xlab, runs on omap3 based boards include beagleboard and devkit8000.

Version: beagle-eclair-0x5-sgx, beagle-eclair-0x5-no-sgx, devkit8k-eclair-0x5-sgx, devkit8k-eclair-0x5-no-sgx

Version: beagle-eclair-0x5
Date: July 30, 2010
Release Image:
beagle-eclair-0x5_no_sgx.zip
beagle-eclair-0x5_sgx.zip
devkit8k-eclair-0x5_no_sgx.zip
devkit8k-eclair-0x5_sgx.zip
MD5 sum:
beagle-eclair-0x5_no_sgx
beagle-eclair-0x5_sgx
devkit8k-eclair-0x5_no_sgx
devkit8k-eclair-0x5_sgx


Release Details
  • Eclair codebase
  • Feature: Major Linux kernel upgrade: from 2.6.29 to 2.6.32
  • Feature: Support TI's Android PowerVR SGX (hardware 2D/3D engine)
  • Feature: Support Android USB gadget: adb and mass-storage (issue #95)
  • Note: 0xdroid no longer support usbnet gadget driver. Use adb or USB Ethernet instead.
  • Feature: new Bluetooth Extensions -- HID (issue #102)
  • Feature: Make Launcher2 really usable (issue #76)
  • Feature: Make Gallery3D workable by fixing PixelFlinger regressions (issue #107)
  • Feature: Touchscreen Calibration shouldn't require reboot (issue #94, issue #99)
  • Feature: Robocat i2c port support (issue #134)
  • Feature: Improved libgralloc for non HW accelerated target (issue #108, issue #133)

For more detail, please reference our roadmap and issues tracking

Where to download images
You can grab the image from here and following the steps described on the wiki page to test the image.

This release comes with PowerVR SGX from Texas Instruments. If you try both two images with SGX and without SGX, you would tell how amazing it displays photos in Gallery 3D application. Like ususal, it also comes with a happy Installer and it would bring you an Android Eclair system in few seconds. If you are looking for more details about the integration, you could reference to this wiki page.

How to build from scratch

$ repo init -u git://gitorious.org/0xdroid/manifest.git -b beagle-eclair
$ echo "TARGET_PRODUCT := beagleboard" > buildspec.mk
$ echo "TARGET_PRODUCT := devkit8000" > buildspec.mk ( if build for devkit8000 )
$ echo "INSTALL_PREBUILT_DEMO_APKS := true" >> buildspec.mk ( optional for adding prebuilt demo apks )
$ cd .repo/manifests/
$ git checkout -b beagle-eclair-0x5-release beagle-eclair-0x5
$ repo sync
$ repo forall -c "git checkout -b beagle-eclair-0x5-release beagle-eclair-0x5"
$ make (or make -j4 if there are 4 cores)

Monday, July 5, 2010

Connect with Bluetooth keyboard and mice in Android Eclair

In Nexus one without HID profile:




In Qualcomm MSM72xx platform with HID profile support:





Apparently, it is more friendly and user can connect with bluetooth keyboard from Setting UI application. Use can type words from a real keyboard, not from a tiny touch screen. All code are in 0xdroid project based on Eclair.

Monday, June 21, 2010

Add Bluetooth HID profile in Android

The HID profile defines the protocols, procedures and features to be used by Bluetooth HID such as keyboards, pointing devices, gaming devices and remote monitoring devices. When I tried bluetooth function in Android Dev Phone (G1) last year, I use a utility tool 'hidd' which is from native bluez. It is a command tool. After I can pair with Apple Wireless keyboard sucessfully, I type 'hidd ' from terminal, then I can start to use it. But it's not automatically, I cannot connect it from Setting UI application either. Therefore, we should add a new Bluetooth HID profile in Android, to make it be connectable, like a BT headset or speaker.


# hidd --connect 00:1D:4F:A7:9A:49

# hidd --show
00:1D:4F:A7:9A:49 Apple Inc. Keyboard [05ac:022c] connected



0xlab is a member of OESF (Oopen Embedded Software Foundation) and they have some very useful bluetooth extensions in their 'Embedded Master 1' project. Althought these features are based on Android Donuts, they are still a very good reference. Therefore, I use their code and modify few parts of code for newer Android Eclair version. The difference of Eclair from Donuts in Bluetooth is bluez dbus API changes and some java API changes in frameworks. I've committed my patches to 0xdroid project in gitouris. If you'd like to use my work, you could apply patches in Frameworks and Setting application.



Beside the code in Frameworks and Settings UI application, I have to enable some features in kernel, since I use Apple Wireless Keyboard for this experiment. If I don't enable them, I can't never create an input device for Apple keyboard in Android. It took me few days to debug this issue. I cannot tell why I can use hidd to connect with it without any problem, but cannot use Dbus method to connect with it correctly. It's very weird. It's said 'Connected', but I cannot receive any key events or cannot see a virtual input device in Android system. Furthermore, there is no problem on connecting with a BT mice at all. Both methods are fine.

When I tried to implement any features in Android, I would try it in my Ubuntu machine first. They have linux kenel and many native code are the same. Based on the experiences in Ubuntu, I can know how it works and the normal flow what it looks like. In Ubuntu, when I connect with an Apple Wireless Keyboard, I can see the device name from dmesg. But I cannot see the device name in Android at all, I can see BT mouse device name in Android. Therefore, I check menuconfig on building kernel, and then I see some HID special drivers. I just enable features like CONFIG_HID_APPLE=y, CONFIG_HID_DEBUG=y, CONFIG_HIDRAW=y, CONFIG_USB_HIDDEV=y. After using the new kenel image, I can connect/disconnect with a BT keyboard from Setting UI application normally. I've verified my work in Beagle board and Qualcomm MSM72xx platform.

Monday, May 3, 2010

How to add a test plan, package to Android CTS?

If we check Android source code, we can find some test packages in Android applications. We can either run these test packages in Android device or we can combine them with Android CTS from host machine. Here is an example from Music application. I will create a test plan MusicTests and test package MusicTestCases in CTS.

Add test package source code to cts folder

$ cp -a $MYDROID/packages/apps/Music/tests $MYDROID/cts/tests/tests/MusicTests


Modify test package name in Android.mk to avoid redundant name

$ cat $MYDROID/cts/tests/tests/MusicTests/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

# We only want this apk build for tests.
LOCAL_MODULE_TAGS := tests

LOCAL_JAVA_LIBRARIES := android.test.runner

# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_PACKAGE_NAME := MusicTestsCases

LOCAL_INSTRUMENTATION_FOR := Music

include $(BUILD_PACKAGE)


Add one test case to CTS_CASE_LIST in build/core/tasks/cts.mk


erin@midnight:~/eclair/build/core$ git diff
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 917c5dc..17f6dbc 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -97,6 +97,7 @@ CTS_CASE_LIST := \
CtsPerformance3TestCases \
CtsPerformance4TestCases \
CtsPerformance5TestCases \
+ MusicTestsCases \
ApiDemos \
ApiDemosReferenceTest \
$(CTS_CORE_CASE_LIST) \


Add test plan 'MusicTests' in cts/tools/utils/buildCts.py

def GenerateTestPlans(self):
.....
plan = tools.TestPlan(packages)
plan.Include(r'android\.MusicTests')
self.__WritePlan(plan, 'MusicTests')


make cts again


$ cd $MYDROID
$ . build/envsetup.sh
$ make cts


run MusicTestCases

$ cd $mydroid/out/host/linux-x86/bin/
$ ./cts

cts_host > start --plan MusicTests
start test plan MusicTests
==============================================================
Test package: android.MusicTests
install met failure [install_failed_insufficient_storage]
com.android.music.tests.stress.AlbumsPlaybackStress#testAlbumPlay.....(pass)
com.android.music.tests.stress.AlbumsPlaybackStress#testActivityTestCaseSetUpProperly....(pass)
com.android.music.tests.stress.MusicPlaybackStress#testPlayAllSongs....(pass)
com.android.music.tests.stress.MusicPlaybackStress#testActivityTestCaseSetUpProperly....(pass)
com.android.music.tests.functional.TestPlaylist#testDeletePlaylist....(pass)
com.android.music.tests.functional.TestPlaylist#testRenamePlaylist....(pass)
com.android.music.tests.functional.TestPlaylist#testActivityTestCaseSetUpProperly....(pass)
com.android.music.tests.functional.TestSongs#testAddPlaylist.....(pass)
com.android.music.tests.functional.TestSongs#testSetRingtone.....(pass)
com.android.music.tests.functional.TestSongs#testDeleteSong.....(pass)
com.android.music.tests.functional.TestSongs#testActivityTestCaseSetUpProperly....(pass)
com.android.music.tests.MusicPlayerStability#testPlay30sMP3....(pass)
com.android.music.tests.MusicPlayerStability#testLaunchMusicPlayer....(pass)
==============================================================
Test summary: pass=13 fail=0 timeOut=0 notExecuted=0 Total=13
Time: 100.780s


Here is a video I run this MusicTestCases in Android emulator!

Tuesday, April 27, 2010

[video] Use 3G modem card in Android (devkit8000)

Use 3G modem data card in Android

We found Android-x86 had a new feature about telephony. It's about to use a 3G modem data card in EeePC and it can use 3G network to browse Internet. Therefore, I followed up this issue and verified it in Devkit8000 device. Now, it's one of our new released features and it comes with 0xdroid 0x4 release pre-built image too. In the beginning, I was trying to use a Quanta Q101 data card in Android emulator. How to run this experiment in my Ubuntu 9.10 manchine?



Set up Quanta Q101

Check this long discussion, I added a new rule file as below. When I plug-in q101 card, it can auto-mount to GSM modem mode with 4 ports.


erin@midnight:~$ cat /etc/udev/rules.d/30-q101.rules
#
# first, q101 will be detected as usb_storage of 0408:1000
# you have to force it suspend to change running mode from
# storage to 3.5g card

SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ACTION=="add", ATTRS{idVendor}=="0408", ATTRS{idProduct}=="1000", RUN+="/bin/sh -c 'cd /sys$env{DEVPATH};until test -f power/level;do cd ..;done;if [ -f power/level ];then echo suspend > power/level;fi'"

Wait about 10 seconds, then you can check these devices. RIL is /dev/ttyUSB3, PPP is /dev/ttyUSB1. When you use in Android emulator, it would become /dev/ttyS2 and /dev/ttyS3.


erin@midnight:~$ ls -l /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 1 2010-04-27 16:34 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 2010-04-27 15:55 /dev/ttyUSB2
crw-rw---- 1 root dialout 188, 3 2010-04-27 17:16 /dev/ttyUSB3
crw-rw---- 1 root dialout 188, 4 2010-04-27 15:50 /dev/ttyUSB4


Need Kernel support PPP
I read this discussion and download Android kernel source code to rebuild kernel.


# git clone git://android.git.kernel.org/kernel/common.git
# cd kernel
# git checkout -b android-goldfish korg/android-goldfish-2.6.29
# cd $MYDROID/out
# ./host/linux-x86/bin/emulator -system ./target/product/generic/system.img -sysdir ./target/product/generic/system -data ./target/product/generic/userdata.img -kernel ../prebuilt/android-arm/kernel/kernel-qemu -ramdisk ./target/product/generic/ramdisk.img
# adb pull /proc/config.gz $MYDROID/kernel/
# cd $MYDROID/kernel/
# gunzip config.gz
# mv config .config
# make ARCH=arm menuconfig
(Add PPP in)
# make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- zImage


Start the emulator again with new kernel image and then check /dev/ppp device!

# cd $MYDROID/out
# ./host/linux-x86/bin/emulator -system ./target/product/generic/system.img -sysdir ./target/product/generic/system -data ./target/product/generic/userdata.img -kernel ../kernel/arch/arm/boot/zImage -ramdisk ./target/product/generic/ramdisk.img
# adb shell ls -l /dev/ppp
crw-rw---- radio vpn 108, 0 2010-04-27 15:36 ppp


Modify Android source code
I applied the patches from Android-x86 and re-modified some code for Quanta q101 card. Also modify gprs script, since I am using Taiwan GSM netowork.

external ppp
http://gitorious.org/0xdroid/external_ppp/commit/6624b6760d8fde02993f3a3f02df3ec9db739e41

hardware ril
http://git.android-x86.org/?p=platform/hardware/ril.git;a=commit;h=b499fabc3459930a42f0ecc62257caef6aa216dc

system core
http://gitorious.org/0xdroid/system_core/commit/81b121623c3f05298b5166d03714655d1ab2ddf8

Since I am using Android emulator, the device names are different from Devkit8000.

Change the device permissions:

diff --git a/init/devices.c b/init/devices.c
index 4d93b44..0023cc3 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -108,6 +108,8 @@ static struct perms_ devperms[] = {
{ "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 },
{ "/dev/ttyMSM0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
{ "/dev/ttyHS0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
+ { "/dev/ttyS2", 0660, AID_RADIO, AID_RADIO, 0 },
+ { "/dev/ttyS3", 0660, AID_RADIO, AID_RADIO, 0 },
{ "/dev/uinput", 0660, AID_SYSTEM, AID_BLUETOOTH, 0 },
{ "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 },
{ "/dev/tty0", 0660, AID_ROOT, AID_SYSTEM, 0 },


Modify RIL argument and add ppp service from init:

erin@midnight:~/eclair/mydroid/build/target/board/generic$ cat system.prop
#
# system.prop for generic sdk
#

rild.libpath=/system/lib/libreference-ril.so
rild.libargs=-d /dev/ttyS2

# add these lines in system/core/rootdir/init.rc
service ppp /system/bin/pppd call gprs
user root
group system radio
disabled
oneshot


Run Android Emulator
After changing these code, rebuilt Android again. Then we can run Android emulator from below command:


erin@midnight:~/eclair/mydroid/out$ ./host/linux-x86/bin/emulator -system ./target/product/generic/system.img -sysdir ./target/product/generic/system -data ./target/product/generic/userdata.img -kernel ../kernel/arch/arm/boot/zImage -ramdisk ./target/product/generic/ramdisk.img -sdcard ./target/product/generic/sdcard.img -qemu -serial /dev/ttyUSB3 -serial /dev/ttyUSB1


Run ppp manually
After starting ppp service, it would appear one network connection called 'ppp'.

# adb shell
# start ppp
# netcfg
lo UP 127.0.0.1 255.0.0.0 0x00000049
eth0 UP 10.0.2.15 255.255.255.0 0x00001043
tunl0 DOWN 0.0.0.0 0.0.0.0 0x00000080
gre0 DOWN 0.0.0.0 0.0.0.0 0x00000080
ppp0 UP 115.82.23.238 255.255.255.255 0x000010d1

Add APN for Taiwan GSM network




Sunday, April 25, 2010

Android CTS (Compatibility Test Suite) introduction

What is CTS?

Compatibility Test Suite is a command mode tool to run a series of test cases in Android. They published all CTS source codes from Eclair branch on January 2010.

git repository

http://android.git.kernel.org/?p=platform/cts.git;a=summary

How to run CTS in host machine?

$ cd $MYDROID
$ . build/envsetup.sh
$ make cts

(it would generate all test plans, packages, cases, result report format and then zip to a android-cts.zip file)

  • Package CTS: out/host/linux-x86/cts/android-cts.zip
  • cts make file: mydroid/build/core/tasks/cts.mk
  • run cts program: mydroid/out/host/linux-x86/bin/cts
  • test plans: mydroid/out/host/linux-x86/cts/android-cts/repository/plans
  • test packages: mydroid/out/host/linux-x86/cts/android-cts/repository/testcases
  • test results: mydroid/out/host/linux-x86/cts/android-cts/repository/results
  • CTS program settings value: mydroid/cts/tools/utils/host_config.xml


run cts
$ cd $mydroid/out/host/linux-x86/bin/
$ ./cts

Screen would like this:

erin@midnight:~/eclair/mydroid/out/host/linux-x86/bin$ ./cts
Android CTS version 2.1_r1
cts_host > help
Usage: command options
Avaiable commands and options:
Host:
help: show this message
exit: exit cts command line
Plan:
ls --plan: list available plans
ls --plan plan_name: list contents of the plan with specified name
add --plan plan_name: add a new plan with specified name
add --derivedplan plan_name -s/--session session_id -r/--result result_type: derive a plan from the given session
rm --plan plan_name/all: remove a plan or all plans from repository
start --plan test_plan_name: run a test plan
start --plan test_plan_name -d/--device device_ID: run a test plan using the specified device
start --plan test_plan_name -t/--test test_name: run a specific test
start --plan test_plan_name -p/--package java_package_name: run a specific java package
start --plan test_plan_name -t/--test test_name -d/--device device_ID: run a specific test using the specified device
start --plan test_plan_name -p/--package java_package_name -d/--device device_ID: run a specific java package using the specified device
Package:
ls -p/--package: list available packages
ls -p/--package package_name: list contents of the package with specified name
add -p/--package root: add packages from root to repository
rm -p/--package package_name/all: remove a package or all packages from repository
Result:
ls -r/--result: list all result of sessions
ls -r/--result -s/--session session_id: list detail case result of a specified session
ls -r/--result [pass/fail/notExecuted/timeout] -s/--session session_id: list detail cases of a specified session by the specified result.
History:
history/h: list all commands in command history
history/h count: list the latest count records in command history
history/h -e num: run the command designated by 'num' in command history
Device:
ls -d/--device: list available devices




How to add test plan, test packages to CTS?

  1. Add test package name to cts.mk, it would generate apk file when we build cts.
  2. Add all source folder (includes src java files, Android.mk and its Manifest file) to mydroid/cts/tests/tests
  3. If you'd like to create a test plan for this test package. Modify this python script: mydroid/cts/tools/utils/buildCts.py

Adjust CTS program settings?


Modify $mydroid/cts/tools/utils/host_config.xml
  • Number of tests executed between reboots. A value <= 0 disables reboots. (maxTestCount)
  • Max size [tests] for a package to be run in batch mode. (maxTestInBatchMode)
  • Max time [ms] between test status updates. (testStatusTimeoutMs)
  • Max time [ms] from start of package in batch mode and the first test status update. (batchStartTimeoutMs)
  • Max time [ms] from start of test in individual mode to the first test status update. (individualStartTimeoutMs)
  • Timeout [ms] for the signature check. (signatureTestTimeoutMs)
  • Timeout [ms] for package installations. (packageInstallTimeoutMs)
  • Time to wait [ms] after a package installation or removal. (postInstallWaitMs)
Write your own testing package?

If you would like to write your own testing package, you may reference the Instrumentation Testing document from Android porting guide. Also, you could reference the source code from few Android application, like Browser, Messages, Gallery, Email, Camera, Calculator....etc. You can build its test apk file and upload it to device.

How to write test cases?
Each instrumentation test case is similar to an Android application with the distinction that it starts another application. For example, have a look in the $MYDROID/packages/apps/Music directory.
  • There should be a Makefile and an Android Manifest file
  • Tests are located in $MYDROID/packages/apps/Music/tests.
  • The Instrumentation Test Runner is located at packages/apps/Music/tests/src/com/android/music/MusicPlayerFunctionalTestRunner.java.

Build package apk file

erin@midnight:~/eclair/mydroid/packages/apps/Music/tests$ mm
Install: out/target/product/generic/data/app/MusicTests.apk

Install it to the device
erin@midnight:~/eclair/mydroid/packages/apps/Music/tests$ adb install ../../../../out/target/product/generic/data/app/MusicTests.apk

How to run test cases in device?

Running Tests

erin@midnight:~/$ adb shell pm list instrumentation
instrumentation:com.android.music.tests/.MusicPlayerStressTestRunner (target=com.android.music)
instrumentation:com.android.music.tests/.MusicPlayerFunctionalTestRunner (target=com.android.music)
instrumentation:com.android.music.tests/.MusicPlayerLaunchPerformance (target=com.android.music)


The am command is a command-line interface to the ActivityManager. 'am' is used to start and instrument activities using the adb shell command, as shown in the snippet below:


> adb shell am
usage: am [start|instrument]
am start [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e <EXTRA_KEY> <EXTRA_VALUE> [-e <EXTRA_KEY> <EXTRA_VALUE> ...]
[-n <COMPONENT>] [-D] [<URI>]
am instrument [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]
[-w] <COMPONENT>

For example, to start the Contacts application you can use
> adb shell am start -n com.google.android.contacts/.ContactsActivity


Eg. verify Music player launcher performance

erin@midnight:~/$ adb shell am instrument -w -r com.android.music.tests/.MusicPlayerLaunchPerformance

Eg. verify Music player stress test

erin@midnight:~/$ adb shell am instrument -w -r com.android.music.tests/.MusicPlayerStressTestRunner

Here is a video about running a cts test case by Android emulator!

Monday, February 1, 2010

New Bluetooth Object Push Profile in Android 2.0 (Eclair)

From Android developer website, they said Android 2.0 provides two new Bluetooth profiles: Object Push Profile (OPP) and Phone Book Access Profile (PBAP). Seeing is believing. Where is the meat? ha, I found they finally released their Bluetooth application source code. Therefore, I tried to verify OPP in Beagle board. :D

As usual, I read Build-from-Scratch wiki page and download code from 0xdroid project with beagle-eclair branch. LIke beagle-donut, I can use USB mouse, keyboard, mount a SD sdcard, use USB networking, and then I turn Bluetooth on. It's very easy to set up the working environment with 0xdroid.

Check Bluetooth application source code and install it in Beagleboard

cd packages/apps
git clone git://android.git.kernel.org/platform/packages/apps/Bluetooth.git
cd Bluetooth
git checkout -b eclair remotes/origin/eclair
git pull
source ../../../build/envsetup.sh
mm
adb install ../../../out/target/product/beagleboard/system/app/Bluetooth.apk


Trace related log
When we saw the log like below, it means it provides OPP service in RFCOMM channel 12 and PBAP service in RFCOMM channel 19.

I/bluedroid( 736): Starting hciattach daemon
I/bluedroid( 736): Starting bluetoothd deamon

I/bluetooth_ScoSocket.cpp( 797): Listening SCO socket...
V/BtOpp Service( 933): Service onCreate

V/BtOpp Service( 933): Starting RfcommListener in 9 seconds
V/BtOpp Service( 933): Service onStartCommand

V/BluetoothPbapService( 933): Pbap Service onCreate
V/BluetoothPbapService( 933): Starting PBAP service
V/BluetoothPbapService( 933): Pbap Service onStartCommand

D/BluetoothService( 736): Registering hfag record
D/BluetoothService( 736): Registering opush record
D/BluetoothService( 736): Registering pbap record

V/BluetoothPbapService( 933): Handler(): got msg=1
V/BluetoothPbapService( 933): Pbap Service startRfcommSocketListener
V/BluetoothPbapService( 933): Pbap Service initSocket
V/BluetoothPbapService( 933): Succeed to create listening socket on channel 19

V/BtOpp Service( 933): start RfcommListener
V/BtOpp Service( 933): RfcommListener started
I/BtOppRfcommListener( 933): Accept thread started on channel 12


Receiving and sending out data via Bluetooth

Currently, it only accepts few media types, like image, video, audio, text/plain and text/html and it should have the extension name. It cannot accept vcard and vcalendar. But we can modify few lines in 'Bluetooth/src/com/android/bluetooth/opp/Constants.java ', then it can store vcard files. One more problem, there is no matched application can view *.vcf file. I guess I can reference with previous beagle-donut code to fix it. All incoming files are stored in /sdcard/bluetooth folder. Also, there is a db file to record all Bluetooth application actions.

# cd /sdcard/bluetooth
# ls
08042009068.jpg
08042009068-1.jpg

# cd /data/data/com.android.bluetooth/databases
# ls
btopp.db
# sqlite3 btopp.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> .tables
android_metadata btopp
sqlite> select * from btopp;
1||08042009068.jpg||image/jpeg|1|00:18:C5:42:18:78|1|1|493|394450||946685154325|0
2|content://media/external/images/media/1|08042009068.jpg|/sdcard/bluetooth/08042009068.jpg|image/jpeg|1|00:18:C5:42:18:78|1|1|200|394450|394450|946685200379|1
3||olv.vcf|/sdcard/bluetooth/olv.vcf|text/x-vcard|1|00:18:C5:42:18:78|1|1|200|68|68|946685305125|2
4|file:///sdcard/bluetooth/08042009068.jpg|08042009068.jpg||image/jpeg|0|00:18:C5:42:18:78|1|2|200|394450|394450|946685368037|0
5||btopp_vcard.vcf|/sdcard/bluetooth/btopp_vcard.vcf|text/x-vcard|1|00:22:A5:B8:AD:65|1|1|496|168||946685701894|0
6||btopp_vcard.vcf|/sdcard/bluetooth/btopp_vcard.vcf|text/x-vcard|1|00:22:A5:B8:AD:65|1|1|200|168|168|946685806848|2
7||08042009068.jpg||image/jpeg|1|00:18:C5:42:18:78|1|4|490|394450||946698435289|0
8||08042009068.jpg||image/jpeg|1|00:18:C5:42:18:78|1|4|490|394450||946698501841|0
9|content://media/external/images/media/1|08042009068.jpg|/sdcard/bluetooth/08042009068.jpg|image/jpeg|1|00:18:C5:42:18:78|1|1|200|394450|394450|946698554454|1
10|content://media/external/images/media/2|08042009068-1.jpg|/sdcard/bluetooth/08042009068-1.jpg|image/jpeg|1|00:18:C5:42:18:78|1|1|200|394450|394450|946698717592|1
11|file:///sdcard/bluetooth/08042009068-1.jpg|08042009068-1.jpg||image/jpeg|0|00:22:A5:B8:AD:65|1|2|495|394450|0|946698901473|0
12|content://media/external/images/media/2|08042009068-1.jpg||image/jpeg|0|00:18:C5:42:18:78|1|2|200|394450|394450|946699019695|0


Screenshots from beagle-eclair

* Turn Bluetooth On
* Pair with Nokia N73 phone
* Receive an image from N73 to Beagle board via BT
* Send an image from Beagle board to N73 via BT

Monday, January 25, 2010

Automated test in Android by Sikuli

There is a very friendly and pretty cool project called 'Sikuli' and the authors are from Taiwan too. What is Sikuli? I copy these texts from its website. Sikuli is a visual technology to search and automate graphical user interfaces (GUI) using images (screenshots). The first release of Sikuli contains Sikuli Script, a visual scripting API for Jython, and Sikuli IDE, an integrated development environment for writing visual scripts with screenshots easily. Sikuli Script automates anything you see on the screen without internal API's support. You can programmatically control a web page, a desktop application running on Windows/Linux/Mac OS X, or even an iphone application running in an emulator.

How I use Sikuli for Android? Since we can catch things from screenshots, it means we can run Android emulator in my Ubuntu machine. Furthermore, I can run a vnc server in Android device, then run a vnc viewer in Ubuntu. Therefore, I can see Android HOME screen in my Desktop. What it can do for me? ha, it can run automated tests and then we don't need SQA to verify phone basic functionalities. Like detect GSM signal, dial out a phone call, enable Bluetooth, connect to WiFi hotspot....etc.

Launch Sikuli IDE editor in Ubuntu

wget http://sikuli.org/dl/Sikuli-IDE-linux-20100104.zip
unzip Sikuli-IDE-linux-20100104.zip
sh Sikuli-IDE/sikuli-ide.sh



Launch Android in Ubuntu

There is another tool "androidscreencast" I am using for this automated test. It can allow me to control my Android Dev phone remotely. We can have keyboard and mouse input! This is very important for Sikuli scripts, coz I can say "Click" something or "type" something. :)

wget http://androidscreencast.googlecode.com/svn/trunk/AndroidScreencast/dist/androidscreencast.jnlp
javaws androidscreencast.jnlp



Let's write some examples! Please check these draft videos!



Build Sikuli in Ubuntu 9.10 (64 bit)

1. download the source code (you'll need to install bzr, if you don't have it)
> bzr branch lp:sikuli

2. check java version (use java-6-sun)
erin@midnight:~/code/sikuli$ file /etc/alternatives/java
/etc/alternatives/java: symbolic link to `/usr/lib/jvm/java-6-sun/jre/bin/java'
erin@midnight:~/code/sikuli$ file /etc/alternatives/javac
/etc/alternatives/javac: symbolic link to `/usr/lib/jvm/java-1.5.0-sun/bin/javac'

3. install some libraries
tesseract-ocr - Command line OCR tool
tesseract-ocr-dev - Development files for the tesseract command line OCR tool
maven2 - Java software project management and comprehension tool
libcv1 - computer vision library
libcvaux1 - computer vision extension library
libhighgui1 - computer vision GUI library

4. build code
>cd sikuli-script
>make

g++ ScreenMatchProxy.o ocr-matcher.o template-matcher.o myocr.o screendiff.o -o ../../../target/lib/libScreenMatchProxy.so `pkg-config --libs opencv` -shared -L/usr/local/lib -I/usr/lib/jvm/java-6-sun/lib -ltesseract_full -ltiff
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.4.1/../../../../lib/libtesseract_full.a(libtesseract_full.o): relocation R_X86_64_32 against `BLOCK_zapper(ELIST_LINK*)' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/4.4.1/../../../../lib/libtesseract_full.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make[1]: *** [../../../target/lib/libScreenMatchProxy.so] Error 1

how i solved: i removed -ltesseract_full, then rebuilt it!
>cd src/main/native/
>g++ ScreenMatchProxy.o ocr-matcher.o template-matcher.o myocr.o screendiff.o -o ../../../target/lib/libScreenMatchProxy.so `pkg-config --libs opencv` -shared -L/usr/local/lib -I/usr/lib/jvm/java-6-sun/lib -ltiff

>make install-jar (it would build sikuli-script.jar, that is what we need!)
>make release (it would build for all platforms, then zip to a file.)

erin@midnight:~/project/sikuli/sikuli-script$ make release
mkdir -p target/sikuli-script
rm -rf target/sikuli-script/*
cp target/sikuli-script.{bat,sh} target/sikuli-script
cp: cannot stat `target/sikuli-script.{bat,sh}': No such file or directory
make: *** [release] Error 1

how i solved: modify two lines in sikuli-script/Makefile and mkdir ../release
cp target/sikuli-script.bat target/sikuli-script.sh $(RELEASE_TMP_PATH)
cp -r $(LIB_PATH)/win32 $(LIB_PATH)/tmplib $(RELEASE_TMP_PATH)

Done! you will find a zip file 'Sikuli-Script-all-20100128.zip' in release directory.

>cd sikuli-ide
>make install-jar
>make major-release

Done! you will find a zip file 'Sikuli-IDE-linux-20100128.zip' in release directory. This one is like we download from Sikuli website for linux version.