├── README.md ├── android-btsim-application ├── AndroidManifest.xml ├── bin │ ├── BluetoothEmulator.apk │ ├── classes.dex │ ├── dk │ │ └── itu │ │ │ └── android │ │ │ ├── bluetooth │ │ │ ├── BluetoothAdapter$1.class │ │ │ ├── BluetoothAdapter.class │ │ │ ├── BluetoothClass$Device$Major.class │ │ │ ├── BluetoothClass$Device.class │ │ │ ├── BluetoothClass$Service.class │ │ │ ├── BluetoothClass.class │ │ │ ├── BluetoothDevice.class │ │ │ ├── BluetoothServerSocket$1.class │ │ │ ├── BluetoothServerSocket.class │ │ │ └── BluetoothSocket.class │ │ │ └── btemu │ │ │ ├── BTEnableControl.class │ │ │ ├── Main$1.class │ │ │ ├── Main$10$1.class │ │ │ ├── Main$10.class │ │ │ ├── Main$2.class │ │ │ ├── Main$3.class │ │ │ ├── Main$4.class │ │ │ ├── Main$5.class │ │ │ ├── Main$6.class │ │ │ ├── Main$7.class │ │ │ ├── Main$8.class │ │ │ ├── Main$9.class │ │ │ ├── Main.class │ │ │ ├── R$attr.class │ │ │ ├── R$drawable.class │ │ │ ├── R$id.class │ │ │ ├── R$layout.class │ │ │ ├── R$string.class │ │ │ ├── R.class │ │ │ └── service │ │ │ ├── BTEmulator$1.class │ │ │ ├── BTEmulator.class │ │ │ ├── BTService.class │ │ │ └── cmd │ │ │ ├── BaseCommand.class │ │ │ ├── CommandType.class │ │ │ ├── Discovery$WithDevices.class │ │ │ ├── Discovery.class │ │ │ ├── Join.class │ │ │ ├── Leave.class │ │ │ ├── ModifyService.class │ │ │ └── NoParamsBaseCommand.class │ └── resources.ap_ ├── default.properties ├── dist-shared │ └── btsim.jar ├── dist │ └── BluetoothEmulator.apk ├── gen │ └── dk │ │ └── itu │ │ └── android │ │ └── btemu │ │ └── R.java ├── res │ ├── drawable-hdpi │ │ └── icon.png │ ├── drawable-ldpi │ │ └── icon.png │ ├── drawable-mdpi │ │ └── icon.png │ ├── layout │ │ ├── ctrl.xml │ │ ├── main.xml │ │ └── row.xml │ └── values │ │ └── strings.xml ├── src-sysactivities │ └── dk │ │ └── itu │ │ └── android │ │ └── btemu │ │ └── BTEnableControl.java ├── src-testapp │ └── dk │ │ └── itu │ │ └── android │ │ └── btemu │ │ └── Main.java └── src │ └── dk │ └── itu │ └── android │ ├── bluetooth │ ├── BluetoothAdapter.java │ ├── BluetoothClass.java │ ├── BluetoothDevice.java │ ├── BluetoothServerSocket.java │ └── BluetoothSocket.java │ └── btemu │ └── service │ ├── BTEmulator.java │ ├── BTService.java │ └── cmd │ ├── BaseCommand.java │ ├── CommandType.java │ ├── Discovery.java │ ├── Join.java │ ├── Leave.java │ ├── ModifyService.java │ └── NoParamsBaseCommand.java └── btsim-server ├── bin └── dk │ └── itu │ └── btemu │ ├── BTMacForwardingsChecker$DeviceAddr.class │ ├── BTMacForwardingsChecker.class │ ├── CommandParser.class │ ├── Server$1.class │ ├── Server.class │ ├── State.class │ ├── cmd │ ├── BaseCommand$Param.class │ ├── BaseCommand.class │ ├── CommandType.class │ ├── Discovery.class │ ├── Join.class │ ├── Leave.class │ └── ModifyService.class │ ├── state │ ├── Device.class │ └── Service.class │ └── test │ └── VarTest.class ├── client-src └── dk │ └── itu │ └── btemu │ └── client │ └── BtEmuClient.java ├── dist └── btsimserver.jar ├── src └── dk │ └── itu │ └── btemu │ ├── BTMacForwardingsChecker.java │ ├── CommandParser.java │ ├── Server.java │ ├── State.java │ ├── cmd │ ├── BaseCommand.java │ ├── CommandType.java │ ├── Discovery.java │ ├── Join.java │ ├── Leave.java │ └── ModifyService.java │ └── state │ ├── Device.java │ └── Service.java └── test └── dk └── itu └── btemu └── test └── VarTest.java /README.md: -------------------------------------------------------------------------------- 1 | # Android Bluetooth Simulator 2 | 3 | ## What is it 4 | 5 | It's a tcp-based implementation of part of the android bluetooth API. 6 | As for now, you can communicate between different emulators using the RFComm protocol, you can start a discovery phase and enable/disable the bluetooth. 7 | 8 | What you need to do in order to use the simulator instead of the android API, is to change the import from `android.bluetooth` to `dk.itu.android.bluetooth` (and also add the `INTERNET` permission in the android manifest file). 9 | 10 | There is a slight modification to the code, in order to use the simulator: 11 | 12 | - call `BluetoothAdapter.SetContext(this);` at some point (the `onCreate` method is fine) in your activity/service. 13 | 14 | ## How do I use it? 15 | 16 | You will have to follow some steps: 17 | 18 | - download everything in this repository 19 | - compile and install into at least 2 android emulators the *android-bt-simulator* application 20 | - a precompiled version of the application is provided in the *dist* directory 21 | - there are 3 source directories, `src`, `src-sysactivities` and `src-testapp`. The application need all of them, but for the library jar you just need to compile the main one (`src`). The jar library is provided as convenience in the `dist-shared` directory 22 | - compile the *btsim-server* and run it. 23 | - there is an already precompiled jar in *dist*, execute `java -jar btsimserver.jar --help` to see some options (if you don't have the `adb` command in your path, you will need to set the `adb.path` variable) 24 | 25 | You need to install the application because it will handle the *system activities* of the bluetooth, like switching on/off the radio and start a discovery. 26 | 27 | Then you can create a new android project. 28 | My preferred workflow, at this point, is: 29 | 30 | - add the necessary permissions for the bluetooth AND for internet access (required by the bt simulator). 31 | - add the *btsim.jar* to the libraries of the project 32 | - add the call to `BluetoothAdapter.SetContext(this);` in the `onCreate` method of the activity 33 | - start using the bluetooth API, importing the `dk.itu.android.bluetooth` version 34 | - set up two launch configurations for the project (one for each android emulator) 35 | 36 | Then, depending on your needs, when you want to deploy the application on an actual device, you will need to delete or comment the `SetContext` call (as this will not compile, since it is not part of the android bluetooth api, but just a custom call for the simulator) and delete and re-import all the bluetooth stuff (this time using the `android.bluetooth` classes). 37 | 38 | I hope this will be useful for somebody, I know that it implements just a subset of the API and it is not possible to put into play different devices than the emulators themselves, but until we got something in the android emulator itself, this is what we got :D 39 | 40 | ## Adding dummy devices 41 | 42 | You can add dummy devices to the server, so that you can check if the discovery phase works. This involves communicating directly with the bluetooth emulator server, which accept text-based command. 43 | 44 | First of all, fire up a terminal and telnet to localhost, port 8199: 45 | 46 | telnet localhost 8199 47 | 48 | when the terminal prompt, use the following syntax: 49 | 50 | 0]tcp.address=10.0.2.2¬.android.emulator=true&bt.address=
&device.name=] 51 | 52 | e.g. : 53 | 54 | 0]tcp.address=10.0.2.2¬.android.emulator=true&bt.address=00:11:22:AA:BB:CC&device.name=Dummy1] 55 | 56 | In general, the bluetooth emulator server accepts commands on the form: 57 | 58 | ]=&...] 59 | 60 | Another useful command is the discovery one, if you want to know which devices are listed in the server, telnet and enter: 61 | 62 | 2]] 63 | 64 | then the list of the devices and relative registered services will appear. -------------------------------------------------------------------------------- /android-btsim-application/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | -------------------------------------------------------------------------------- /android-btsim-application/bin/BluetoothEmulator.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/BluetoothEmulator.apk -------------------------------------------------------------------------------- /android-btsim-application/bin/classes.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/classes.dex -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothAdapter$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothAdapter$1.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothAdapter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothAdapter.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass$Device$Major.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass$Device$Major.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass$Device.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass$Device.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass$Service.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass$Service.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothClass.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothDevice.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothDevice.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothServerSocket$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothServerSocket$1.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothServerSocket.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothServerSocket.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothSocket.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/bluetooth/BluetoothSocket.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/BTEnableControl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/BTEnableControl.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$1.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$10$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$10$1.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$10.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$10.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$2.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$3.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$4.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$4.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$5.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$5.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$6.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$6.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$7.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$7.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$8.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$8.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main$9.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main$9.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/Main.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/R$attr.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/R$attr.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/R$drawable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/R$drawable.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/R$id.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/R$id.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/R$layout.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/R$layout.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/R$string.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/R$string.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/R.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/R.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/BTEmulator$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/BTEmulator$1.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/BTEmulator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/BTEmulator.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/BTService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/BTService.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/BaseCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/BaseCommand.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/CommandType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/CommandType.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Discovery$WithDevices.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Discovery$WithDevices.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Discovery.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Discovery.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Join.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Join.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Leave.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/Leave.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/ModifyService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/ModifyService.class -------------------------------------------------------------------------------- /android-btsim-application/bin/dk/itu/android/btemu/service/cmd/NoParamsBaseCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/dk/itu/android/btemu/service/cmd/NoParamsBaseCommand.class -------------------------------------------------------------------------------- /android-btsim-application/bin/resources.ap_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/bin/resources.ap_ -------------------------------------------------------------------------------- /android-btsim-application/default.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "build.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Indicates whether an apk should be generated for each density. 11 | split.density=false 12 | # Project target. 13 | target=android-5 14 | -------------------------------------------------------------------------------- /android-btsim-application/dist-shared/btsim.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/dist-shared/btsim.jar -------------------------------------------------------------------------------- /android-btsim-application/dist/BluetoothEmulator.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/dist/BluetoothEmulator.apk -------------------------------------------------------------------------------- /android-btsim-application/gen/dk/itu/android/btemu/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package dk.itu.android.btemu; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static final int icon=0x7f020000; 15 | } 16 | public static final class id { 17 | public static final int Devices=0x7f050003; 18 | public static final int Disable=0x7f050001; 19 | public static final int Discovery=0x7f050002; 20 | public static final int EchoResponse=0x7f050006; 21 | public static final int Enable=0x7f050000; 22 | public static final int StartClient=0x7f050005; 23 | public static final int StartServer=0x7f050004; 24 | public static final int list_value=0x7f050007; 25 | } 26 | public static final class layout { 27 | public static final int btenablecontrol=0x7f030000; 28 | public static final int main=0x7f030001; 29 | public static final int row=0x7f030002; 30 | } 31 | public static final class string { 32 | public static final int app_name=0x7f040001; 33 | public static final int btctrl=0x7f040002; 34 | public static final int btctrl_title=0x7f040003; 35 | public static final int hello=0x7f040000; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /android-btsim-application/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /android-btsim-application/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /android-btsim-application/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/android-btsim-application/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /android-btsim-application/res/layout/ctrl.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | -------------------------------------------------------------------------------- /android-btsim-application/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /android-btsim-application/res/layout/row.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /android-btsim-application/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello World, Main! 4 | BluetoothEmulator 5 | BluetoothEmulatorControl 6 | BluetoothEmulatorControl 7 | 8 | -------------------------------------------------------------------------------- /android-btsim-application/src-sysactivities/dk/itu/android/btemu/BTEnableControl.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu; 2 | 3 | import dk.itu.android.bluetooth.BluetoothAdapter; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | 9 | public class BTEnableControl extends Activity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.ctrl); 15 | 16 | BluetoothAdapter.SetContext(this); 17 | } 18 | 19 | @Override 20 | protected void onStart() { 21 | super.onStart(); 22 | Intent started = getIntent(); 23 | Log.i("BTCTRL", "start with action: "+started.getAction()); 24 | if(started.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) { 25 | //start 26 | BluetoothAdapter.getDefaultAdapter().enable(); 27 | setResult(RESULT_OK); 28 | 29 | } else if(started.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) { 30 | //enabled discoverable 31 | setResult(RESULT_OK); 32 | } 33 | try { 34 | Thread.sleep(500); 35 | } catch (InterruptedException e) { 36 | // TODO Auto-generated catch block 37 | e.printStackTrace(); 38 | } 39 | finish(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /android-btsim-application/src-testapp/dk/itu/android/btemu/Main.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.UUID; 11 | 12 | import android.app.Activity; 13 | import android.content.BroadcastReceiver; 14 | import android.content.Context; 15 | import android.content.Intent; 16 | import android.content.IntentFilter; 17 | import android.os.Bundle; 18 | import android.util.Log; 19 | import android.view.View; 20 | import android.widget.AdapterView; 21 | import android.widget.Button; 22 | import android.widget.ListView; 23 | import android.widget.SimpleAdapter; 24 | import android.widget.TextView; 25 | import android.widget.AdapterView.OnItemClickListener; 26 | import dk.itu.android.bluetooth.BluetoothAdapter; 27 | import dk.itu.android.bluetooth.BluetoothDevice; 28 | import dk.itu.android.bluetooth.BluetoothServerSocket; 29 | import dk.itu.android.bluetooth.BluetoothSocket; 30 | 31 | public class Main extends Activity { 32 | final BroadcastReceiver mReceiver = new BroadcastReceiver() { 33 | @Override 34 | public void onReceive(Context context, Intent intent) { 35 | String action = intent.getAction(); 36 | if(BluetoothDevice.ACTION_FOUND.equals(action)) { 37 | addDevice( (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) ); 38 | } 39 | } 40 | }; 41 | static final String ITEM_KEY = "key"; 42 | ListView devices; 43 | BluetoothAdapter bta; 44 | @Override 45 | public void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.main); 48 | BluetoothAdapter.SetContext(this); 49 | bta = BluetoothAdapter.getDefaultAdapter(); 50 | IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 51 | registerReceiver(mReceiver, filter); 52 | 53 | Button enableBtn = (Button)findViewById(R.id.Enable); 54 | Button disableBtn = (Button)findViewById(R.id.Disable); 55 | Button discoveryBtn = (Button)findViewById(R.id.Discovery); 56 | 57 | Button serverBtn = (Button)findViewById(R.id.StartServer); 58 | Button clientBtn = (Button)findViewById(R.id.StartClient); 59 | serverBtn.setOnClickListener(new View.OnClickListener() { 60 | @Override 61 | public void onClick(View v) { 62 | startServer(); 63 | } 64 | }); 65 | clientBtn.setOnClickListener(new View.OnClickListener() { 66 | @Override 67 | public void onClick(View v) { 68 | startClient(); 69 | } 70 | }); 71 | 72 | devices = (ListView)findViewById(R.id.Devices); 73 | // devices.setOnClickListener(new View.OnClickListener() { 74 | // @Override 75 | // public void onClick(View v) { 76 | // } 77 | // }); 78 | devices.setOnItemClickListener(new OnItemClickListener() { 79 | @Override 80 | public void onItemClick(AdapterView arg0, View arg1, int position, 81 | long arg3) { 82 | Log.i("BTEMU_TEST", "selecting remote device at position: "+position); 83 | other = (BluetoothDevice)list.get(position).get("DEVICE"); 84 | Log.i("BTEMU_TEST", "other device is: "+other); 85 | } 86 | }); 87 | 88 | enableBtn.setOnClickListener(new View.OnClickListener() { 89 | @Override 90 | public void onClick(View v) { 91 | enableBT(); 92 | } 93 | }); 94 | disableBtn.setOnClickListener(new View.OnClickListener() { 95 | @Override 96 | public void onClick(View v) { 97 | disableBT(); 98 | } 99 | }); 100 | discoveryBtn.setOnClickListener(new View.OnClickListener() { 101 | @Override 102 | public void onClick(View v) { 103 | startDiscovery(); 104 | } 105 | }); 106 | 107 | adapter = new SimpleAdapter(this, list, R.layout.row, new String[]{ITEM_KEY}, new int[]{R.id.list_value}); 108 | this.devices.setAdapter(adapter); 109 | } 110 | SimpleAdapter adapter; 111 | List> list = new ArrayList>(); 112 | 113 | static int REQUEST_ENABLE_BT = 1234; 114 | private void enableBT() { 115 | Log.i("BTEMU", "enabling btemulator..."); 116 | // bta.enable(); 117 | if(!bta.isEnabled()) { 118 | Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 119 | startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); 120 | } 121 | } 122 | @Override 123 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 124 | if(requestCode == REQUEST_ENABLE_BT) { 125 | //just received the results for bt enabling 126 | if(resultCode == RESULT_OK) { 127 | Log.i("BTEMU", "bluetooth was enabled!"); 128 | } 129 | } 130 | } 131 | private void disableBT() { 132 | Log.i("BTEMU", "disabling btemulator..."); 133 | bta.disable(); 134 | } 135 | private void startDiscovery() { 136 | Log.i("BTEMU", "starting discovery..."); 137 | clearDevices(); 138 | bta.startDiscovery(); 139 | } 140 | 141 | private void clearDevices(){ 142 | Log.i("BTEMU", "clearing device list"); 143 | list.clear(); 144 | adapter.notifyDataSetChanged(); 145 | } 146 | BluetoothDevice other = null; 147 | @SuppressWarnings("serial") 148 | private void addDevice(final BluetoothDevice d) { 149 | // other = d; 150 | Log.i("TESTACTIVITY", "got device! " + d.getAddress()); 151 | Map item = new HashMap(){{ 152 | put(ITEM_KEY, d.getName() + " - " + d.getAddress()); 153 | put("DEVICE", d); 154 | }}; 155 | list.add(item); 156 | adapter.notifyDataSetChanged(); 157 | } 158 | 159 | private void startServer() { 160 | new Thread(new Runnable(){ 161 | @Override 162 | public void run() { 163 | try { 164 | Log.i("BTTEST", "accepting bt connection..."); 165 | BluetoothServerSocket server = BluetoothAdapter 166 | .getDefaultAdapter() 167 | .listenUsingRfcommWithServiceRecord("dk.echo", 168 | UUID.fromString("419bbc68-c365-4c5e-8793-5ebff85b908c")); 169 | BluetoothSocket client = server.accept(); 170 | String line = new BufferedReader(new InputStreamReader(client.getInputStream())).readLine(); 171 | Log.i("BTTEST", "read: "+line); 172 | client.getOutputStream().write( ("echoed: "+line).getBytes("UTF-8") ); 173 | Log.i("BTTEST", "replying"); 174 | client.close(); 175 | server.close(); 176 | } catch (Exception e) { 177 | Log.e("BTTEST", "error in echo server", e); 178 | } 179 | } 180 | }).start(); 181 | } 182 | String resp; 183 | private void setResp(String r){resp=r;} 184 | private void startClient() { 185 | Thread t =new Thread(new Runnable(){ 186 | @Override 187 | public void run() { 188 | try { 189 | Log.i("BTTEST_CLIENT", "creating socket.."); 190 | BluetoothSocket s = other.createRfcommSocketToServiceRecord(UUID.fromString("419bbc68-c365-4c5e-8793-5ebff85b908c")); 191 | Log.i("BTTEST_CLIENT", "socket created"); 192 | s.connect(); 193 | Log.i("BTTEST_CLIENT", "socket connected"); 194 | s.getOutputStream().write("foo bar? baaaz\r\n".getBytes("UTF-8")); 195 | s.getOutputStream().flush(); 196 | Log.i("BTTEST_CLIENT", "message wrote"); 197 | String reply = new BufferedReader(new InputStreamReader(s.getInputStream())).readLine(); 198 | Log.i("BTTEST_CLIENT", "reply: "+reply); 199 | setResp(reply); 200 | s.close(); 201 | runOnUiThread(new Runnable(){ 202 | @Override 203 | public void run() { 204 | ((TextView)findViewById(R.id.EchoResponse)).setText(resp); 205 | } 206 | }); 207 | // synchronized(lock) { 208 | // lock.notify(); 209 | // } 210 | } catch (IOException e) { 211 | // TODO Auto-generated catch block 212 | e.printStackTrace(); 213 | Log.e("BTTEST", "error in echo client", e); 214 | } 215 | } 216 | }); 217 | t.start(); 218 | // try { 219 | // 220 | // } catch (InterruptedException e) { 221 | // // TODO Auto-generated catch block 222 | // e.printStackTrace(); 223 | // } 224 | // synchronized(lock) { 225 | // try { 226 | // lock.wait(); 227 | // } catch (InterruptedException e) { 228 | // // TODO Auto-generated catch block 229 | // e.printStackTrace(); 230 | // } 231 | // 232 | // } 233 | } 234 | } -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/bluetooth/BluetoothAdapter.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.bluetooth; 2 | 3 | import java.io.FileOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStreamWriter; 8 | import java.io.Reader; 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Random; 12 | import java.util.Set; 13 | import java.util.UUID; 14 | 15 | import android.content.Context; 16 | import android.content.Intent; 17 | import android.net.Uri; 18 | import android.util.Log; 19 | import dk.itu.android.btemu.service.BTEmulator; 20 | import dk.itu.android.btemu.service.cmd.Discovery; 21 | 22 | public class BluetoothAdapter { 23 | public static final String ACTION_DISCOVERY_FINISHED = "dk.android.bluetooth.adapter.action.DISCOVERY_FINISHED"; 24 | public static final String ACTION_DISCOVERY_STARTED = "dk.android.bluetooth.adapter.action.DISCOVERY_STARTED"; 25 | /** 26 | * Contains EXTRA_LOCAL_NAME with the new name 27 | */ 28 | public static final String ACTION_LOCAL_NAME_CHANGED = "dk.android.bluetooth.adapter.action.LOCAL_NAME_CHANGED"; 29 | /** 30 | * Activity Action: Show a system activity that requests discoverable mode. This activity will also request the user to turn on Bluetooth if it is not currently enabled. 31 | Discoverable mode is equivalent to SCAN_MODE_CONNECTABLE_DISCOVERABLE. It allows remote devices to see this Bluetooth adapter when they perform a discovery. 32 | For privacy, Android is not discoverable by default. 33 | The sender of this Intent can optionally use extra field EXTRA_DISCOVERABLE_DURATION to request the duration of discoverability. Currently the default duration is 120 seconds, and maximum duration is capped at 300 seconds for each request. 34 | Notification of the result of this activity is posted using the onActivityResult(int, int, Intent) callback. The resultCode will be the duration (in seconds) of discoverability or RESULT_CANCELED if the user rejected discoverability or an error has occurred. 35 | Applications can also listen for ACTION_SCAN_MODE_CHANGED for global notification whenever the scan mode changes. For example, an application can be notified when the device has ended discoverability. 36 | Requires BLUETOOTH 37 | */ 38 | public static final String ACTION_REQUEST_DISCOVERABLE = "dk.android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"; 39 | /** 40 | * Activity Action: Show a system activity that allows the user to turn on Bluetooth. 41 | This system activity will return once Bluetooth has completed turning on, or the user has decided not to turn Bluetooth on. 42 | Notification of the result of this activity is posted using the onActivityResult(int, int, Intent) callback. The resultCode will be RESULT_OK if Bluetooth has been turned on or RESULT_CANCELED if the user has rejected the request or an error has occurred. 43 | Applications can also listen for ACTION_STATE_CHANGED for global notification whenever Bluetooth is turned on or off. 44 | Requires BLUETOOTH 45 | */ 46 | public static final String ACTION_REQUEST_ENABLE = "dk.android.bluetooth.adapter.action.REQUEST_ENABLE"; 47 | /** 48 | * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter has changed. 49 | Always contains the extra fields EXTRA_SCAN_MODE and EXTRA_PREVIOUS_SCAN_MODE containing the new and old scan modes respectively. 50 | Requires BLUETOOTH 51 | */ 52 | public static final String ACTION_SCAN_MODE_CHANGED = "dk.android.bluetooth.adapter.action.SCAN_MODE_CHANGED"; 53 | /** 54 | * Broadcast Action: The state of the local Bluetooth adapter has been changed. 55 | For example, Bluetooth has been turned on or off. 56 | Always contains the extra fields EXTRA_STATE and EXTRA_PREVIOUS_STATE containing the new and old states respectively. 57 | Requires BLUETOOTH to receive. 58 | */ 59 | public static final String ACTION_STATE_CHANGED = "dk.android.bluetooth.adapter.action.STATE_CHANGED"; 60 | /** 61 | * Sentinel error value for this class. Guaranteed to not equal any other integer constant in this class. Provided as a convenience for functions that require a sentinel error value, for example: 62 | Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) 63 | */ 64 | public static final int ERROR = -2147483648; 65 | /** 66 | * Used as an optional int extra field in ACTION_REQUEST_DISCOVERABLE intents to request a specific duration for discoverability in seconds. The current default is 120 seconds, and requests over 300 seconds will be capped. These values could change. 67 | */ 68 | public static final String EXTRA_DISCOVERABLE_DURATION = "dk.android.bluetooth.adapter.extra.DISCOVERABLE_DURATION"; 69 | /** 70 | * Used as a String extra field in ACTION_LOCAL_NAME_CHANGED intents to request the local Bluetooth name. 71 | */ 72 | public static final String EXTRA_LOCAL_NAME = "dk.android.bluetooth.adapter.extra.LOCAL_NAME"; 73 | /** 74 | * Used as an int extra field in ACTION_SCAN_MODE_CHANGED intents to request the previous scan mode. Possible values are: SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE, 75 | */ 76 | public static final String EXTRA_PREVIOUS_SCAN_MODE = "dk.android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE"; 77 | /** 78 | * Used as an int extra field in ACTION_STATE_CHANGED intents to request the previous power state. Possible values are: STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, 79 | */ 80 | public static final String EXTRA_PREVIOUS_STATE = "dk.android.bluetooth.adapter.extra.PREVIOUS_STATE"; 81 | /** 82 | * Used as an int extra field in ACTION_SCAN_MODE_CHANGED intents to request the current scan mode. Possible values are: SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE, 83 | */ 84 | public static final String EXTRA_SCAN_MODE = "dk.android.bluetooth.adapter.extra.SCAN_MODE"; 85 | /** 86 | * Used as an int extra field in ACTION_STATE_CHANGED intents to request the current power state. Possible values are: STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, 87 | */ 88 | public static final String EXTRA_STATE = "dk.android.bluetooth.adapter.extra.STATE"; 89 | 90 | public static final int SCAN_MODE_CONNECTABLE = 21; 91 | public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; 92 | public static final int SCAN_MODE_NONE = 20; 93 | public static final int STATE_OFF = 10; 94 | public static final int STATE_ON = 12; 95 | public static final int STATE_TURNING_OFF = 13; 96 | public static final int STATE_TURNING_ON = 11; 97 | 98 | static final BluetoothAdapter def = new BluetoothAdapter(); 99 | 100 | static Context context = null; 101 | public static void SetContext(Context c) { 102 | if(context != null) return; 103 | context=c; 104 | try { 105 | InputStream is = c.getContentResolver().openInputStream(Uri.parse("file:///data/data/dk.itu.android.btemu/files/BTADDR.TXT")); 106 | Reader reader = new InputStreamReader(is); 107 | char[] buf = new char[100]; 108 | int read = reader.read(buf); 109 | String addr = new String(buf,0,read); 110 | def.addr = addr; 111 | Log.i("BTADAPTEREMULATOR", "read address: "+def.addr); 112 | return; 113 | } catch(Exception e) { 114 | Log.i("BTADAPTEREMULATOR", "file was not found", e); 115 | } 116 | try { 117 | // for(String name : c.fileList()){ 118 | // if(name.equals("BTADDR.TXT")) { 119 | // Log.i("BTADAPTEREMULATOR", "btaddress found"); 120 | // FileInputStream fis = c.openFileInput("BTADDR.TXT"); 121 | // return; 122 | // } 123 | // } 124 | FileOutputStream fos = c.openFileOutput("BTADDR.TXT", Context.MODE_WORLD_READABLE); 125 | OutputStreamWriter outw = new OutputStreamWriter(fos); 126 | outw.write(def.getAddress()); 127 | outw.flush(); 128 | outw.close(); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | Log.e("BTADAPTEREMULATOR", "cannot write BTADDR.TXT file!", e); 132 | } 133 | } 134 | 135 | String name = "local"; 136 | String addr = null; 137 | boolean enabled = false; 138 | boolean discovering = false; 139 | Set bonded = new HashSet(); 140 | int scanMode = android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 141 | 142 | public static boolean checkBluetoothAddress(String addr) { 143 | return android.bluetooth.BluetoothAdapter.checkBluetoothAddress(addr); 144 | } 145 | public static BluetoothAdapter getDefaultAdapter() { 146 | return def; 147 | } 148 | 149 | private BluetoothAdapter() { 150 | this.addr = getAddress(); 151 | this.emulator = new BTEmulator(); 152 | } 153 | 154 | public boolean cancelDiscovery() { 155 | return false; 156 | } 157 | public boolean disable(){ 158 | return setEnabled(false); 159 | } 160 | public boolean enable(){ 161 | return setEnabled(true); 162 | } 163 | public String getAddress(){ 164 | /** 165 | * TODO: get a decent random address! 166 | */ 167 | if(addr==null){addr=createRandomAddress();} 168 | return addr; 169 | } 170 | public Set getBondedDevices(){ 171 | Set out = null; 172 | synchronized(this.bonded) { 173 | out = new HashSet(bonded); 174 | } 175 | return out; 176 | } 177 | public String getName(){ 178 | return name; 179 | } 180 | public BluetoothDevice getRemoteDevice(String address) { 181 | if(!checkBluetoothAddress(address)) 182 | throw new IllegalArgumentException("wrong device address"); 183 | return emulator.lookupBT(address);//new BluetoothDevice(address); 184 | } 185 | public int getScanMode() { 186 | return scanMode; 187 | } 188 | public boolean isDiscovering() { 189 | return discovering; 190 | } 191 | public boolean isEnabled() { 192 | return enabled; 193 | } 194 | public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) 195 | throws IOException { 196 | 197 | //chhoose a random tcp port 198 | int port = choosePort(); 199 | 200 | BluetoothServerSocket out = new BluetoothServerSocket(emulator,uuid.toString(),port); 201 | 202 | // emulator.addService(uuid.toString(), port); 203 | 204 | return out; 205 | } 206 | public boolean setName(String name) { 207 | this.name = name; 208 | return true; 209 | } 210 | public boolean startDiscovery() { 211 | if(discovering) 212 | return false; 213 | 214 | discovering = true; 215 | Discovery.WithDevices wd = new Discovery.WithDevices() { 216 | @Override 217 | public void devices(List devices) { 218 | Intent intent = new Intent(ACTION_DISCOVERY_STARTED); 219 | context.sendBroadcast(intent); 220 | for(BluetoothDevice d : devices) { 221 | intent = new Intent(); 222 | intent.setAction(BluetoothDevice.ACTION_FOUND); 223 | intent.putExtra(BluetoothDevice.EXTRA_DEVICE, d); 224 | intent.putExtra(BluetoothDevice.EXTRA_CLASS, d.getBluetoothClass()); 225 | context.sendBroadcast(intent); 226 | } 227 | intent = new Intent(ACTION_DISCOVERY_FINISHED); 228 | context.sendBroadcast(intent); 229 | discovering = false; 230 | } 231 | }; 232 | emulator.asyncDiscovery(wd); 233 | return true; 234 | } 235 | 236 | 237 | 238 | 239 | ///////////////////////////// 240 | private BTEmulator emulator; 241 | private boolean setEnabled(boolean enable) { 242 | Log.d("BTADAPTEREMULATOR", "setEnabled->"+enable+", was->"+enabled); 243 | if(enable){// && !enabled) { 244 | Log.d("BTADAPTEREMULATOR", "joining..."); 245 | emulator.join(); 246 | 247 | } else if(/*enabled && */!enable) { 248 | Log.d("BTADAPTEREMULATOR", "leaving..."); 249 | emulator.leave(); 250 | } 251 | this.enabled = enable; 252 | return true; 253 | } 254 | private String createRandomAddress() { 255 | //sample: 00:11:22:AA:BB:CC 256 | StringBuffer sb = new StringBuffer(); 257 | Random r = new Random(); 258 | boolean f = true; 259 | for(int i=0;i<3;i++) { 260 | if(f){f=!f;}else{sb.append(":");} 261 | int n = 0; 262 | do { 263 | n = r.nextInt(99); 264 | } while(n<10); 265 | sb.append(n); 266 | } 267 | String chars = "ABCDEF"; 268 | for(int i=0;i<3;i++) { 269 | sb.append(":"); 270 | sb.append( chars.charAt( r.nextInt(6) ) ); 271 | sb.append( chars.charAt( r.nextInt(6) ) ); 272 | } 273 | 274 | return sb.toString(); 275 | } 276 | static int _curPort = 8123; 277 | private int choosePort() { 278 | _curPort++; 279 | return _curPort; 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/bluetooth/BluetoothClass.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.bluetooth; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | public class BluetoothClass implements Parcelable { 7 | 8 | public static Parcelable.Creator CREATOR = new Parcelable.Creator() { 9 | @Override 10 | public BluetoothClass createFromParcel(Parcel source) { 11 | BluetoothClass out = new BluetoothClass(); 12 | out.dClass = source.readInt(); 13 | out.mdClass = source.readInt(); 14 | out.services = source.createIntArray(); 15 | return out; 16 | } 17 | @Override 18 | public BluetoothClass[] newArray(int size) { 19 | return new BluetoothClass[size]; 20 | } 21 | }; 22 | 23 | public static class Device { 24 | public static class Major { 25 | public static final int PHONE = android.bluetooth.BluetoothClass.Device.Major.PHONE; 26 | public static final int COMPUTER = android.bluetooth.BluetoothClass.Device.Major.COMPUTER; 27 | } 28 | public static final int PHONE_SMART = android.bluetooth.BluetoothClass.Device.PHONE_SMART; 29 | } 30 | public static class Service { 31 | public static final int NETWORKING = android.bluetooth.BluetoothClass.Service.NETWORKING; 32 | } 33 | 34 | int dClass; 35 | int mdClass; 36 | int[] services; 37 | 38 | //needed by the serialization framework stuff 39 | /** 40 | * THIS IS NOT PART OF THE ANDROID BLUETOOTH FRAMEWORK, IGNORE THIS METHOD 41 | */ 42 | public BluetoothClass(){} 43 | protected BluetoothClass(int dClass, int mdClass, int...services) { 44 | this.dClass = dClass; 45 | this.mdClass = mdClass; 46 | this.services = services; 47 | } 48 | 49 | // 50 | public int describeContents() { 51 | return -1; 52 | } 53 | public boolean equals(Object o) { 54 | return false; 55 | } 56 | public int getDeviceClass() { 57 | return dClass; 58 | } 59 | public int getMajorDeviceClass() { 60 | return mdClass; 61 | } 62 | public boolean hasService(int service) { 63 | for(int i : services) { 64 | if (i == service) return true; 65 | } 66 | return false; 67 | } 68 | public int hashCode() { 69 | int out = dClass+mdClass; 70 | for(int i : services) { out+=i; } 71 | return out; 72 | } 73 | public void writeToParcel(Parcel out, int flags) { 74 | out.writeInt(dClass); 75 | out.writeInt(mdClass); 76 | out.writeIntArray(services); 77 | } 78 | // 79 | 80 | //serialization stuff 81 | // 82 | public int getdClass() { 83 | return dClass; 84 | } 85 | public void setdClass(int dClass) { 86 | this.dClass = dClass; 87 | } 88 | public int getMdClass() { 89 | return mdClass; 90 | } 91 | public void setMdClass(int mdClass) { 92 | this.mdClass = mdClass; 93 | } 94 | public int[] getServices() { 95 | return services; 96 | } 97 | public void setServices(int[] services) { 98 | this.services = services; 99 | } 100 | // 101 | 102 | } 103 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/bluetooth/BluetoothDevice.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.bluetooth; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.UUID; 7 | 8 | import android.os.Parcel; 9 | import android.os.Parcelable; 10 | import android.util.Log; 11 | import dk.itu.android.btemu.service.BTService; 12 | 13 | public class BluetoothDevice implements Parcelable { 14 | 15 | public static Parcelable.Creator CREATOR = new Parcelable.Creator() { 16 | @Override 17 | public BluetoothDevice createFromParcel(Parcel source) { 18 | BluetoothDevice out = new BluetoothDevice(); 19 | out.addr = source.readString(); 20 | out.tcpAddr = source.readString(); 21 | out.name = source.readString(); 22 | Parcelable[] tmp = source.readParcelableArray(BluetoothDevice.class.getClassLoader()); 23 | for(Parcelable s : tmp) { 24 | out.services.add((BTService)s); 25 | } 26 | return out; 27 | } 28 | @Override 29 | public BluetoothDevice[] newArray(int size) { 30 | return new BluetoothDevice[size]; 31 | } 32 | }; 33 | public void writeToParcel(Parcel out, int flags) { 34 | out.writeString(addr); 35 | out.writeString(tcpAddr); 36 | out.writeString(name); 37 | out.writeParcelableArray(services.toArray(new BTService[]{}), 0); 38 | } 39 | 40 | 41 | //constants 42 | public static final String ACTION_ACL_CONNECTED = "dk.android.bluetooth.device.action.ACL_CONNECTED"; 43 | public static final String ACTION_ACL_DISCONNECGTED = "dk.android.bluetooth.device.action.ACL_DISCONNECTED"; 44 | public static final String ACTION_ACL_DISCONNECT_REQUEST = "dk.android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"; 45 | public static final String ACTION_BOND_STATE_CHANGED = "dk.android.bluetooth.device.action.BOND_STATE_CHANGED"; 46 | public static final String ACTION_CLASS_CHANGED = "dk.android.bluetooth.device.action.CLASS_CHANGED"; 47 | public static final String ACTION_FOUND = "dk.android.bluetooth.device.action.FOUND"; 48 | public static final String ACTION_NAME_CHANGED = "dk.android.bluetooth.device.action.NAME_CHANGED"; 49 | public static final String EXTRA_BOND_STATE = "dk.android.bluetooth.device.extra.BOND_STATE"; 50 | public static final String EXTRA_CLASS = "dk.android.bluetooth.device.extra.CLASS"; 51 | public static final String EXTRA_DEVICE = "dk.android.bluetooth.device.extra.DEVICE"; 52 | public static final String EXTRA_NAME = "dk.android.bluetooth.device.extra.NAME"; 53 | public static final String EXTRA_PREVIOUS_BOND_STATE = "dk.android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; 54 | public static final String EXTRA_RSSI = "dk.android.bluetooth.device.extra.RSSI"; 55 | 56 | public static final int BOND_BONDED = 12; 57 | public static final int BOND_BONDING = 11; 58 | public static final int BOND_NONE = 10; 59 | public static final int ERROR = 0x80000000; 60 | // 61 | 62 | // 63 | public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { 64 | String uuids = uuid.toString(); 65 | for(BTService s : services) { 66 | if(s.getUuid().equals(uuids)) { 67 | Log.i("BT_DEVICE", "found service "+s.getUuid()+" on device "+addr); 68 | return new BluetoothSocket(this.tcpAddr,s.getTcpPort(),this); 69 | } 70 | 71 | } 72 | throw new IOException("sdp serivce discovery failed: service not found"); 73 | } 74 | public int describeContents(){ 75 | return -1; 76 | } 77 | public boolean equals(Object o) { 78 | return false; 79 | } 80 | public String getAddress(){ return addr; } 81 | public BluetoothClass getBluetoothClass(){ return btClass; } 82 | public int getBondState() { 83 | return BOND_NONE; 84 | } 85 | public String getName() { 86 | return name; 87 | } 88 | public int hashCode() { 89 | return addr.hashCode(); 90 | } 91 | public String toString() { 92 | return "BluetoothDevice " + addr; 93 | } 94 | // 95 | 96 | BluetoothClass btClass; 97 | String addr; 98 | String tcpAddr; 99 | String name; 100 | List services; 101 | 102 | /** 103 | * THIS IS NOT PART OF THE ANDROID PLATFORM, IGNORE THIS METHOD! 104 | * @param uuid 105 | * @param port 106 | */ 107 | public BluetoothDevice(String btAddr, String tcpAddr, String name) { 108 | this.addr = btAddr; 109 | this.tcpAddr = tcpAddr; 110 | this.name = name; 111 | this.services = new ArrayList(); 112 | this.btClass = new BluetoothClass( 113 | android.bluetooth.BluetoothClass.Device.PHONE_SMART, 114 | android.bluetooth.BluetoothClass.Device.Major.PHONE, 115 | android.bluetooth.BluetoothClass.Service.NETWORKING); 116 | } 117 | private BluetoothDevice() { 118 | this.services = new ArrayList(); 119 | this.btClass = new BluetoothClass( 120 | android.bluetooth.BluetoothClass.Device.PHONE_SMART, 121 | android.bluetooth.BluetoothClass.Device.Major.PHONE, 122 | android.bluetooth.BluetoothClass.Service.NETWORKING); 123 | } 124 | 125 | /** 126 | * THIS IS NOT PART OF THE ANDROID PLATFORM, IGNORE THIS METHOD! 127 | * @param uuid 128 | * @param port 129 | */ 130 | public void addService(String uuid, int port) { 131 | this.services.add(new BTService(uuid,port)); 132 | } 133 | 134 | /** 135 | * THIS IS NOT PART OF THE ANDROID PLATFORM, IGNORE THIS METHOD! 136 | * @param uuid 137 | * @param port 138 | */ 139 | public String getAddr() { 140 | return addr; 141 | } 142 | /** 143 | * THIS IS NOT PART OF THE ANDROID PLATFORM, IGNORE THIS METHOD! 144 | * @param uuid 145 | * @param port 146 | */ 147 | public String getTcpAddr() { 148 | return tcpAddr; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/bluetooth/BluetoothServerSocket.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.bluetooth; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.net.ServerSocket; 6 | import java.net.Socket; 7 | import java.nio.ByteBuffer; 8 | import java.util.Timer; 9 | import java.util.concurrent.Callable; 10 | import java.util.concurrent.ExecutorService; 11 | import java.util.concurrent.Executors; 12 | import java.util.concurrent.FutureTask; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | import android.util.Log; 16 | import dk.itu.android.btemu.service.BTEmulator; 17 | 18 | public class BluetoothServerSocket { 19 | static final String TAG = "BTEMU_SERVERSOCKET"; 20 | 21 | final ExecutorService executor = Executors.newFixedThreadPool(1); 22 | BTEmulator emulator; 23 | Timer timer = null; 24 | ServerSocket socket; 25 | 26 | int port; 27 | String UUID; 28 | 29 | protected BluetoothServerSocket(BTEmulator emulator,String UUID,int port) { 30 | this.emulator = emulator; 31 | this.port = port; 32 | this.UUID = UUID; 33 | try { 34 | this.socket = new ServerSocket(port); 35 | emulator.addService(UUID, port); 36 | } catch (IOException e) { 37 | Log.e(TAG, "cannot create server socket", e); 38 | } 39 | } 40 | 41 | private BluetoothSocket createBTSocket(Socket s) throws IOException { 42 | InputStream is = s.getInputStream(); 43 | Log.i(TAG, "creating btsocket, reading btaddr..."); 44 | int read; 45 | byte[] buf = new byte[25]; 46 | 47 | 48 | 49 | int idx = 0; 50 | do { 51 | read = is.read(); 52 | buf[idx] = (byte)read; 53 | idx++; 54 | } while( '\n' != read ); 55 | 56 | String btaddr = new String(buf,0,idx-1); 57 | 58 | Log.i(TAG, "received btaddr: " + btaddr); 59 | BluetoothDevice d = emulator.lookupBT(btaddr.trim()); 60 | return new BluetoothSocket(s, d); 61 | } 62 | 63 | public BluetoothSocket accept() throws IOException { 64 | //block until a conn is established 65 | Socket s = socket.accept(); 66 | return createBTSocket(s); 67 | } 68 | public BluetoothSocket accept(int timeout) throws IOException { 69 | //block until a conn is established with timeout 70 | FutureTask future = new FutureTask(new Callable() { 71 | @Override 72 | public Socket call() throws Exception { 73 | return socket.accept(); 74 | } 75 | }); 76 | executor.execute(future); 77 | try { 78 | Socket s = future.get(timeout, TimeUnit.SECONDS); 79 | return createBTSocket(s); 80 | } catch(Exception e) { 81 | Log.e(TAG, "accept(timeout) timed out? ",e); 82 | throw new IOException("timed out"); 83 | } 84 | } 85 | public void close() throws IOException { 86 | emulator.removeService(this.UUID, this.port); 87 | socket.close(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/bluetooth/BluetoothSocket.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.bluetooth; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | public class BluetoothSocket { 9 | 10 | //this is provided if the socket was created using the bt socket server 11 | Socket socket = null; 12 | 13 | //these are provided if device.open bla bla was called 14 | String ip; 15 | int port; 16 | 17 | BluetoothDevice remote; 18 | 19 | protected BluetoothSocket( String ip,int port,BluetoothDevice device ) { 20 | this.ip = ip; 21 | this.port = port; 22 | this.remote = device; 23 | } 24 | protected BluetoothSocket(Socket s,BluetoothDevice device){ 25 | this.socket = s; 26 | this.remote = device; 27 | } 28 | 29 | public void close() throws IOException { 30 | socket.close(); 31 | } 32 | public void connect() throws IOException { 33 | if(socket == null) { 34 | socket = new Socket(ip,port); 35 | OutputStream os = getOutputStream(); 36 | os.write( (BluetoothAdapter.getDefaultAdapter().getAddress()+"\n").getBytes() ); 37 | os.flush(); 38 | } 39 | } 40 | public InputStream getInputStream() throws IOException { 41 | return socket.getInputStream(); 42 | } 43 | public OutputStream getOutputStream() throws IOException { 44 | return socket.getOutputStream(); 45 | } 46 | public BluetoothDevice getRemoteDevice() { 47 | return remote; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/BTEmulator.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service; 2 | 3 | import java.net.Socket; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.FutureTask; 9 | 10 | import android.util.Log; 11 | import dk.itu.android.bluetooth.BluetoothDevice; 12 | import dk.itu.android.btemu.service.cmd.Discovery; 13 | import dk.itu.android.btemu.service.cmd.Join; 14 | import dk.itu.android.btemu.service.cmd.Leave; 15 | import dk.itu.android.btemu.service.cmd.ModifyService; 16 | 17 | public class BTEmulator { 18 | static final String TAG = "BTEMULATOR"; 19 | 20 | static final String DevMachineIP = "10.0.2.2"; 21 | static final int DiscoveryServerPort = 8199; 22 | 23 | static final BTEmulator _instance = new BTEmulator(); 24 | public static BTEmulator instance(){ return _instance; } 25 | 26 | public BTEmulator() { 27 | } 28 | 29 | public void join() { 30 | try { 31 | new Join(new Socket(DevMachineIP,DiscoveryServerPort)).run(); 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | Log.e(TAG, "cannot join", e); 35 | } 36 | } 37 | public void leave() { 38 | try { 39 | new Leave(new Socket(DevMachineIP,DiscoveryServerPort)).run(); 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | Log.e(TAG, "cannot leave", e); 43 | } 44 | } 45 | 46 | public void asyncDiscovery( Discovery.WithDevices wd ) { 47 | Discovery d; 48 | try { 49 | d = new Discovery(new Socket(DevMachineIP,DiscoveryServerPort)); 50 | d.setWithDevices(wd); 51 | new Thread(d).start(); 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | Log.e(TAG, "cannot async discovery", e); 55 | } 56 | } 57 | 58 | public void discovery( Discovery.WithDevices wd ) { 59 | Discovery d; 60 | try { 61 | d = new Discovery(new Socket(DevMachineIP,DiscoveryServerPort)); 62 | d.setWithDevices(wd); 63 | d.run(); 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | Log.e(TAG, "cannot discovery", e); 67 | } 68 | } 69 | 70 | public BluetoothDevice lookupBT( String btAddr ) { 71 | ExecutorService executor = Executors.newFixedThreadPool(1); 72 | FutureTask> future = 73 | new FutureTask>(new Callable>(){ 74 | @Override 75 | public List call() throws Exception { 76 | Discovery d = new Discovery(new Socket(DevMachineIP,DiscoveryServerPort)); 77 | d.run(); 78 | return d.getDevices(); 79 | } 80 | }); 81 | executor.execute(future); 82 | try { 83 | List devices = future.get(); 84 | for(BluetoothDevice d : devices) { 85 | Log.i(TAG, "check btaddr: "+d.getAddr() + " == " + btAddr + "?"); 86 | if(d.getAddr().equals(btAddr)) { 87 | Log.i(TAG, "btAddr match, return device"); 88 | return d; 89 | } 90 | } 91 | } catch (Exception e) { 92 | e.printStackTrace(); 93 | Log.e(TAG, "cannot retrieve btdevices", e); 94 | } 95 | Log.i(TAG, "btAddr " + btAddr + " not found! return null!"); 96 | return null; 97 | } 98 | // public BluetoothDevice lookupIP( String ipAddr ) { 99 | // ExecutorService executor = Executors.newFixedThreadPool(1); 100 | // FutureTask> future = 101 | // new FutureTask>(new Callable>(){ 102 | // @Override 103 | // public List call() throws Exception { 104 | // Discovery d = new Discovery(new Socket(DevMachineIP,DiscoveryServerPort)); 105 | // d.run(); 106 | // return d.getDevices(); 107 | // } 108 | // }); 109 | // executor.execute(future); 110 | // try { 111 | // List devices = future.get(); 112 | // for(BluetoothDevice d : devices) { 113 | // if(d.getTcpAddr().equals(ipAddr)) 114 | // return d; 115 | // } 116 | // } catch (Exception e) { 117 | // e.printStackTrace(); 118 | // Log.e(TAG, "cannot retrieve btdevices", e); 119 | // } 120 | // 121 | // return null; 122 | // } 123 | 124 | public void addService( String uuid, int port ) { 125 | modifyService(uuid,port,true); 126 | } 127 | public void removeService( String uuid, int port ) { 128 | modifyService(uuid,port,false); 129 | } 130 | protected void modifyService( String uuid, int port, boolean add ) { 131 | try { 132 | new ModifyService(new Socket(DevMachineIP,DiscoveryServerPort),uuid,port,add).run(); 133 | } catch (Exception e) { 134 | e.printStackTrace(); 135 | Log.e(TAG, "cannot modify service", e); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/BTService.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | public class BTService implements Parcelable { 7 | 8 | public static Parcelable.Creator CREATOR = new Parcelable.Creator() { 9 | @Override 10 | public BTService createFromParcel(Parcel source) { 11 | BTService out = new BTService(); 12 | out.tcpPort = source.readInt(); 13 | out.uuid = source.readString(); 14 | return out; 15 | } 16 | @Override 17 | public BTService[] newArray(int size) { 18 | return new BTService[size]; 19 | } 20 | }; 21 | 22 | @Override 23 | public int describeContents() { 24 | return 0; 25 | } 26 | @Override 27 | public void writeToParcel(Parcel dest, int flags) { 28 | dest.writeInt(tcpPort); 29 | dest.writeString(uuid); 30 | } 31 | 32 | int tcpPort; 33 | String uuid; 34 | 35 | public BTService(){} 36 | public BTService(String uuid, int port) { 37 | this.uuid = uuid; 38 | this.tcpPort = port; 39 | } 40 | 41 | public void setTcpPort(int tcpPort) { 42 | this.tcpPort = tcpPort; 43 | } 44 | public void setUuid(String uuid) { 45 | this.uuid = uuid; 46 | } 47 | public int getTcpPort() { 48 | return tcpPort; 49 | } 50 | public String getUuid() { 51 | return uuid; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/BaseCommand.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | import android.util.Log; 9 | 10 | public abstract class BaseCommand implements Runnable { 11 | static final String UTF8 = "UTF8"; 12 | 13 | CommandType type; 14 | Socket socket; 15 | InputStream in; 16 | OutputStream out; 17 | boolean hasParameters = false; 18 | 19 | public BaseCommand(CommandType type, Socket socket) { 20 | this(type,socket,true); 21 | } 22 | public BaseCommand(CommandType type, Socket socket, boolean hasParameters) { 23 | this.type = type; 24 | this.socket = socket; 25 | this.hasParameters = hasParameters; 26 | } 27 | 28 | @Override 29 | public void run() { 30 | try { 31 | out = socket.getOutputStream(); 32 | in = socket.getInputStream(); 33 | //1. send preamble (command name) 34 | writePreamble(); 35 | //2. send command specific variables? 36 | if(hasParameters) { 37 | sendParameters(out); 38 | } 39 | //in any case, send the bt.address parameter 40 | sendParameter( 41 | "bt.address", 42 | dk.itu.android.bluetooth.BluetoothAdapter.getDefaultAdapter().getAddress(), 43 | out ); 44 | out.write("]".getBytes(UTF8)); 45 | //3. close input stream 46 | // out.close(); 47 | //4. read response 48 | //5. read >>>>EOF<<<< 49 | readResponse(in); 50 | //6. close output stream and socket. 51 | // out.close(); 52 | // in.close(); 53 | socket.close(); 54 | Log.d("BTEMU_CMD", "command execution completed."); 55 | } catch(Exception e) { 56 | Log.e("BTEMU_CMD", "error while executing command " + type.name(), e); 57 | } finally { 58 | if(socket.isConnected()) { 59 | try{socket.close();}catch(Exception ignored){} 60 | } 61 | } 62 | } 63 | 64 | protected void writePreamble() throws IOException { 65 | Log.d("BTEMU_CMD", "writing preamble for type: "+type.name()); 66 | out.write( (Integer.toString(type.intRepr)+"]").getBytes(UTF8) ); 67 | } 68 | 69 | protected abstract void sendParameters(OutputStream out) throws IOException; 70 | protected abstract void readResponse(InputStream in) throws IOException; 71 | 72 | protected void sendParameter(String name, String value, OutputStream out) throws IOException { 73 | out.write( (name+"="+value+"&").getBytes(UTF8) ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/CommandType.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | public enum CommandType { 4 | 5 | JOIN(0), 6 | LEAVE(1), 7 | DISCOVERY(2), 8 | MODIFYSERVICE(3) 9 | ; 10 | 11 | int intRepr; 12 | private CommandType(int intRepr) { 13 | this.intRepr = intRepr; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/Discovery.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStream; 8 | import java.net.Socket; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import android.util.Log; 13 | 14 | import dk.itu.android.bluetooth.BluetoothDevice; 15 | 16 | public class Discovery extends NoParamsBaseCommand { 17 | public interface WithDevices { 18 | public void devices( List devices ); 19 | } 20 | 21 | @SuppressWarnings("unchecked") 22 | List devices = new ArrayList(); 23 | WithDevices withDevices = null; 24 | 25 | public Discovery( Socket socket ) { 26 | super(CommandType.DISCOVERY, socket); 27 | } 28 | public void setWithDevices(WithDevices wd) { 29 | this.withDevices = wd; 30 | } 31 | 32 | public List getDevices() { 33 | return devices; 34 | } 35 | 36 | // @Override 37 | // protected void readResponse(InputStream in) throws IOException { 38 | // String all = readAll(in); 39 | // Log.i("DISCOVERY_CMD", "all response: "+all); 40 | // for(String line : all.split("\r\n")) { 41 | // String[] parts = line.trim().split("|"); 42 | // dk.itu.android.bluetooth.BluetoothDevice d = new BluetoothDevice(parts[0], parts[1]); 43 | // 44 | // if(parts[3].length()>0) { 45 | // String[] sParts = parts[3].split("<>"); 46 | // for(String p : sParts) { 47 | // String[] s = p.split("|"); 48 | // d.addService(s[0], Integer.parseInt(s[1])); 49 | // } 50 | // } 51 | // devices.add(d); 52 | // } 53 | // if(withDevices != null) { 54 | // withDevices.devices(devices); 55 | // } 56 | // 57 | // } 58 | 59 | @Override 60 | protected void readResponse(InputStream in) throws IOException { 61 | //devices are: 62 | //bt.addr|ip.addr|uuid<>port|uuid<>port...\r\n 63 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 64 | String line = null; 65 | do { 66 | line = br.readLine(); 67 | Log.i("DISCOVERY_CMD", "device: " + line); 68 | if(line==null) break; 69 | 70 | String[] parts = line.trim().split("--"); 71 | dk.itu.android.bluetooth.BluetoothDevice d = new BluetoothDevice(parts[0], parts[1],parts[2]); 72 | 73 | String log = ""; 74 | int idx = 0; 75 | for(String part : parts) { 76 | log += idx + ". " + part + "\n"; 77 | } 78 | Log.i("DISCOVERY_CMD",log); 79 | 80 | if(parts.length>3) { 81 | if(parts[3].length()>0) { 82 | String[] sParts = parts[3].split("<><>"); 83 | Log.i("DISCOVERY_CMD","services: " + parts[3]); 84 | for(String p : sParts) { 85 | Log.i("DISCOVERY_CMD",p); 86 | String[] s = p.split("<>"); 87 | Log.i("DISCOVERY_CMD","Split service length: " + s.length); 88 | d.addService(s[0], Integer.parseInt(s[1])); 89 | } 90 | } 91 | } 92 | devices.add(d); 93 | } while(line != null); 94 | 95 | if(withDevices != null) { 96 | withDevices.devices(devices); 97 | } 98 | } 99 | 100 | @Override 101 | protected void sendParameters(OutputStream out) throws IOException { 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/Join.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStream; 8 | import java.net.Socket; 9 | 10 | public class Join extends BaseCommand { 11 | 12 | public Join( Socket socket ) { 13 | super(CommandType.JOIN, socket); 14 | } 15 | 16 | @Override 17 | protected void readResponse(InputStream in) throws IOException { 18 | //get the emulator port number 19 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 20 | String p = br.readLine(); 21 | String name = "emulator-" + p; 22 | name = name.trim(); 23 | dk.itu.android.bluetooth.BluetoothAdapter.getDefaultAdapter().setName(name); 24 | } 25 | 26 | @Override 27 | protected void sendParameters(OutputStream out) throws IOException { 28 | sendParameter( "tcp.address","10.0.2.2",out ); 29 | sendParameter( "device.name", dk.itu.android.bluetooth.BluetoothAdapter.getDefaultAdapter().getName(), out); 30 | // sendParameter( "bt.address", dk.itu.android.bluetooth.BluetoothAdapter.getDefaultAdapter().getAddress(), out ); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/Leave.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | public class Leave extends NoParamsBaseCommand { 9 | 10 | public Leave( Socket socket ) { 11 | super(CommandType.LEAVE,socket); 12 | } 13 | 14 | @Override 15 | protected void readResponse(InputStream in) throws IOException { 16 | //don't care 17 | } 18 | 19 | @Override 20 | protected void sendParameters(OutputStream out) throws IOException { 21 | // sendParameter( "tcp.address", socket.getLocalAddress().getHostAddress(), out ); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/ModifyService.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | public class ModifyService extends BaseCommand { 9 | 10 | int port; 11 | String uuid; 12 | boolean added; 13 | public ModifyService(Socket socket, String uuid, int port, boolean added) { 14 | super(CommandType.MODIFYSERVICE, socket); 15 | this.uuid = uuid; 16 | this.port = port; 17 | this.added = added; 18 | } 19 | 20 | @Override 21 | protected void readResponse(InputStream in) throws IOException { 22 | } 23 | 24 | @Override 25 | protected void sendParameters(OutputStream out) throws IOException { 26 | sendParameter("type", added ? "added" : "removed", out); 27 | sendParameter("tcp.port", port+"",out); 28 | sendParameter("service.uuid",uuid,out); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /android-btsim-application/src/dk/itu/android/btemu/service/cmd/NoParamsBaseCommand.java: -------------------------------------------------------------------------------- 1 | package dk.itu.android.btemu.service.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.net.Socket; 6 | 7 | public abstract class NoParamsBaseCommand extends BaseCommand { 8 | 9 | public NoParamsBaseCommand(CommandType type, Socket socket) { 10 | super(type,socket,false); 11 | } 12 | 13 | @Override 14 | protected void sendParameters(OutputStream in) throws IOException { 15 | //emtpy method 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/BTMacForwardingsChecker$DeviceAddr.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/BTMacForwardingsChecker$DeviceAddr.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/BTMacForwardingsChecker.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/BTMacForwardingsChecker.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/CommandParser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/CommandParser.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/Server$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/Server$1.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/Server.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/Server.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/State.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/State.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/BaseCommand$Param.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/BaseCommand$Param.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/BaseCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/BaseCommand.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/CommandType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/CommandType.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/Discovery.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/Discovery.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/Join.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/Join.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/Leave.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/Leave.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/cmd/ModifyService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/cmd/ModifyService.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/state/Device.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/state/Device.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/state/Service.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/state/Service.class -------------------------------------------------------------------------------- /btsim-server/bin/dk/itu/btemu/test/VarTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/bin/dk/itu/btemu/test/VarTest.class -------------------------------------------------------------------------------- /btsim-server/client-src/dk/itu/btemu/client/BtEmuClient.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.client; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.OutputStream; 7 | import java.net.Socket; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | public class BtEmuClient { 16 | static final String UTF8 = "UTF-8"; 17 | 18 | static final int JOIN = 0; 19 | static final int LEAVE = 1; 20 | static final int DISCOVERY = 2; 21 | static final int MODIFYSERVICE = 3; 22 | 23 | class Device { 24 | String btAddr; 25 | String ipAddr; 26 | List services = new ArrayList(); 27 | 28 | public String getBtAddr() { 29 | return btAddr; 30 | } 31 | public String getIpAddr() { 32 | return ipAddr; 33 | } 34 | public List getServices() { 35 | return services; 36 | } 37 | } 38 | class Service { 39 | String uuid; 40 | int port; 41 | 42 | public int getPort() { 43 | return port; 44 | } 45 | public String getUuid() { 46 | return uuid; 47 | } 48 | } 49 | 50 | String fakeBluetoothAddress; 51 | 52 | String serverAddr; 53 | int serverPort; 54 | 55 | Socket socket; 56 | BufferedReader isReader; 57 | OutputStream os; 58 | Thread clientThread; 59 | 60 | boolean running = true; 61 | 62 | public BtEmuClient(String btAddr, String addr,int port) { 63 | this.fakeBluetoothAddress = btAddr; 64 | this.serverAddr = addr; 65 | this.serverPort = port; 66 | } 67 | 68 | public BtEmuClient(String btAddr) { 69 | this(btAddr,"localhost",8199); 70 | } 71 | 72 | public void start() { 73 | try { 74 | socket = new Socket(this.serverAddr,this.serverPort); 75 | os = socket.getOutputStream(); 76 | isReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 77 | } catch (Exception e) { 78 | e.printStackTrace(); 79 | throw new RuntimeException("cannot connect to server!"); 80 | } 81 | } 82 | public void stop() { 83 | try { 84 | socket.close(); 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | 90 | public void join() { 91 | send( JOIN,stdCmd() ); 92 | } 93 | public void leave() { 94 | send( LEAVE,stdCmd() ); 95 | } 96 | public void addService(String uuid,int port) { 97 | modifyService(uuid,port,true); 98 | } 99 | public void removeService(String uuid) { 100 | modifyService(uuid,0,false); 101 | } 102 | void log(String tag,String s){ 103 | System.out.println(tag+"\n\t"+s); 104 | } 105 | private void modifyService(String uuid, int port, boolean added) { 106 | Map m = stdCmd(); 107 | m.put("type", added ? "added" : "removed"); 108 | m.put("tcp.port", port+""); 109 | m.put("service.uuid",uuid); 110 | send( MODIFYSERVICE,m ); 111 | } 112 | public Set discovery() { 113 | Set out = new HashSet(); 114 | send( DISCOVERY,stdCmd() ); 115 | 116 | String line = null; 117 | do { 118 | try { 119 | line = isReader.readLine(); 120 | } catch (IOException e) { 121 | e.printStackTrace(); 122 | throw new RuntimeException("cannot read inputstream!"); 123 | } 124 | log("DISCOVERY_CMD", "device: " + line); 125 | if(line==null) break; 126 | 127 | String[] parts = line.trim().split("--"); 128 | Device d = new Device(); 129 | d.btAddr = parts[0]; 130 | d.ipAddr = parts[1]; 131 | 132 | if(parts.length>2) { 133 | if(parts[2].length()>0) { 134 | String[] sParts = parts[2].split("<><>"); 135 | for(String p : sParts) { 136 | String[] s = p.split("<>"); 137 | Service srv = new Service(); 138 | srv.uuid = s[0]; 139 | srv.port = Integer.parseInt(s[1]); 140 | d.services.add(srv); 141 | } 142 | } 143 | } 144 | out.add(d); 145 | } while(line != null); 146 | 147 | return out; 148 | } 149 | 150 | public Map stdCmd() { 151 | Map out = new HashMap(); 152 | out.put("bt.address", this.fakeBluetoothAddress); 153 | out.put("tcp.address", "127.0.0.1"); 154 | out.put("not.android.emulator", "true"); 155 | return out; 156 | } 157 | 158 | void send(int cmdType, Map command) { 159 | try { 160 | os.write( (cmdType+"]").getBytes(UTF8) ); 161 | for(String k : command.keySet()) { 162 | os.write( (k+"="+command.get(k)+"&").getBytes(UTF8) ); 163 | } 164 | os.write("]".getBytes(UTF8)); 165 | os.flush(); 166 | } catch (Exception e) { 167 | e.printStackTrace(); 168 | } 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /btsim-server/dist/btsimserver.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheng81/Android-Bluetooth-Simulator/68aca94792b97dab9f9d8531cbae642da8635457/btsim-server/dist/btsimserver.jar -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/BTMacForwardingsChecker.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import dk.itu.btemu.state.Device; 11 | 12 | public class BTMacForwardingsChecker { 13 | 14 | private class DeviceAddr { 15 | String type; 16 | String btaddr; 17 | int port; 18 | public DeviceAddr(String type, int port) { 19 | this.type = type; this.port = port; 20 | } 21 | } 22 | 23 | public void run() { 24 | System.out.println("getting device list..."); 25 | //get avail devices 26 | List addresses = getAvailableDevices(); 27 | //for each one, check if a device exists? 28 | System.out.println("search for bt addresses..."); 29 | searchBTAddresses(addresses); 30 | updateEmulatorPort(addresses); 31 | } 32 | 33 | private void updateEmulatorPort(List addresses) { 34 | for(DeviceAddr addr : addresses) { 35 | Device d = State.getInstance().get(addr.btaddr); 36 | if(d != null) { 37 | d.setEmulatorPort(addr.port); 38 | } else { 39 | System.out.println("cannot find device with bt.addr: " + addr.btaddr + 40 | ", running on port: " + addr.port); 41 | } 42 | } 43 | } 44 | 45 | private void searchBTAddresses(List addresses) { 46 | for(DeviceAddr addr : addresses) { 47 | Process p = createProcess(Server.ADB_CMD(), "-s", addr.type+"-"+addr.port, 48 | "shell", 49 | "cat /data/data/dk.itu.android.btemu/files/BTADDR.TXT"); 50 | InputStream is = p.getInputStream(); 51 | InputStreamReader inr = new InputStreamReader(is); 52 | char[] buf = new char[1]; 53 | String s = ""; 54 | int read = 0; 55 | try { 56 | do { 57 | read = inr.read(buf); 58 | if(read>0) 59 | s+=buf[0]; 60 | } while(read>0); 61 | } catch(Exception e) { 62 | throw new RuntimeException(e); 63 | } 64 | System.out.println("got bluetooth address: " + s); 65 | addr.btaddr = s; 66 | } 67 | } 68 | private List getAvailableDevices() { 69 | List out = new ArrayList(); 70 | Process p = createProcess(Server.ADB_CMD(),"devices"); 71 | BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); 72 | String line = ""; 73 | do { 74 | try { 75 | line = br.readLine(); 76 | DeviceAddr cur = parse(line); 77 | if(cur!=null){ 78 | out.add(cur); 79 | } 80 | } catch (IOException e) { 81 | e.printStackTrace(); 82 | throw new RuntimeException(e); 83 | } 84 | } while(line != null); 85 | return out; 86 | } 87 | private DeviceAddr parse(String line) { 88 | if(line==null) return null; 89 | line = line.trim(); 90 | System.out.println("trying to parse: " + line); 91 | if(line.startsWith("emulator")) { 92 | line = line.substring("emulator-".length()); 93 | line = line.substring(0, 4); 94 | int port = Integer.parseInt(line); 95 | System.out.println("added device running on port: " + port); 96 | return new DeviceAddr("emulator",port); 97 | } 98 | return null; 99 | } 100 | 101 | 102 | 103 | public static Process createProcess(String...args) { 104 | ProcessBuilder pb = new ProcessBuilder(args); 105 | try { 106 | return pb.start(); 107 | } catch (IOException e) { 108 | e.printStackTrace(); 109 | throw new RuntimeException(e); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/CommandParser.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.net.Socket; 7 | 8 | import dk.itu.btemu.cmd.BaseCommand; 9 | import dk.itu.btemu.cmd.CommandType; 10 | 11 | public class CommandParser { 12 | public BaseCommand resolve(Socket socket) throws IOException { 13 | InputStream is = socket.getInputStream(); 14 | InputStreamReader isr = new InputStreamReader(is, "UTF-8"); 15 | 16 | char[] buf = new char[1]; 17 | 18 | StringBuilder sb = new StringBuilder(); 19 | String s = ""; 20 | int count = 0; 21 | 22 | do { 23 | count = isr.read(buf); 24 | sb.append(buf); 25 | s = sb.toString(); 26 | System.out.println("new string is : '" + s + "'"); 27 | } while( s.charAt(s.length()-1) != ']' && count != -1 ); 28 | 29 | s = s.substring(0, s.length()-1); 30 | int type = Integer.parseInt(s); 31 | 32 | return CommandType.fromRepr(type).createCommand(socket, isr); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/Server.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu; 2 | 3 | import java.io.IOException; 4 | import java.net.ServerSocket; 5 | import java.net.Socket; 6 | 7 | public class Server { 8 | public static String ADB_CMD_PATH = "";//"/Applications/code/android-sdk/tools/"; 9 | public static String ADB_EXE = "adb"; 10 | public static String ADB_CMD(){ return ADB_CMD_PATH + ADB_EXE; } 11 | static int StartPort = 8123; 12 | static int _n = 0; 13 | public static int next() { 14 | _n++; 15 | return StartPort+_n; 16 | } 17 | 18 | int port; 19 | boolean running; 20 | CommandParser cmdParser; 21 | Thread serverThread; 22 | ServerSocket server; 23 | 24 | public Server(int port) { 25 | running = true; 26 | this.port = port; 27 | this.cmdParser = new CommandParser(); 28 | } 29 | 30 | public void start() { 31 | try { 32 | server = new ServerSocket(port); 33 | } catch (IOException e1) { 34 | // TODO Auto-generated catch block 35 | e1.printStackTrace(); 36 | return; 37 | } 38 | serverThread = new Thread(new Runnable(){ 39 | @Override 40 | public void run() { 41 | while(running) { 42 | try { 43 | Socket spawned = server.accept(); 44 | System.out.println("accepting a new connection from " 45 | + spawned.getInetAddress()); 46 | spawnWorker(spawned); 47 | } catch (Exception e) { 48 | e.printStackTrace(); 49 | System.out.println("error in server main loop!"); 50 | } 51 | } 52 | } 53 | }); 54 | serverThread.start(); 55 | } 56 | public void stop() { 57 | if(serverThread != null) { 58 | running = false; 59 | try { 60 | server.close(); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | } 66 | 67 | protected void spawnWorker(final Socket socket) throws IOException { 68 | new Thread(cmdParser.resolve(socket)).start(); 69 | } 70 | 71 | public static void main(String args[]) throws Exception { 72 | int port = 8199; 73 | if(args.length>0) { 74 | if(args[0].equals("--help")) { 75 | PrintHelp(); 76 | return; 77 | } else { 78 | for(String s : args) { 79 | if(s.startsWith("--port=")) { 80 | String sport = s.substring("--port=".length()); 81 | port = Integer.parseInt(sport); 82 | } else if(s.startsWith("--adb.path=")) { 83 | ADB_CMD_PATH = s.substring("--adb.path=".length()); 84 | } 85 | } 86 | } 87 | } 88 | if( System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 ) { 89 | //this is windows, so the ADB_EXE is adb.exe 90 | ADB_EXE = "adb.exe"; 91 | } 92 | 93 | Server s = new Server(port); 94 | s.start(); 95 | 96 | System.out.println("Server started on port " + s.port); 97 | System.out.println("ADB command: "+ ADB_CMD()); 98 | System.out.println("press any key to exit"); 99 | System.in.read(); 100 | System.out.println("exiting..."); 101 | s.stop(); 102 | } 103 | 104 | private static void PrintHelp() { 105 | String out = "Start the Bluetooth Android Emulator server.\n"; 106 | out += "Sample usage:\n"; 107 | out += "java dk.itu.btemu.Server --adb.path=/usr/local/share/android.sk/tools/\n\n"; 108 | out += "Parameters:\n"; 109 | out += "--port= specify the port on which run the server\n"; 110 | out += "\tdefault: 8199. Note that currently is hard-coded in\n"; 111 | out += "\tthe android library.\n"; 112 | out += "--adb.path= specify where to find the adb command\n"; 113 | out += "\tdefault: /Applications/code/android.sdk/tools/\n\n"; 114 | out += "If you want to check which devices are connected, \n"; 115 | out += "telnet localhost , followd by the discovery command\n"; 116 | out += "which is 2]](return)"; 117 | System.out.println(out); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/State.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class State { 9 | static final State _instance = new State(); 10 | public static State getInstance(){ return _instance; } 11 | 12 | Map _state = new HashMap(); 13 | 14 | @SuppressWarnings("unchecked") 15 | public T get(String key) { 16 | return (T)_state.get(key); 17 | } 18 | 19 | @SuppressWarnings("unchecked") 20 | public List asList(Class cls) { 21 | List out = new ArrayList(); 22 | for(String k : _state.keySet()) { 23 | if(_state.get(k).getClass().equals(cls)) { 24 | T t = (T)_state.get(k); 25 | out.add(t); 26 | } 27 | } 28 | return out; 29 | } 30 | 31 | public void put(String key, Object value) { 32 | _state.put(key, value); 33 | } 34 | public boolean remove(String key) { 35 | if(_state.containsKey(key)) { 36 | _state.remove(key); 37 | return true; 38 | } 39 | return false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/cmd/BaseCommand.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public abstract class BaseCommand implements Runnable { 11 | public class Param { 12 | String name; 13 | String value; 14 | public Param(String n, String v) { 15 | this.name = n; 16 | this.value = v; 17 | } 18 | public String getName() { 19 | return name; 20 | } 21 | public String getValue() { 22 | return value; 23 | } 24 | } 25 | 26 | Socket socket; 27 | InputStreamReader in; 28 | OutputStream out; 29 | 30 | List params; 31 | String remoteIp; 32 | 33 | public BaseCommand(Socket socket, InputStreamReader socketInputStream) { 34 | // try { 35 | this.socket = socket; 36 | in = socketInputStream; 37 | // } catch(IOException e) { 38 | // throw new RuntimeException(e); 39 | // } 40 | } 41 | 42 | public void run() { 43 | try { 44 | out = socket.getOutputStream(); 45 | params = readParams(in); 46 | remoteIp = socket.getInetAddress().getHostAddress(); 47 | work(params); 48 | writeResponse(out); 49 | out.flush(); 50 | // out.close(); 51 | // in.close(); 52 | socket.close(); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } finally { 56 | if(socket.isConnected()) { 57 | try{socket.close();}catch(IOException ignored){} 58 | } 59 | } 60 | 61 | } 62 | 63 | protected abstract void work( List params ) throws Exception; 64 | protected abstract void writeResponse( OutputStream out ) throws IOException; 65 | 66 | protected List readParams(InputStreamReader in) throws IOException { 67 | List out = new ArrayList(); 68 | String[] cur = null; 69 | do { 70 | cur = readParam(in); 71 | if(cur != null) { 72 | out.add(new Param(cur[0],cur[1])); 73 | } 74 | } while(cur != null); 75 | return out; 76 | } 77 | 78 | protected String[] readParam(InputStreamReader inr) throws IOException { 79 | 80 | char[] buf = new char[1]; 81 | 82 | StringBuilder sb = new StringBuilder(); 83 | int count = 0; 84 | String s = ""; 85 | char last = ' '; 86 | do { 87 | count = inr.read(buf); 88 | sb.append(buf); 89 | s=sb.toString(); 90 | last = buf[0]; 91 | } while( (last != '&' && last != ']') && count!=-1 ); 92 | 93 | if(last == ']') { 94 | return null; 95 | } 96 | s = s.substring(0,s.length()-1); 97 | System.out.println("read parameter: " + s); 98 | return s.split("="); 99 | } 100 | 101 | protected String getParam(String key) { 102 | for(Param p : params) { 103 | if(p.name.equals(key)) 104 | return p.value; 105 | } 106 | return null; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/cmd/CommandType.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.cmd; 2 | 3 | import java.io.InputStreamReader; 4 | import java.net.Socket; 5 | 6 | public enum CommandType { 7 | 8 | JOIN(0, Join.class), 9 | LEAVE(1, Leave.class), 10 | DISCOVERY(2, Discovery.class), 11 | MODIFYSERVICE(3, ModifyService.class); 12 | 13 | int intRepr; 14 | Class cls; 15 | private CommandType(int i, Class cls) { 16 | intRepr = i; 17 | this.cls = cls; 18 | } 19 | @SuppressWarnings("unchecked") 20 | public T createCommand(Socket s, InputStreamReader r) { 21 | System.out.println("creating command " + name()); 22 | try { 23 | return (T)cls.getConstructor(Socket.class,InputStreamReader.class).newInstance(s,r); 24 | } catch(Exception e) { 25 | throw new RuntimeException(e); 26 | } 27 | } 28 | public static CommandType fromRepr(int i) { 29 | for(CommandType c : values()) { 30 | if(i==c.intRepr) 31 | return c; 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/cmd/Discovery.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.util.List; 8 | 9 | import dk.itu.btemu.State; 10 | import dk.itu.btemu.state.Device; 11 | import dk.itu.btemu.state.Service; 12 | 13 | public class Discovery extends BaseCommand { 14 | 15 | List devices; 16 | String btAddr; 17 | public Discovery(Socket socket, InputStreamReader socketInputStream) { 18 | super(socket, socketInputStream); 19 | } 20 | 21 | @Override 22 | protected void work(List params) throws Exception { 23 | devices = State.getInstance().asList(Device.class); 24 | btAddr = getParam("bt.address"); 25 | } 26 | 27 | @Override 28 | protected void writeResponse(OutputStream out) throws IOException { 29 | // OutputStreamWriter wrt = new OutputStreamWriter(out,"UTF-8"); 30 | for( Device d : devices ) { 31 | if(d.getBtAddr().equals(btAddr)) 32 | continue; 33 | String cur = d.getBtAddr() + "--" + d.getIpAddr() + "--" + d.getName() + "--"; 34 | boolean f = true; 35 | for(Service s : d.getServices()) { 36 | if(f){f=!f;}else{cur+="<><>";} 37 | cur += s.getUUID() + "<>" + s.getHostPort(); 38 | } 39 | cur+="\r\n"; 40 | out.write(cur.getBytes("UTF-8")); 41 | System.out.println("writing: " + cur); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/cmd/Join.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.util.List; 8 | 9 | import dk.itu.btemu.BTMacForwardingsChecker; 10 | import dk.itu.btemu.State; 11 | import dk.itu.btemu.state.Device; 12 | 13 | public class Join extends BaseCommand { 14 | int port = -1; 15 | 16 | public Join(Socket s, InputStreamReader in) { 17 | super(s,in); 18 | } 19 | 20 | @Override 21 | protected void work( List params ) throws Exception { 22 | String ipAddress = getParam("tcp.address");//remoteIp;//this.socket.getInetAddress().getHostAddress(); 23 | String btAddress = getParam("bt.address"); 24 | 25 | //save them 26 | Device device = new Device(ipAddress, btAddress); 27 | State.getInstance().put(btAddress, device); 28 | 29 | 30 | if(null == getParam("not.android.emulator")) { 31 | BTMacForwardingsChecker checker = new BTMacForwardingsChecker(); 32 | System.out.println("running checker..."); 33 | checker.run(); 34 | port = device.getEmulatorPort(); 35 | } else { 36 | device.setAndroidEmulator(false); 37 | } 38 | } 39 | 40 | @Override 41 | protected void writeResponse(OutputStream out) throws IOException { 42 | if(port > 0) { 43 | out.write( (port+"\n").getBytes("UTF-8") ); 44 | } 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/cmd/Leave.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.util.List; 8 | 9 | import dk.itu.btemu.State; 10 | 11 | public class Leave extends BaseCommand { 12 | 13 | public Leave(Socket socket, InputStreamReader socketInputStream) { 14 | super(socket, socketInputStream); 15 | } 16 | 17 | @Override 18 | protected void work(List params) throws Exception { 19 | State.getInstance().remove(getParam("bt.address")); 20 | } 21 | 22 | @Override 23 | protected void writeResponse(OutputStream out) throws IOException { 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/cmd/ModifyService.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.cmd; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.util.List; 8 | 9 | import dk.itu.btemu.State; 10 | import dk.itu.btemu.state.Device; 11 | 12 | public class ModifyService extends BaseCommand { 13 | 14 | public ModifyService(Socket socket, InputStreamReader socketInputStream) { 15 | super(socket, socketInputStream); 16 | } 17 | 18 | @Override 19 | protected void work(List params) throws Exception { 20 | String sport = getParam("tcp.port"); 21 | String UUID = getParam("service.uuid"); 22 | String type = getParam("type"); 23 | int port = Integer.parseInt(sport); 24 | 25 | Device d = State.getInstance().get(getParam("bt.address")); 26 | 27 | if(type.equals("added")) { 28 | d.addService(UUID, port); 29 | } else { 30 | d.removeService(UUID); 31 | } 32 | } 33 | 34 | @Override 35 | protected void writeResponse(OutputStream out) throws IOException { 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/state/Device.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.state; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Device { 7 | 8 | String ipAddr; 9 | String btAddr; 10 | String name; 11 | 12 | boolean isAndroidEmulator = true; 13 | 14 | /** 15 | * The port at which is running the emulator 16 | */ 17 | int emulatorPort = -1; 18 | List services; 19 | 20 | public Device(String ip,String bt) { 21 | this.ipAddr = ip; 22 | this.btAddr = bt; 23 | this.services = new ArrayList(); 24 | } 25 | 26 | public void addService(String UUID, int port) { 27 | services.add(new Service(UUID, port, this)); 28 | } 29 | public void removeService(String UUID) { 30 | Service s = getService(UUID); 31 | services.remove(s); 32 | } 33 | 34 | protected Service getService(String uuid) { 35 | for(Service s : services) { 36 | if(s.UUID.equals(uuid)) 37 | return s; 38 | } 39 | return null; 40 | } 41 | 42 | public String getBtAddr() { 43 | return btAddr; 44 | } 45 | public String getIpAddr() { 46 | return ipAddr; 47 | } 48 | public String getName() { 49 | return name; 50 | } 51 | public List getServices() { 52 | return services; 53 | } 54 | public void setEmulatorPort(int emulatorPort) { 55 | this.name = "emulator-"+emulatorPort; 56 | this.emulatorPort = emulatorPort; 57 | } 58 | public int getEmulatorPort() { 59 | return emulatorPort; 60 | } 61 | public boolean isAndroidEmulator() { 62 | return isAndroidEmulator; 63 | } 64 | public void setAndroidEmulator(boolean isAndroidEmulator) { 65 | this.isAndroidEmulator = isAndroidEmulator; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /btsim-server/src/dk/itu/btemu/state/Service.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.state; 2 | 3 | import dk.itu.btemu.BTMacForwardingsChecker; 4 | import dk.itu.btemu.Server; 5 | 6 | public class Service { 7 | 8 | String UUID; 9 | Device device; 10 | int tcpPort; 11 | /** 12 | * The port on which a client should connect 13 | * in order to connect to the service 14 | * due to networking limitation of the emulator.. 15 | */ 16 | int hostPort; 17 | 18 | public Service(String UUID, int tcpPort, Device device) { 19 | this.UUID = UUID; 20 | this.tcpPort = tcpPort; 21 | this.device = device; 22 | 23 | if(device.isAndroidEmulator()) { 24 | this.hostPort = Server.next(); 25 | createNetworkRedirection(); 26 | } else { 27 | System.out.println("not-android-emulator service"); 28 | this.hostPort = tcpPort; 29 | } 30 | 31 | } 32 | private void createNetworkRedirection() { 33 | System.out.println("creating network forwarding from "+tcpPort+" to "+hostPort); 34 | Process p = BTMacForwardingsChecker.createProcess(Server.ADB_CMD(), 35 | "-s","emulator-"+device.emulatorPort, 36 | "forward", 37 | "tcp:"+hostPort, 38 | "tcp:"+tcpPort); 39 | int exitValue; 40 | try { 41 | exitValue = p.waitFor(); 42 | System.out.println("forward process exit value: " + exitValue); 43 | } catch (InterruptedException e) { 44 | // TODO Auto-generated catch block 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | public int getTcpPort() { 50 | return tcpPort; 51 | } 52 | public int getHostPort() { 53 | return hostPort; 54 | } 55 | public String getUUID() { 56 | return UUID; 57 | } 58 | public Device getDevice() { 59 | return device; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /btsim-server/test/dk/itu/btemu/test/VarTest.java: -------------------------------------------------------------------------------- 1 | package dk.itu.btemu.test; 2 | 3 | import java.util.UUID; 4 | 5 | import junit.framework.TestCase; 6 | 7 | public class VarTest extends TestCase { 8 | 9 | public void testString() { 10 | String s = "foobarbaz"; 11 | System.out.println(s.charAt(s.length()-1)); 12 | } 13 | public void testUUID() { 14 | System.out.println(UUID.randomUUID().toString()); 15 | } 16 | } 17 | --------------------------------------------------------------------------------