summaryrefslogtreecommitdiffstats
path: root/pxp-monitor
diff options
context:
space:
mode:
authorSatish kumar sugasi <ssugas@codeaurora.org>2013-11-21 16:48:40 -0800
committerSubramanian Srinivasan <subrsrin@codeaurora.org>2013-12-16 15:22:35 -0800
commit9a41f62ea7933ad2ed1e663ef731780741aa39c8 (patch)
tree5461399cd2e791eb0f2bfa8e96f23675c549c63a /pxp-monitor
parent4e389ad19c8d49cd2072ecbc2f9f6fa6e44a127d (diff)
downloadandroid_packages_apps_BluetoothExt-9a41f62ea7933ad2ed1e663ef731780741aa39c8.tar.gz
android_packages_apps_BluetoothExt-9a41f62ea7933ad2ed1e663ef731780741aa39c8.tar.bz2
android_packages_apps_BluetoothExt-9a41f62ea7933ad2ed1e663ef731780741aa39c8.zip
Bluetooth: Add support for LE proximity profile
This Enables Proximity service and pxp monitor test application Change-Id: I7be72defcae8c1d926e55aa29c744d7e64425f93 CRs-fixed: 580130
Diffstat (limited to 'pxp-monitor')
-rw-r--r--pxp-monitor/.gitignore30
-rw-r--r--pxp-monitor/Android.mk19
-rw-r--r--pxp-monitor/AndroidManifest.xml73
-rw-r--r--pxp-monitor/res/drawable-hdpi/ic_launcher.pngbin0 -> 7044 bytes
-rw-r--r--pxp-monitor/res/drawable-hdpi/search.pngbin0 -> 7044 bytes
-rw-r--r--pxp-monitor/res/drawable-mdpi/ic_launcher.pngbin0 -> 4151 bytes
-rw-r--r--pxp-monitor/res/drawable-mdpi/search.pngbin0 -> 7044 bytes
-rw-r--r--pxp-monitor/res/drawable-xhdpi/ic_launcher.pngbin0 -> 7044 bytes
-rw-r--r--pxp-monitor/res/drawable-xhdpi/search.pngbin0 -> 7044 bytes
-rw-r--r--pxp-monitor/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 7044 bytes
-rwxr-xr-xpxp-monitor/res/drawable-xxhdpi/search.pngbin0 -> 7044 bytes
-rw-r--r--pxp-monitor/res/layout/activity_alerts_history.xml62
-rw-r--r--pxp-monitor/res/layout/activity_device.xml53
-rw-r--r--pxp-monitor/res/layout/activity_list_devices.xml62
-rw-r--r--pxp-monitor/res/layout/activity_main.xml90
-rw-r--r--pxp-monitor/res/layout/connect_to_device_dialog_fragment.xml45
-rw-r--r--pxp-monitor/res/layout/device_info_fragment.xml47
-rw-r--r--pxp-monitor/res/layout/link_loss_fragment.xml80
-rw-r--r--pxp-monitor/res/layout/path_loss_fragment.xml121
-rw-r--r--pxp-monitor/res/menu/device.xml45
-rw-r--r--pxp-monitor/res/menu/main.xml34
-rw-r--r--pxp-monitor/res/menu/scan.xml40
-rw-r--r--pxp-monitor/res/values-sw600dp/dimens.xml36
-rw-r--r--pxp-monitor/res/values-sw720dp-land/dimens.xml37
-rw-r--r--pxp-monitor/res/values-v11/styles.xml39
-rw-r--r--pxp-monitor/res/values-v14/styles.xml40
-rw-r--r--pxp-monitor/res/values/dimens.xml35
-rw-r--r--pxp-monitor/res/values/strings.xml54
-rw-r--r--pxp-monitor/res/values/styles.xml48
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertInformation.java37
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertsHistory.java235
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectToDeviceDialogFragment.java87
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectedDevicesActivity.java247
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceActivity.java365
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceInfoFragment.java60
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/LinkLossFragment.java165
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/MainActivity.java188
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PairedDevicesActivity.java236
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PathLossFragment.java299
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PxpServiceProxy.java393
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ScanDevicesActivity.java326
-rw-r--r--pxp-monitor/src/org/codeaurora/bluetooth/pxpservice/IPxpService.aidl170
42 files changed, 3898 insertions, 0 deletions
diff --git a/pxp-monitor/.gitignore b/pxp-monitor/.gitignore
new file mode 100644
index 0000000..5e8706a
--- /dev/null
+++ b/pxp-monitor/.gitignore
@@ -0,0 +1,30 @@
+lt application files
+*.apk
+*.ap_
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# generated files
+bin/
+gen/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Eclipse project files
+.classpath
+.project
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Intellij project files
+*.iml
+*.ipr
+*.iws
+.idea/
+
diff --git a/pxp-monitor/Android.mk b/pxp-monitor/Android.mk
new file mode 100644
index 0000000..5cedf1a
--- /dev/null
+++ b/pxp-monitor/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ src/org/codeaurora/bluetooth/pxpservice/IPxpService.aidl
+
+LOCAL_PACKAGE_NAME := pxp-monitor
+LOCAL_CERTIFICATE := platform
+
+LOCAL_MODULE_OWNER := qcom
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/pxp-monitor/AndroidManifest.xml b/pxp-monitor/AndroidManifest.xml
new file mode 100644
index 0000000..c984c0a
--- /dev/null
+++ b/pxp-monitor/AndroidManifest.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.codeaurora.bluetooth.pxpmonitor"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="18"
+ android:targetSdkVersion="18" />
+
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+
+ <uses-feature
+ android:name="android.hardware.bluetooth_le"
+ android:required="true" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".DeviceActivity" />
+ <activity android:name=".ScanDevicesActivity" />
+ <activity android:name=".PariedDevicesActivity" />
+ <activity android:name=".ConnectedDevicesActivity" />
+ <activity android:name=".AlertsHistory" />
+
+ <service
+ android:name="org.codeaurora.bluetooth.pxpmonitor.PxpServiceProxy"
+ android:exported="false" >
+ </service>
+ </application>
+
+</manifest>
diff --git a/pxp-monitor/res/drawable-hdpi/ic_launcher.png b/pxp-monitor/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-hdpi/search.png b/pxp-monitor/res/drawable-hdpi/search.png
new file mode 100644
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-hdpi/search.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-mdpi/ic_launcher.png b/pxp-monitor/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..347779c
--- /dev/null
+++ b/pxp-monitor/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-mdpi/search.png b/pxp-monitor/res/drawable-mdpi/search.png
new file mode 100644
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-mdpi/search.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-xhdpi/ic_launcher.png b/pxp-monitor/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-xhdpi/search.png b/pxp-monitor/res/drawable-xhdpi/search.png
new file mode 100644
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-xhdpi/search.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-xxhdpi/ic_launcher.png b/pxp-monitor/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pxp-monitor/res/drawable-xxhdpi/search.png b/pxp-monitor/res/drawable-xxhdpi/search.png
new file mode 100755
index 0000000..f7d13f1
--- /dev/null
+++ b/pxp-monitor/res/drawable-xxhdpi/search.png
Binary files differ
diff --git a/pxp-monitor/res/layout/activity_alerts_history.xml b/pxp-monitor/res/layout/activity_alerts_history.xml
new file mode 100644
index 0000000..8dafa94
--- /dev/null
+++ b/pxp-monitor/res/layout/activity_alerts_history.xml
@@ -0,0 +1,62 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/device_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:textSize="22sp"
+ android:textStyle="bold" />
+
+ <TextView
+ android:id="@+id/device_address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="16sp" />
+
+ <TextView
+ android:id="@+id/alert_time"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:textSize="20sp" />
+
+ <TextView
+ android:id="@+id/device_rssi"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:textSize="20sp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/pxp-monitor/res/layout/activity_device.xml b/pxp-monitor/res/layout/activity_device.xml
new file mode 100644
index 0000000..cc8edd4
--- /dev/null
+++ b/pxp-monitor/res/layout/activity_device.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <fragment class="org.codeaurora.bluetooth.pxpmonitor.DeviceInfoFragment"
+ android:id="@+id/device_info_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="35" />
+
+ <fragment class="org.codeaurora.bluetooth.pxpmonitor.LinkLossFragment"
+ android:id="@+id/link_loss_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="35" />
+
+ <fragment class="org.codeaurora.bluetooth.pxpmonitor.PathLossFragment"
+ android:id="@+id/path_loss_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="35" />
+
+</LinearLayout>
diff --git a/pxp-monitor/res/layout/activity_list_devices.xml b/pxp-monitor/res/layout/activity_list_devices.xml
new file mode 100644
index 0000000..cbef9ce
--- /dev/null
+++ b/pxp-monitor/res/layout/activity_list_devices.xml
@@ -0,0 +1,62 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/device_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="30dp"
+ android:textSize="24sp" />
+
+ <TextView
+ android:id="@+id/device_address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/device_rssi"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/device_adv_data"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:textSize="12sp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/pxp-monitor/res/layout/activity_main.xml b/pxp-monitor/res/layout/activity_main.xml
new file mode 100644
index 0000000..4162de7
--- /dev/null
+++ b/pxp-monitor/res/layout/activity_main.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <Button
+ android:id="@+id/button3"
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:onClick="searchForDevices"
+ android:text="@string/scan"
+ android:textSize="24sp" />
+
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_centerHorizontal="true"
+ android:layout_above="@id/button3"
+ android:onClick="showPairedDevices"
+ android:text="@string/paired"
+ android:textSize="24sp" />
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_above="@id/button2"
+ android:layout_alignLeft="@+id/button2"
+ android:layout_alignRight="@+id/button2"
+ android:onClick="showConnectedDevices"
+ android:text="@string/connected"
+ android:textSize="24sp" />
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@+id/button3"
+ android:onClick="connectToDevice"
+ android:text="@string/connect_to"
+ android:textSize="24sp" />
+
+ <Button
+ android:id="@+id/button5"
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@+id/button4"
+ android:onClick="showAlertHistory"
+ android:text="@string/history"
+ android:textSize="24sp" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/pxp-monitor/res/layout/connect_to_device_dialog_fragment.xml b/pxp-monitor/res/layout/connect_to_device_dialog_fragment.xml
new file mode 100644
index 0000000..09dcce7
--- /dev/null
+++ b/pxp-monitor/res/layout/connect_to_device_dialog_fragment.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <EditText
+ android:id="@+id/device_address"
+ android:layout_width="250dp"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="text"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:layout_centerHorizontal="true"/>
+
+</RelativeLayout>
diff --git a/pxp-monitor/res/layout/device_info_fragment.xml b/pxp-monitor/res/layout/device_info_fragment.xml
new file mode 100644
index 0000000..a5eba15
--- /dev/null
+++ b/pxp-monitor/res/layout/device_info_fragment.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView android:id="@+id/device_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ android:layout_marginTop="8dp"/>
+
+ <TextView android:id="@+id/device_address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="12sp"
+ android:layout_marginTop="8dp"/>
+
+</LinearLayout>
diff --git a/pxp-monitor/res/layout/link_loss_fragment.xml b/pxp-monitor/res/layout/link_loss_fragment.xml
new file mode 100644
index 0000000..a57a96a
--- /dev/null
+++ b/pxp-monitor/res/layout/link_loss_fragment.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/link_loss"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/link"
+ android:textSize="18sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <ToggleButton
+ android:id="@+id/link_off"
+ android:layout_width="110dp"
+ android:layout_height="wrap_content"
+ android:checked="false"
+ android:text="@string/off"
+ android:textOff="@string/off"
+ android:textOn="@string/off"
+ android:layout_marginTop="8dp"
+ android:layout_marginLeft="8dp"/>
+
+ <ToggleButton
+ android:id="@+id/link_mild"
+ android:layout_width="110dp"
+ android:layout_height="wrap_content"
+ android:checked="false"
+ android:text="@string/mild"
+ android:textOff="@string/mild"
+ android:textOn="@string/mild"
+ android:layout_marginTop="8dp"/>
+
+ <ToggleButton
+ android:id="@+id/link_high"
+ android:layout_width="110dp"
+ android:layout_height="wrap_content"
+ android:checked="false"
+ android:text="@string/high"
+ android:textOff="@string/high"
+ android:textOn="@string/high"
+ android:layout_marginTop="8dp"/>
+
+ </LinearLayout>
+</LinearLayout>
+
diff --git a/pxp-monitor/res/layout/path_loss_fragment.xml b/pxp-monitor/res/layout/path_loss_fragment.xml
new file mode 100644
index 0000000..58b7273
--- /dev/null
+++ b/pxp-monitor/res/layout/path_loss_fragment.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/path_loss"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/path"
+ android:textSize="18sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <ToggleButton
+ android:id="@+id/path_off"
+ android:layout_width="110dp"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="8dp"
+ android:checked="false"
+ android:text="@string/off"
+ android:textOff="@string/off"
+ android:textOn="@string/off" />
+
+ <ToggleButton
+ android:id="@+id/path_mild"
+ android:layout_width="110dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:checked="false"
+ android:text="@string/mild"
+ android:textOff="@string/mild"
+ android:textOn="@string/mild" />
+
+ <ToggleButton
+ android:id="@+id/path_high"
+ android:layout_width="110dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:checked="false"
+ android:text="@string/high"
+ android:textOff="@string/high"
+ android:textOn="@string/high" />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/set_threshold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="100dp"
+ android:text="@string/threshold"
+ android:textSize="18sp" />
+
+ <TextView
+ android:id="@+id/threshold_min"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/threshold_min"
+ android:textSize="18sp" />
+
+ <EditText
+ android:id="@+id/threshold_min_value"
+ android:layout_width="155dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:ems="10"
+ android:inputType="numberSigned" />
+
+ <TextView
+ android:id="@+id/threshold_max"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/threshold_max"
+ android:textSize="18sp" />
+
+ <EditText
+ android:id="@+id/threshold_max_value"
+ android:layout_width="155dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:ems="10"
+ android:inputType="numberSigned" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/pxp-monitor/res/menu/device.xml b/pxp-monitor/res/menu/device.xml
new file mode 100644
index 0000000..3a2d30d
--- /dev/null
+++ b/pxp-monitor/res/menu/device.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:id="@+id/action_settings"
+ android:orderInCategory="1"
+ android:showAsAction="ifRoom"
+ android:title="@string/action_settings"/>
+
+ <item android:id="@+id/menu_disconnect"
+ android:title="@string/menu_disconnect"
+ android:orderInCategory="100"
+ android:showAsAction="ifRoom|withText"/>
+
+ <item android:id="@+id/menu_connect"
+ android:title="@string/menu_connect"
+ android:orderInCategory="101"
+ android:showAsAction="ifRoom|withText"/>
+</menu>
diff --git a/pxp-monitor/res/menu/main.xml b/pxp-monitor/res/menu/main.xml
new file mode 100644
index 0000000..95c3298
--- /dev/null
+++ b/pxp-monitor/res/menu/main.xml
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="ifRoom"
+ android:title="@string/action_settings"/>
+</menu>
diff --git a/pxp-monitor/res/menu/scan.xml b/pxp-monitor/res/menu/scan.xml
new file mode 100644
index 0000000..18359cd
--- /dev/null
+++ b/pxp-monitor/res/menu/scan.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:id="@+id/action_search"
+ android:icon="@drawable/search"
+ android:orderInCategory="100"
+ android:showAsAction="ifRoom" />
+
+ <item android:id="@+id/menu_stop"
+ android:title="@string/menu_stop"
+ android:orderInCategory="101"
+ android:showAsAction="ifRoom|withText"/>
+</menu>
diff --git a/pxp-monitor/res/values-sw600dp/dimens.xml b/pxp-monitor/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..8b8679c
--- /dev/null
+++ b/pxp-monitor/res/values-sw600dp/dimens.xml
@@ -0,0 +1,36 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <!--
+ Customize dimensions originally defined in res/values/dimens.xml (such as
+ screen margins) for sw600dp devices (e.g. 7" tablets) here.
+ -->
+
+</resources>
diff --git a/pxp-monitor/res/values-sw720dp-land/dimens.xml b/pxp-monitor/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..dcb6433
--- /dev/null
+++ b/pxp-monitor/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,37 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <!--
+ Customize dimensions originally defined in res/values/dimens.xml (such as
+ screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
+ -->
+ <dimen name="activity_horizontal_margin">128dp</dimen>
+
+</resources>
diff --git a/pxp-monitor/res/values-v11/styles.xml b/pxp-monitor/res/values-v11/styles.xml
new file mode 100644
index 0000000..77efabc
--- /dev/null
+++ b/pxp-monitor/res/values-v11/styles.xml
@@ -0,0 +1,39 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
diff --git a/pxp-monitor/res/values-v14/styles.xml b/pxp-monitor/res/values-v14/styles.xml
new file mode 100644
index 0000000..165ee27
--- /dev/null
+++ b/pxp-monitor/res/values-v14/styles.xml
@@ -0,0 +1,40 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
diff --git a/pxp-monitor/res/values/dimens.xml b/pxp-monitor/res/values/dimens.xml
new file mode 100644
index 0000000..c64c4c0
--- /dev/null
+++ b/pxp-monitor/res/values/dimens.xml
@@ -0,0 +1,35 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/pxp-monitor/res/values/strings.xml b/pxp-monitor/res/values/strings.xml
new file mode 100644
index 0000000..d15d12e
--- /dev/null
+++ b/pxp-monitor/res/values/strings.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <string name="off">OFF</string>
+ <string name="mild">MILD</string>
+ <string name="high">HIGH</string>
+ <string name="link">Link Loss Level</string>
+ <string name="path">Path Loss Level</string>
+ <string name="threshold">Set threshold</string>
+ <string name="threshold_min">Min threshold</string>
+ <string name="threshold_max">Max threshold</string>
+ <string name="app_name">Proximity Monitor</string>
+ <string name="action_settings">Settings</string>
+ <string name="menu_disconnect">Disconnect</string>
+ <string name="menu_connect">Connect</string>
+ <string name="menu_stop">Stop</string>
+ <string name="connected">Connected devices</string>
+ <string name="paired">Connect to paired dvice</string>
+ <string name="scan">Scan for a device</string>
+ <string name="connect_to">Connect to device</string>
+ <string name="history">Alert history</string>
+ <string name="device_address">Connect to</string>
+ <string name="title">Insert bluetooth device address</string>
+ <string name="connect">Connect</string>
+
+</resources> \ No newline at end of file
diff --git a/pxp-monitor/res/values/styles.xml b/pxp-monitor/res/values/styles.xml
new file mode 100644
index 0000000..cbf3ff2
--- /dev/null
+++ b/pxp-monitor/res/values/styles.xml
@@ -0,0 +1,48 @@
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertInformation.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertInformation.java
new file mode 100644
index 0000000..af36c7b
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertInformation.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.bluetooth.BluetoothDevice;
+
+public class AlertInformation {
+ public BluetoothDevice device;
+ public String date;
+ public int rssi;
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertsHistory.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertsHistory.java
new file mode 100644
index 0000000..f17c2e7
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/AlertsHistory.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class AlertsHistory extends ListActivity {
+
+ private static final String TAG = AlertsHistory.class.getSimpleName();
+
+ private static final int REQUEST_ENABLE_BT = 1;
+
+ private static AlertHistoryAdapter mAlertHistoryAdapter = null;
+
+ private BluetoothAdapter mBluetoothAdapter = null;
+
+ private PxpServiceProxy mPxpServiceProxy = null;
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mPxpServiceProxy = ((PxpServiceProxy.LocalBinder) service).getService();
+
+ if (mPxpServiceProxy == null) {
+ return;
+ }
+ listAlerts();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpServiceProxy = null;
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ getActionBar().setTitle("Alert History");
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent(this, PxpServiceProxy.class);
+
+ if (bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE) == false) {
+ Log.e(TAG, "Unable to bind");
+ }
+
+ final BluetoothManager bluetoothManager =
+ (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = bluetoothManager.getAdapter();
+
+ mAlertHistoryAdapter = new AlertHistoryAdapter(this);
+ setListAdapter(mAlertHistoryAdapter);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (!mBluetoothAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+
+ if (mPxpServiceProxy != null) {
+ mAlertHistoryAdapter.clear();
+ listAlerts();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ unbindService(mConnection);
+ mPxpServiceProxy = null;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+ finish();
+ return;
+ }
+
+ if (mPxpServiceProxy != null) {
+ listAlerts();
+ }
+ }
+
+ private void listAlerts() {
+ Iterator<AlertInformation> iterator =
+ mPxpServiceProxy.mAlertHistory.iterator();
+
+ while (iterator.hasNext()) {
+ mAlertHistoryAdapter.addAlert(iterator.next());
+ mAlertHistoryAdapter.notifyDataSetChanged();
+ }
+
+ }
+
+ private class AlertHistoryAdapter extends BaseAdapter {
+
+ private ArrayList<AlertInformation> mAlertInf;
+
+ private LayoutInflater mInflater;
+
+ private TextView mDeviceName;
+
+ private TextView mDeviceAddress;
+
+ private TextView mTime;
+
+ private TextView mRssi;
+
+ public AlertHistoryAdapter(Context context) {
+ super();
+
+ mAlertInf = new ArrayList<AlertInformation>();
+ mInflater = LayoutInflater.from(context);
+ }
+
+ public void addAlert(AlertInformation alert) {
+ if (!mAlertInf.contains(alert)) {
+ mAlertInf.add(alert);
+ }
+ }
+
+ public void clear() {
+ mAlertInf.clear();
+ this.notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mAlertInf.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mAlertInf.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+
+ if (view == null) {
+ view = mInflater.inflate(R.layout.activity_alerts_history, null);
+ }
+
+ mDeviceName = (TextView) view.findViewById(R.id.device_name);
+ mDeviceAddress = (TextView) view.findViewById(R.id.device_address);
+ mTime = (TextView) view.findViewById(R.id.alert_time);
+ mRssi = (TextView) view.findViewById(R.id.device_rssi);
+
+ Log.e(TAG, "i: " + i);
+
+ AlertInformation alert = mAlertInf.get(i);
+
+ final String deviceName = alert.device.getName();
+
+ if (deviceName != null && deviceName.length() > 0) {
+ mDeviceName.setText(deviceName);
+
+ } else {
+ mDeviceName.setText("Unknow device");
+ }
+
+ mDeviceAddress.setText(alert.device.getAddress());
+
+ mTime.setText(alert.date);
+ mRssi.setText("RSSI = " + String.valueOf(alert.rssi) + "dBm");
+
+ return view;
+ }
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectToDeviceDialogFragment.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectToDeviceDialogFragment.java
new file mode 100644
index 0000000..b3e5ca2
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectToDeviceDialogFragment.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+
+public class ConnectToDeviceDialogFragment extends DialogFragment {
+
+ private EditText mEditText;
+
+ private ConnectToDeviceDialogListener mListener;
+
+ public interface ConnectToDeviceDialogListener {
+ public void onConnectToDeviceDialogPositive(String address);
+ };
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+
+ View view = inflater.inflate(R.layout.connect_to_device_dialog_fragment, null);
+
+ mEditText = (EditText) view.findViewById(R.id.device_address);
+
+ builder.setTitle(R.string.title);
+ builder.setView(view)
+ .setPositiveButton(R.string.connect, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ String address = mEditText.getText().toString();;
+
+ mListener.onConnectToDeviceDialogPositive(address);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null);
+ return builder.create();
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ try {
+ mListener = (MainActivity) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(this.getClass().getSimpleName()
+ + " can be only attached to " + MainActivity.class.getSimpleName());
+ }
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectedDevicesActivity.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectedDevicesActivity.java
new file mode 100644
index 0000000..4968123
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ConnectedDevicesActivity.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ConnectedDevicesActivity extends ListActivity {
+
+ private static final String TAG = ConnectedDevicesActivity.class.getSimpleName();
+
+ public static final String DEVICE_CONNECTED_SELECTED = "android.bluetooth.devicepicker.action.DEVICE_SELECTED";
+
+ private static final int REQUEST_ENABLE_BT = 1;
+
+ private ConnectedDeviceAdapter mConnectedDeviceAdapter;
+
+ private BluetoothAdapter mBluetoothAdapter = null;
+
+ private PxpServiceProxy mPxpServiceProxy = null;
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mPxpServiceProxy = ((PxpServiceProxy.LocalBinder) service).getService();
+
+ if (mPxpServiceProxy == null) {
+ return;
+ }
+
+ listConnectedDevices();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpServiceProxy = null;
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent(this, PxpServiceProxy.class);
+
+ if (bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE) == false) {
+ Log.e(TAG, "Unable to bind");
+ }
+
+ final BluetoothManager bluetoothManager =
+ (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = bluetoothManager.getAdapter();
+
+ mConnectedDeviceAdapter = new ConnectedDeviceAdapter(this);
+ setListAdapter(mConnectedDeviceAdapter);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (!mBluetoothAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+
+ if (mPxpServiceProxy != null) {
+ mConnectedDeviceAdapter.clear();
+ listConnectedDevices();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ unbindService(mConnection);
+ mPxpServiceProxy = null;
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+ finish();
+ return;
+ }
+
+ if (mPxpServiceProxy != null) {
+ listConnectedDevices();
+ }
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+
+ final BluetoothDevice leDevice = mConnectedDeviceAdapter.getDevice(position);
+
+ if (leDevice == null) {
+ return;
+ }
+
+ final Intent intent = new Intent(this, DeviceActivity.class);
+
+ intent.setAction(DEVICE_CONNECTED_SELECTED);
+ intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.putExtra(DeviceActivity.EXTRAS_DEVICE, leDevice);
+
+ startActivity(intent);
+ }
+
+ private synchronized void listConnectedDevices() {
+
+ List<BluetoothDevice> connectedDevices = mPxpServiceProxy.getConnectedDevices();
+
+ Iterator<BluetoothDevice> iterator = connectedDevices.iterator();
+
+ while (iterator.hasNext()) {
+ mConnectedDeviceAdapter.addDevice(iterator.next());
+ mConnectedDeviceAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private class ConnectedDeviceAdapter extends BaseAdapter {
+
+ private ArrayList<BluetoothDevice> mLeDevices;
+
+ private LayoutInflater mInflater;
+
+ private TextView mDeviceName;
+
+ private TextView mDeviceAddress;
+
+ public ConnectedDeviceAdapter(Context context) {
+ super();
+
+ mLeDevices = new ArrayList<BluetoothDevice>();
+ mInflater = LayoutInflater.from(context);
+ }
+
+ public void addDevice(BluetoothDevice device) {
+
+ if (!mLeDevices.contains(device)) {
+ mLeDevices.add(device);
+ }
+ }
+
+ public BluetoothDevice getDevice(int position) {
+ return mLeDevices.get(position);
+ }
+
+ public void clear() {
+ mLeDevices.clear();
+ this.notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mLeDevices.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mLeDevices.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+
+ if (view == null) {
+ view = mInflater.inflate(R.layout.activity_list_devices, null);
+ }
+
+ mDeviceName = (TextView) view.findViewById(R.id.device_name);
+ mDeviceAddress = (TextView) view.findViewById(R.id.device_address);
+
+ BluetoothDevice device = mLeDevices.get(i);
+
+ final String deviceName = device.getName();
+
+ if (deviceName != null && deviceName.length() > 0) {
+ mDeviceName.setText(deviceName);
+
+ } else {
+ mDeviceName.setText("Unknow device");
+ }
+
+ mDeviceAddress.setText(device.getAddress());
+
+ return view;
+ }
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceActivity.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceActivity.java
new file mode 100644
index 0000000..ab12551
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceActivity.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+public class DeviceActivity extends Activity {
+
+ private static final String TAG = DeviceActivity.class.getSimpleName();
+
+ public static final String EXTRAS_DEVICE = "BLUETOOTH_DEVICE";
+
+ private static final int REQUEST_ENABLE_BT = 1;
+
+ private BluetoothAdapter mBluetoothAdapter = null;
+
+ protected PxpServiceProxy mPxpServiceProxy = null;
+
+ protected BluetoothDevice mLeDevice = null;
+
+ private DeviceInfoFragment mDeviceInfoFragment = null;
+
+ private LinkLossFragment mLinkLossFragment = null;
+
+ private PathLossFragment mPathLossFragment = null;
+
+ private Uri mLinkNotification = null;
+
+ private Uri mPathNotification = null;
+
+ private Ringtone mLinkRingtone = null;
+
+ private Ringtone mPathRingtone = null;
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.d(TAG, "Connecting to service");
+ mPxpServiceProxy = ((PxpServiceProxy.LocalBinder) service).getService();
+
+ if (mPxpServiceProxy == null) {
+ return;
+ }
+
+ PxpServiceProxy.registerClient(mHandler);
+
+ Intent intent = getIntent();
+ String action = intent.getAction();
+
+ if (ConnectedDevicesActivity.DEVICE_CONNECTED_SELECTED.
+ equals(action)) {
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+
+ } else if (PairedDevicesActivity.DEVICE_PAIRED_SELECTED.
+ equals(action)) {
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+
+ if (mLeDevice != null && mPxpServiceProxy.connect(mLeDevice)) {
+ Log.d(TAG, "Pxp device connected");
+ }
+
+ } else if (ScanDevicesActivity.DEVICE_NOT_CONNECTED_SELECTED.
+ equals(action)) {
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+
+ if (mLeDevice != null && mPxpServiceProxy.connect(mLeDevice)) {
+ Log.d(TAG, "Pxp device connected");
+ }
+ return;
+
+ } else if (MainActivity.DEVICE_BY_ADDRESS_SELECTED.
+ equals(action)) {
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+
+ if (mLeDevice != null && mPxpServiceProxy.connect(mLeDevice)) {
+ Log.d(TAG, "Pxp device connected");
+ }
+ }
+
+ if (mLeDevice != null && mPxpServiceProxy.isPropertiesSet(mLeDevice)) {
+ setInfo();
+ invalidateOptionsMenu();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpServiceProxy = null;
+ }
+ };
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ CharSequence toastText = null;
+
+ switch (msg.what) {
+
+ case PxpServiceProxy.MSG_DEVICE_CONNECTED:
+ Log.d(TAG, "PxpServiceProxy.MSG_DEVICE_CONNECTED");
+
+ mLeDevice = (BluetoothDevice) msg.obj;
+
+ if (mLinkRingtone.isPlaying()) {
+ mLinkRingtone.stop();
+ }
+
+ this.removeMessages(PxpServiceProxy.MSG_LINK_LOSS_TIMEOUT);
+
+ toastText = "Connected";
+
+ if (mPxpServiceProxy.isPropertiesSet(mLeDevice)) {
+ setInfo();
+ }
+ break;
+
+ case PxpServiceProxy.MSG_DEVICE_DISCONNECTED:
+ Log.d(TAG, "PxpServiceProxy.MSG_DEVICE_DISCONNECTED");
+
+ mLeDevice = (BluetoothDevice) msg.obj;
+
+ if (mLeDevice.equals(mLeDevice)) {
+ toastText = "Disconnected";
+ mLinkLossFragment.init();
+ mPathLossFragment.init();
+ }
+ break;
+
+ case PxpServiceProxy.MSG_MISSING_LLS_SERVICE:
+ Log.d(TAG, "PxpServiceProxy.MSG_MISSING_LLS_SERVICE");
+ toastText = "Device not connected - Link Loss Service not found";
+ break;
+
+ case PxpServiceProxy.MSG_LINKLOSS_ALERT:
+ Log.d(TAG, "PxpServiceProxy.MSG_LINKLOSS_ALERT");
+
+ int llsAlertValue = (Integer) msg.obj;
+ mLinkLossFragment.init();
+ mPathLossFragment.init();
+
+ // No alerting if alertLevel == 0
+ if (llsAlertValue == 0) {
+ return;
+ }
+
+ this.sendMessageDelayed(
+ this.obtainMessage(PxpServiceProxy.MSG_LINK_LOSS_TIMEOUT),
+ PxpServiceProxy.LINK_LOSS_ALERT_TIMEOUT);
+
+ mLinkRingtone.play();
+ break;
+
+ case PxpServiceProxy.MSG_PATHLOSS_ALERT:
+ if (!mPathRingtone.isPlaying()) {
+ mPathRingtone.play();
+ }
+ break;
+
+ case PxpServiceProxy.MSG_LINK_LOSS_TIMEOUT:
+ mLinkRingtone.stop();
+ break;
+
+ case PxpServiceProxy.MSG_ALERT_FINISH:
+ if (mPathRingtone.isPlaying()) {
+ mPathRingtone.stop();
+ }
+ break;
+
+ default:
+ super.handleMessage(msg);
+ }
+
+ if (toastText != null) {
+ Toast toast = Toast.makeText(DeviceActivity.this, toastText, Toast.LENGTH_SHORT);
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.show();
+ }
+
+ invalidateOptionsMenu();
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.activity_device);
+
+ mDeviceInfoFragment = (DeviceInfoFragment) getFragmentManager().findFragmentById(
+ R.id.device_info_fragment);
+ mLinkLossFragment = (LinkLossFragment) getFragmentManager().findFragmentById(
+ R.id.link_loss_fragment);
+ mPathLossFragment = (PathLossFragment) getFragmentManager().findFragmentById(
+ R.id.path_loss_fragment);
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent(this, PxpServiceProxy.class);
+
+ if (bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE) == false) {
+ Log.e(TAG, "Unable to bind");
+ }
+
+ final BluetoothManager bluetoothManager =
+ (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = bluetoothManager.getAdapter();
+
+ mLinkNotification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
+ mLinkRingtone = RingtoneManager.getRingtone(getApplicationContext(), mLinkNotification);
+
+ mPathNotification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+ mPathRingtone = RingtoneManager.getRingtone(getApplicationContext(), mPathNotification);
+
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (!mBluetoothAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+
+ if (mLeDevice != null && mPxpServiceProxy.isPropertiesSet(mLeDevice)) {
+ setInfo();
+ invalidateOptionsMenu();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (mLinkRingtone.isPlaying()) {
+ mLinkRingtone.stop();
+ }
+
+ mLinkRingtone = null;
+ mLinkNotification = null;
+
+ if (mPathRingtone.isPlaying()) {
+ mPathRingtone.stop();
+ }
+
+ mPathRingtone = null;
+ mPathNotification = null;
+
+ unbindService(mConnection);
+ mPxpServiceProxy = null;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+ if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+ finish();
+ return;
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.device, menu);
+
+ if (!mPxpServiceProxy.isPropertiesSet(mLeDevice)) {
+ return false;
+ }
+
+ if (mPxpServiceProxy.getConnectionState(mLeDevice)) {
+ menu.findItem(R.id.menu_disconnect).setVisible(true);
+ menu.findItem(R.id.menu_connect).setVisible(false);
+
+ } else {
+ menu.findItem(R.id.menu_disconnect).setVisible(false);
+ menu.findItem(R.id.menu_connect).setVisible(true);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_disconnect:
+ Log.d(TAG, "Disconnecting");
+ mPxpServiceProxy.disconnect(mLeDevice);
+ break;
+
+ case R.id.menu_connect:
+ Log.d(TAG, "Connecting");
+ if (mPxpServiceProxy.connect(mLeDevice) == true) {
+ setInfo();
+ }
+ invalidateOptionsMenu();
+ break;
+ }
+ return true;
+ }
+
+ void setInfo() {
+
+ final int LinkLossService = 0;
+ final int ImmediateAlertService = 1;
+ final int TxPowerService = 2;
+
+ mDeviceInfoFragment.setDeviceInfo(mLeDevice.getName(), mLeDevice.getAddress());
+
+ mLinkLossFragment.onServiceFound(mPxpServiceProxy.checkServiceStatus(mLeDevice,
+ LinkLossService));
+
+ mPathLossFragment.onServiceFound(
+ mPxpServiceProxy.checkServiceStatus(mLeDevice, ImmediateAlertService),
+ mPxpServiceProxy.checkServiceStatus(mLeDevice, TxPowerService));
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceInfoFragment.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceInfoFragment.java
new file mode 100644
index 0000000..0174355
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/DeviceInfoFragment.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class DeviceInfoFragment extends Fragment {
+
+ private TextView mDeviceName;
+
+ private TextView mDeviceAddress;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View view = inflater.inflate(R.layout.device_info_fragment, container, false);
+
+ mDeviceName = ((TextView) view.findViewById(R.id.device_name));
+ mDeviceAddress = ((TextView) view.findViewById(R.id.device_address));
+
+ return view;
+ }
+
+ public void setDeviceInfo(String deviceName, String deviceAdress) {
+ mDeviceName.setText(deviceName);
+ mDeviceAddress.setText(deviceAdress);
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/LinkLossFragment.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/LinkLossFragment.java
new file mode 100644
index 0000000..ce877d7
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/LinkLossFragment.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+import android.widget.ToggleButton;
+
+public class LinkLossFragment extends Fragment implements View.OnClickListener {
+
+ private static final String TAG = LinkLossFragment.class.getSimpleName();
+
+ private DeviceActivity mActivity;
+
+ private ToggleButton mLinkLossButtons[] = new ToggleButton[3];
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.link_loss_fragment, container, false);
+
+ mLinkLossButtons[0] = (ToggleButton) view.findViewById(R.id.link_off);
+ mLinkLossButtons[1] = (ToggleButton) view.findViewById(R.id.link_mild);
+ mLinkLossButtons[2] = (ToggleButton) view.findViewById(R.id.link_high);
+
+ for (ToggleButton btn : mLinkLossButtons) {
+ btn.setEnabled(false);
+ btn.setOnClickListener(this);
+ }
+
+ return view;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ try {
+ mActivity = (DeviceActivity) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(this.getClass().getSimpleName()
+ + " can be only attached to " + MainActivity.class.getSimpleName());
+ }
+ }
+
+ public void init() {
+
+ for (ToggleButton btn : mLinkLossButtons) {
+ btn.setEnabled(false);
+ }
+ }
+
+ public void onServiceFound(boolean state) {
+ Log.d(TAG, "LLS service" + state);
+
+ if (state) {
+ mLinkLossButtons[0].setEnabled(true);
+ mLinkLossButtons[1].setEnabled(true);
+ mLinkLossButtons[2].setEnabled(true);
+
+ int linkLossLevel = 0;
+
+ if (mActivity.mPxpServiceProxy.getLinkLossAlertLevel(mActivity.mLeDevice) < 0) {
+ mActivity.mPxpServiceProxy.setLinkLossAlertLevel(mActivity.mLeDevice,
+ linkLossLevel);
+
+ } else {
+ linkLossLevel = mActivity.mPxpServiceProxy.
+ getLinkLossAlertLevel(mActivity.mLeDevice);
+ }
+
+ for (int i = 0; i < mLinkLossButtons.length; i++) {
+ mLinkLossButtons[i].setChecked(linkLossLevel == i);
+ }
+
+ } else {
+ init();
+ Context context = getActivity();
+ CharSequence text = "Link Loss Service not found";
+
+ Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.show();
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ ToggleButton clickedButton = (ToggleButton) v;
+
+ if (!mActivity.mPxpServiceProxy.getConnectionState(mActivity.mLeDevice)) {
+ return;
+ }
+
+ int idx;
+
+ switch (clickedButton.getId()) {
+ case R.id.link_off:
+ idx = 0;
+ break;
+
+ case R.id.link_mild:
+ idx = 1;
+ break;
+
+ case R.id.link_high:
+ idx = 2;
+ break;
+
+ default:
+ return;
+ }
+
+ for (int i = 0; i < mLinkLossButtons.length; i++) {
+ ToggleButton btn = mLinkLossButtons[i];
+
+ if (mLinkLossButtons[idx].isChecked()) {
+
+ if (i != idx) {
+ btn.setChecked(false);
+ }
+
+ } else {
+ btn.setChecked(i == 0);
+ idx = 0;
+ }
+ }
+
+ mActivity.mPxpServiceProxy.setLinkLossAlertLevel(mActivity.mLeDevice, idx);
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/MainActivity.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/MainActivity.java
new file mode 100644
index 0000000..63813a1
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/MainActivity.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.Menu;
+import android.view.View;
+import android.widget.Toast;
+
+import org.codeaurora.bluetooth.pxpmonitor.ConnectToDeviceDialogFragment.ConnectToDeviceDialogListener;
+
+public class MainActivity extends Activity implements ConnectToDeviceDialogListener {
+
+ private static final String TAG = MainActivity.class.getSimpleName();;
+
+ private static final int REQUEST_ENABLE_BT = 1;
+
+ public static final String DEVICE_BY_ADDRESS_SELECTED =
+ "android.bluetooth.devicepicker.action.DEVICE_BY_ADDRESS_SELECTED";
+
+ protected BluetoothAdapter mBluetoothAdapter = null;
+
+ protected PxpServiceProxy mPxpServiceProxy = null;
+
+ protected Intent intent = null;
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mPxpServiceProxy = ((PxpServiceProxy.LocalBinder) service).getService();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpServiceProxy = null;
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+ Toast.makeText(this, "BLE not supported", Toast.LENGTH_SHORT).show();
+ finish();
+ }
+
+ final BluetoothManager bluetoothManager =
+ (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = bluetoothManager.getAdapter();
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent(this, PxpServiceProxy.class);
+
+ if (bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE) == false) {
+ Log.e(TAG, "Unable to bind");
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (!mBluetoothAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+ if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+ finish();
+ return;
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+
+ if (mPxpServiceProxy != null) {
+ mPxpServiceProxy.disconnectDevices();
+ }
+
+ unbindService(mConnection);
+ mPxpServiceProxy = null;
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ public void searchForDevices(View view) {
+ final Intent intent = new Intent(this, ScanDevicesActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ startActivity(intent);
+ }
+
+ public void showConnectedDevices(View view) {
+ final Intent intent = new Intent(this, ConnectedDevicesActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ startActivity(intent);
+ }
+
+ public void showPairedDevices(View view) {
+ final Intent intent = new Intent(this, PairedDevicesActivity.class);
+ startActivity(intent);
+ }
+
+ public void connectToDevice(View view) {
+ ConnectToDeviceDialogFragment newFragment = new ConnectToDeviceDialogFragment();
+ newFragment.show(getFragmentManager(), "address");
+ }
+
+ public void showAlertHistory(View view) {
+ final Intent intent = new Intent(this, AlertsHistory.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onConnectToDeviceDialogPositive(String address) {
+ BluetoothDevice leDevice = null;
+
+ if (BluetoothAdapter.checkBluetoothAddress(address)) {
+
+ leDevice = mBluetoothAdapter.getRemoteDevice(address);
+
+ final Intent intent = new Intent(this, DeviceActivity.class);
+ intent.setAction(DEVICE_BY_ADDRESS_SELECTED);
+ intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.putExtra(DeviceActivity.EXTRAS_DEVICE, leDevice);
+ startActivity(intent);
+
+ } else {
+ Log.w(TAG, "Wrong device address");
+ }
+
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PairedDevicesActivity.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PairedDevicesActivity.java
new file mode 100644
index 0000000..d010790
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PairedDevicesActivity.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.ListActivity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+public class PairedDevicesActivity extends ListActivity {
+
+ private static final String TAG = PairedDevicesActivity.class.getSimpleName();
+
+ private static final int REQUEST_ENABLE_BT = 1;
+
+ public static final String DEVICE_PAIRED_SELECTED =
+ "android.bluetooth.devicepicker.action.DEVICE_PAIRED_SELECTED";
+
+ private PairedDevicesListAdapter mPairedDeviceListAdapter;
+
+ private BluetoothAdapter mAdapter = null;
+
+ private PxpServiceProxy mPxpServiceProxy = null;
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.d(TAG, "Connecting to service");
+ mPxpServiceProxy = ((PxpServiceProxy.LocalBinder) service).getService();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpServiceProxy = null;
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ getActionBar().setTitle("Paired Devices");
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent(this, PxpServiceProxy.class);
+
+ if (bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE) == false) {
+ Log.e(TAG, "Unable to bind");
+ }
+
+ final BluetoothManager bluetoothManager =
+ (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mAdapter = bluetoothManager.getAdapter();
+
+ mPairedDeviceListAdapter = new PairedDevicesListAdapter(this);
+ setListAdapter(mPairedDeviceListAdapter);
+ getPairedDevices();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (!mAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+
+ mPairedDeviceListAdapter.clear();
+ getPairedDevices();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_ENABLE_BT) {
+ getPairedDevices();
+ }
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+
+ final BluetoothDevice leDevice = mPairedDeviceListAdapter.getDevice(position);
+
+ if (leDevice == null) {
+ return;
+ }
+
+ Log.d(TAG, "Trying to connect to paired device :" + leDevice.getAddress());
+
+ final Intent intent = new Intent(this, DeviceActivity.class);
+ intent.setAction(DEVICE_PAIRED_SELECTED);
+ intent.putExtra(DeviceActivity.EXTRAS_DEVICE, leDevice);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ unbindService(mConnection);
+ mPxpServiceProxy = null;
+ }
+
+ private void getPairedDevices() {
+ Set<BluetoothDevice> devices = mAdapter.getBondedDevices();
+
+ for (BluetoothDevice device : devices) {
+ mPairedDeviceListAdapter.addDevice(device);
+ mPairedDeviceListAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private class PairedDevicesListAdapter extends BaseAdapter {
+
+ private ArrayList<BluetoothDevice> mLeDevices;
+
+ private LayoutInflater mInflater;
+
+ private TextView mDeviceName;
+
+ private TextView mDeviceAddress;
+
+ public PairedDevicesListAdapter(Context context) {
+ super();
+ mLeDevices = new ArrayList<BluetoothDevice>();
+ mInflater = LayoutInflater.from(context);
+ }
+
+ public void addDevice(BluetoothDevice device) {
+ if (!mLeDevices.contains(device)) {
+ mLeDevices.add(device);
+ }
+ }
+
+ public BluetoothDevice getDevice(int position) {
+ return mLeDevices.get(position);
+ }
+
+ public void clear() {
+ mLeDevices.clear();
+ this.notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mLeDevices.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mLeDevices.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+
+ if (view == null) {
+ view = mInflater.inflate(R.layout.activity_list_devices, null);
+ }
+
+ mDeviceName = (TextView) view.findViewById(R.id.device_name);
+ mDeviceAddress = (TextView) view.findViewById(R.id.device_address);
+
+ BluetoothDevice device = mLeDevices.get(i);
+
+ final String deviceName = device.getName();
+
+ if (deviceName != null && deviceName.length() > 0) {
+ mDeviceName.setText(deviceName);
+
+ } else {
+ mDeviceName.setText("Unknown device");
+ }
+
+ mDeviceAddress.setText(device.getAddress());
+
+ return view;
+ }
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PathLossFragment.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PathLossFragment.java
new file mode 100644
index 0000000..dc2f7ba
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PathLossFragment.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ToggleButton;
+
+public class PathLossFragment extends Fragment implements View.OnClickListener {
+
+ private static final String TAG = PathLossFragment.class.getSimpleName();
+
+ private static final short TX_POWER_MIN = -100;
+
+ private static final short TX_POWER_MAX = 20;
+
+ private static final short RSSI_MIN = -127;
+
+ private static final short RSSI_MAX = 20;
+
+ private static final short THRESHOLD_MIN = TX_POWER_MIN - RSSI_MAX; // -120
+
+ private static final short THRESHOLD_MAX = TX_POWER_MAX - RSSI_MIN; // 147
+
+ private DeviceActivity mActivity;
+
+ private ToggleButton mPathLossButtons[] = new ToggleButton[3];
+
+ private EditText mMinValue;
+
+ private EditText mMaxValue;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.path_loss_fragment, null, false);
+
+ mPathLossButtons[0] = (ToggleButton) view.findViewById(R.id.path_off);
+ mPathLossButtons[1] = (ToggleButton) view.findViewById(R.id.path_mild);
+ mPathLossButtons[2] = (ToggleButton) view.findViewById(R.id.path_high);
+ mMinValue = (EditText) view.findViewById(R.id.threshold_min_value);
+ mMaxValue = (EditText) view.findViewById(R.id.threshold_max_value);
+
+ mMinValue.setOnEditorActionListener(new EditText.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+
+ CharSequence text = null;
+
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ int threshold = Integer.parseInt(mMinValue.getText().toString());
+
+ if (threshold > THRESHOLD_MAX) {
+
+ text = "Threshold is to big. Changing to "
+ + Integer.toString(THRESHOLD_MAX);
+
+ threshold = THRESHOLD_MAX;
+ mMinValue.setText(String.valueOf(threshold));
+
+ } else if (threshold < THRESHOLD_MIN) {
+
+ text = "Threshold is to small. Changing to "
+ + Integer.toString(THRESHOLD_MIN);
+
+ threshold = THRESHOLD_MIN;
+ mMinValue.setText(String.valueOf(threshold));
+ }
+
+ if (text != null) {
+ Context context = getActivity();
+
+ Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.show();
+ }
+
+ mActivity.mPxpServiceProxy.setMinPathLossThreshold(mActivity.mLeDevice,
+ threshold);
+
+ final InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
+
+ return true;
+ }
+ return false;
+ }
+ });
+
+ mMaxValue.setOnEditorActionListener(new EditText.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+
+ CharSequence text = null;
+
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ int threshold = Integer.parseInt(mMaxValue.getText().toString());
+
+ if (threshold > THRESHOLD_MAX) {
+
+ text = "Threshold is to big. Changing to "
+ + Integer.toString(THRESHOLD_MAX);
+
+ threshold = THRESHOLD_MAX;
+ mMaxValue.setText(String.valueOf(threshold));
+
+ } else if (threshold < THRESHOLD_MIN) {
+
+ text = "Threshold is to small. Changing to "
+ + Integer.toString(THRESHOLD_MIN);
+
+ threshold = THRESHOLD_MIN;
+ mMaxValue.setText(String.valueOf(threshold));
+ }
+
+ if (text != null) {
+ Context context = getActivity();
+
+ Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.show();
+ }
+
+ mActivity.mPxpServiceProxy.setMaxPathLossThreshold(mActivity.mLeDevice,
+ threshold);
+
+ final InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
+
+ return true;
+ }
+ return false;
+ }
+ });
+
+ for (ToggleButton btn : mPathLossButtons) {
+ btn.setEnabled(false);
+ btn.setOnClickListener(this);
+ }
+
+ return view;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ try {
+ mActivity = (DeviceActivity) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(this.getClass().getSimpleName()
+ + " can be only attached to " + MainActivity.class.getSimpleName());
+ }
+ }
+
+ public void init() {
+
+ for (ToggleButton btn : mPathLossButtons) {
+ btn.setEnabled(false);
+ }
+
+ mMinValue.setEnabled(false);
+ mMaxValue.setEnabled(false);
+ }
+
+ public void onServiceFound(boolean llsService, boolean tpsService) {
+
+ Log.v(TAG, "IAS service = " + llsService + " TPS service = " + tpsService);
+
+ if (mActivity.mPxpServiceProxy.checkFailedReadTxPowerLevel(mActivity.mLeDevice)) {
+ Context context = getActivity();
+ CharSequence text = "TX Power level not found";
+
+ Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.show();
+
+ } else if (llsService && tpsService) {
+
+ mPathLossButtons[0].setEnabled(true);
+ mPathLossButtons[1].setEnabled(true);
+ mPathLossButtons[2].setEnabled(true);
+ mMinValue.setEnabled(true);
+ mMaxValue.setEnabled(true);
+
+ int pathLossLevel;
+
+ pathLossLevel = mActivity.mPxpServiceProxy
+ .getPathLossAlertLevel(mActivity.mLeDevice);
+
+ for (int i = 0; i < mPathLossButtons.length; i++) {
+ mPathLossButtons[i].setChecked(pathLossLevel == i);
+ }
+
+ int minThresholdValue;
+ int maxThresholdValue;
+
+ minThresholdValue = mActivity.mPxpServiceProxy
+ .getMinPathLossThreshold(mActivity.mLeDevice);
+
+ mMinValue.setText(String.format("%d", minThresholdValue));
+
+ maxThresholdValue = mActivity.mPxpServiceProxy
+ .getMaxPathLossThreshold(mActivity.mLeDevice);
+
+ mMaxValue.setText(String.format("%d", maxThresholdValue));
+
+ } else {
+ init();
+ }
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ ToggleButton clickedButton = (ToggleButton) v;
+
+ if (!mActivity.mPxpServiceProxy.getConnectionState(mActivity.mLeDevice)) {
+ return;
+ }
+
+ int idx;
+
+ switch (clickedButton.getId()) {
+ case R.id.path_off:
+ idx = 0;
+ break;
+
+ case R.id.path_mild:
+ idx = 1;
+ break;
+
+ case R.id.path_high:
+ idx = 2;
+ break;
+
+ default:
+ return;
+ }
+
+ for (int i = 0; i < mPathLossButtons.length; i++) {
+ ToggleButton btn = mPathLossButtons[i];
+
+ if (mPathLossButtons[idx].isChecked()) {
+
+ if (i != idx) {
+ btn.setChecked(false);
+ }
+
+ } else {
+ btn.setChecked(i == 0);
+ idx = 0;
+ }
+ }
+
+ mActivity.mPxpServiceProxy.setPathLossAlertLevel(mActivity.mLeDevice, idx);
+ }
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PxpServiceProxy.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PxpServiceProxy.java
new file mode 100644
index 0000000..8707ec7
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/PxpServiceProxy.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Service;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import org.codeaurora.bluetooth.pxpservice.IPxpService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PxpServiceProxy extends Service {
+
+ private static final String TAG = PxpServiceProxy.class.getSimpleName();
+
+ public static final String DEVICE_CONNECTED = "android.bluetooth.action.DEVICE_CONNECTED";
+
+ public static final String DEVICE_DISCONNECTED = "android.bluetooth.action.DEVICE_DISCONNECTED";
+
+ public static final String MISSING_LLS_SERVICE = "android.bluetooth.action.DEVICE_MISSING_LLS_SERVICE";
+
+ public static final String LINKLOSS_ALERT = "android.bluetooth.action.LINKLOSS_ALERT";
+
+ public static final String DEVICE_ALLERT = "action.DEVICE_ALLERT";
+
+ public static final String PATHLOSS_ALLERT = "action.PATHLOSS_ALLERT";
+
+ public static final String PATHLOSS_ALLERT_FINISH = "action.ALLERT_FINISH";
+
+ public static final String EXTRAS_DEVICE = "BLUETOOTH_DEVICE";
+
+ public static final String EXTRAS_TIME = "ALERT_TIME";
+
+ public static final String EXTRAS_RSSI = "DEVICE_RSSI";
+
+ public static final String EXTRAS_LLS_ALERT_VALUE = "LLS_ALERT_VALUE";
+
+ public static final int MSG_REGISTER_CLIENT = 1;
+
+ public static final int MSG_UNREGISTER_CLIENT = 2;
+
+ public static final int MSG_DEVICE_CONNECTED = 1;
+
+ public static final int MSG_MISSING_LLS_SERVICE = 2;
+
+ public static final int MSG_LINKLOSS_ALERT = 3;
+
+ public static final int MSG_DEVICE_DISCONNECTED = 4;
+
+ public static final int MSG_LINK_LOSS_TIMEOUT = 5;
+
+ public static final int MSG_PATHLOSS_ALERT = 6;
+
+ public static final int MSG_ALERT_FINISH = 7;
+
+ public static final int LINK_LOSS_ALERT_TIMEOUT = 15000;
+
+ private IPxpService mPxpMonitorService = null;
+
+ private static Handler mHandler = null;
+
+ private final LocalBinder mBinder = new LocalBinder();
+
+ protected ArrayList<AlertInformation> mAlertHistory = null;
+
+ public class LocalBinder extends Binder {
+ PxpServiceProxy getService() {
+ return PxpServiceProxy.this;
+ }
+ }
+
+ public static void registerClient(Handler handler) {
+ mHandler = handler;
+ }
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mPxpMonitorService = IPxpService.Stub.asInterface((IBinder) service);
+
+ Log.d(TAG, "Connected to Service");
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpMonitorService = null;
+
+ Log.d(TAG, "Disconnected from Service");
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent();
+ gattServiceIntent.setAction("org.codeaurora.bluetooth.pxpservice.PxpMonitorService");
+ bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE);
+
+ mAlertHistory = new ArrayList<AlertInformation>();
+
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(DEVICE_ALLERT);
+ intentFilter.addAction(DEVICE_CONNECTED);
+ intentFilter.addAction(DEVICE_DISCONNECTED);
+ intentFilter.addAction(MISSING_LLS_SERVICE);
+ intentFilter.addAction(LINKLOSS_ALERT);
+ intentFilter.addAction(PATHLOSS_ALLERT);
+ intentFilter.addAction(PATHLOSS_ALLERT_FINISH);
+
+ registerReceiver(mDataReceiver, intentFilter);
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(TAG, "onDestroy");
+ super.onDestroy();
+
+ unregisterReceiver(mDataReceiver);
+
+ Log.d(TAG, "UnbindService()");
+ unbindService(mConnection);
+ mPxpMonitorService = null;
+ }
+
+ @Override
+ public IBinder onBind(Intent arg0) {
+ Log.v(TAG, "onBind()");
+ return mBinder;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ Log.v(TAG, "onUnbind()");
+ return super.onUnbind(intent);
+ }
+
+ public synchronized boolean connect(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.connect(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return false;
+ }
+
+ public synchronized void disconnect(BluetoothDevice leDevice) {
+ try {
+ mPxpMonitorService.disconnect(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ public synchronized int getLinkLossAlertLevel(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.getLinkLossAlertLevel(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return 0;
+ }
+
+ public synchronized boolean setLinkLossAlertLevel(BluetoothDevice leDevice, int level) {
+ try {
+ return mPxpMonitorService.setLinkLossAlertLevel(leDevice, level);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return false;
+ }
+
+ public synchronized int getPathLossAlertLevel(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.getPathLossAlertLevel(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return 0;
+ }
+
+ public synchronized boolean setPathLossAlertLevel(BluetoothDevice leDevice, int level) {
+ try {
+ return mPxpMonitorService.setPathLossAlertLevel(leDevice, level);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+
+ return false;
+ }
+
+ public synchronized int getMaxPathLossThreshold(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.getMaxPathLossThreshold(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return 0;
+ }
+
+ public synchronized void setMaxPathLossThreshold(BluetoothDevice leDevice, int threshold) {
+ try {
+ mPxpMonitorService.setMaxPathLossThreshold(leDevice, threshold);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ public synchronized int getMinPathLossThreshold(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.getMinPathLossThreshold(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return 0;
+ }
+
+ public synchronized void setMinPathLossThreshold(BluetoothDevice leDevice, int threshold) {
+ try {
+ mPxpMonitorService.setMinPathLossThreshold(leDevice, threshold);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ public synchronized boolean isPropertiesSet(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.isPropertiesSet(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return false;
+ }
+
+ public synchronized boolean getConnectionState(BluetoothDevice leDevice) {
+ try {
+
+ return mPxpMonitorService.getConnectionState(leDevice);
+
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return false;
+ }
+
+ public synchronized boolean checkServiceStatus(BluetoothDevice leDevice, int service) {
+ try {
+ return mPxpMonitorService.checkServiceStatus(leDevice, service);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return false;
+ }
+
+ public synchronized boolean checkFailedReadTxPowerLevel(BluetoothDevice leDevice) {
+ try {
+ return mPxpMonitorService.checkFailedReadTxPowerLevel(leDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return false;
+ }
+
+ public synchronized void disconnectDevices() {
+ try {
+ mPxpMonitorService.disconnectDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ public synchronized List<BluetoothDevice> getConnectedDevices() {
+ try {
+ return mPxpMonitorService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ return null;
+ }
+
+ private final BroadcastReceiver mDataReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ BluetoothDevice mLeDevice;
+ String action = intent.getAction();
+
+ Message msg = null;
+
+ if (DEVICE_CONNECTED.equals(action)) {
+ Log.d(TAG, "Acton = DEVICE_CONNECTED");
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+ Log.d(TAG, "After reading mLeDevice");
+ msg = Message.obtain(null,
+ MSG_DEVICE_CONNECTED, mLeDevice);
+
+ } else if (MISSING_LLS_SERVICE.equals(action)) {
+ Log.d(TAG, "Action = MISSING_LLS_SERVICE");
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+ msg = Message.obtain(null,
+ MSG_MISSING_LLS_SERVICE, mLeDevice);
+
+ } else if (LINKLOSS_ALERT.equals(action)) {
+ Log.d(TAG, "Action = LINKLOSS_ALERT");
+ mLeDevice = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+ int llsAlertValue = intent.getIntExtra(EXTRAS_LLS_ALERT_VALUE, 0);
+
+ msg = Message.obtain(null,
+ MSG_LINKLOSS_ALERT, llsAlertValue);
+
+ } else if (DEVICE_DISCONNECTED.equals(action)) {
+ Log.d(TAG, "Action = DEVICE_DISCONNECTED");
+ mLeDevice = (BluetoothDevice) intent
+ .getParcelableExtra(EXTRAS_DEVICE);
+ msg = Message.obtain(null,
+ MSG_DEVICE_DISCONNECTED, mLeDevice);
+
+ } else if (DEVICE_ALLERT.equals(action)) {
+ Log.d(TAG, "DEVICE_ALLERT");
+
+ AlertInformation alertInfo = new AlertInformation();
+ alertInfo.device = (BluetoothDevice) intent.getParcelableExtra(EXTRAS_DEVICE);
+ alertInfo.date = intent.getStringExtra(EXTRAS_TIME);
+ alertInfo.rssi = intent.getIntExtra(EXTRAS_RSSI, 0);
+ mAlertHistory.add(alertInfo);
+
+ } else if (PATHLOSS_ALLERT.equals(action)) {
+ Log.d(TAG, "PATHLOSS_ALLERT");
+
+ mLeDevice = (BluetoothDevice) intent
+ .getParcelableExtra(EXTRAS_DEVICE);
+ msg = Message.obtain(null,
+ MSG_PATHLOSS_ALERT, mLeDevice);
+ } else if (PATHLOSS_ALLERT_FINISH.equals(action)) {
+ Log.d(TAG, "DEVICE_ALLERT_FINISH");
+
+ mLeDevice = (BluetoothDevice) intent
+ .getParcelableExtra(EXTRAS_DEVICE);
+ msg = Message.obtain(null,
+ MSG_ALERT_FINISH, mLeDevice);
+ }
+
+ if (msg == null) {
+ return;
+ }
+
+ if (mHandler != null) {
+ mHandler.sendMessage(msg);
+ }
+ }
+ };
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ScanDevicesActivity.java b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ScanDevicesActivity.java
new file mode 100644
index 0000000..cfdf371
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpmonitor/ScanDevicesActivity.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpmonitor;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ScanDevicesActivity extends ListActivity {
+ private static final String TAG = ScanDevicesActivity.class.getSimpleName();
+
+ public static final String DEVICE_NOT_CONNECTED_SELECTED =
+ "android.bluetooth.devicepicker.action.NOT_CONNECTED_DEVICE_SELECTED";
+
+ private static final int REQUEST_ENABLE_BT = 1;
+
+ private BluetoothAdapter mBluetoothAdapter = null;
+
+ private ScanDevicesListAdapter mDeviceListAdapter = null;
+
+ private PxpServiceProxy mPxpServiceProxy = null;
+
+ private Handler mHandler;
+
+ private boolean mScanning;
+
+ private static final long SCAN_PERIOD = 30000; // 30sec for now
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.d(TAG, "Connecting to service");
+ mPxpServiceProxy = ((PxpServiceProxy.LocalBinder) service).getService();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mPxpServiceProxy = null;
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ getActionBar().setTitle("Scan for Devices");
+
+ Log.d(TAG, "On create: new intent BluetoothService");
+ Intent gattServiceIntent = new Intent(this, PxpServiceProxy.class);
+
+ if (bindService(gattServiceIntent, mConnection, BIND_AUTO_CREATE) == false) {
+ Log.e(TAG, "Unable to bind");
+ }
+
+ mHandler = new Handler();
+
+ final BluetoothManager bluetoothManager =
+ (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = bluetoothManager.getAdapter();
+
+ mDeviceListAdapter = new ScanDevicesListAdapter(this);
+ setListAdapter(mDeviceListAdapter);
+ scanDevice(true);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.scan, menu);
+
+ if (mScanning) {
+ menu.findItem(R.id.menu_stop).setVisible(true);
+ menu.findItem(R.id.action_search).setVisible(false);
+
+ } else {
+ menu.findItem(R.id.menu_stop).setVisible(false);
+ menu.findItem(R.id.action_search).setVisible(true);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_search:
+ mDeviceListAdapter.clear();
+ scanDevice(true);
+ break;
+
+ case R.id.menu_stop:
+ scanDevice(false);
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ scanDevice(true);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ if (!mBluetoothAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+
+ scanDevice(false);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+ if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+ finish();
+ return;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ unbindService(mConnection);
+ mPxpServiceProxy = null;
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ final BluetoothDevice leDevice = mDeviceListAdapter.getDevice(position);
+
+ if (mScanning) {
+ scanDevice(false);
+ }
+
+ final Intent intent = new Intent(this, DeviceActivity.class);
+ intent.setAction(DEVICE_NOT_CONNECTED_SELECTED);
+ intent.putExtra(DeviceActivity.EXTRAS_DEVICE, leDevice);
+ startActivity(intent);
+ }
+
+ private void scanDevice(final boolean enable) {
+
+ Runnable scan = new Runnable() {
+
+ @Override
+ public void run() {
+ mScanning = false;
+ mBluetoothAdapter.stopLeScan(mLeScanCallback);
+ invalidateOptionsMenu();
+ }
+ };
+
+ if (enable) {
+ mHandler.postDelayed(scan, SCAN_PERIOD);
+ mScanning = true;
+ mBluetoothAdapter.startLeScan(mLeScanCallback);
+
+ } else {
+ mScanning = false;
+ mBluetoothAdapter.stopLeScan(mLeScanCallback);
+ mHandler.removeCallbacks(scan);
+ }
+ invalidateOptionsMenu();
+ }
+
+ private class ScanDevicesListAdapter extends BaseAdapter {
+ private ArrayList<BluetoothDevice> mLeDevices;
+ private LayoutInflater mInflater;
+ private Map<BluetoothDevice, DeviceInfo> mHashMapDevice;
+ private TextView mDeviceName;
+ private TextView mDeviceAddress;
+ private TextView mDeviceRssi;
+ private TextView mDeviceAdvData;
+
+ public ScanDevicesListAdapter(Context context) {
+ super();
+ mLeDevices = new ArrayList<BluetoothDevice>();
+ mInflater = LayoutInflater.from(context);
+ mHashMapDevice = new HashMap<BluetoothDevice, DeviceInfo>();
+ }
+
+ public void addDevice(BluetoothDevice device, int rssi, String advData) {
+
+ if (!mLeDevices.contains(device)) {
+ mLeDevices.add(device);
+ DeviceInfo deviceInfo = new DeviceInfo(rssi, advData);
+ mHashMapDevice.put(device, deviceInfo);
+ }
+ this.notifyDataSetChanged();
+ }
+
+ public BluetoothDevice getDevice(int position) {
+ return mLeDevices.get(position);
+ }
+
+ public void clear() {
+ mLeDevices.clear();
+ this.notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mLeDevices.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mLeDevices.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+
+ if (view == null) {
+ view = mInflater.inflate(R.layout.activity_list_devices, null);
+ }
+ mDeviceName = (TextView) view.findViewById(R.id.device_name);
+ mDeviceAddress = (TextView) view.findViewById(R.id.device_address);
+ mDeviceRssi = (TextView) view.findViewById(R.id.device_rssi);
+ mDeviceAdvData = (TextView) view.findViewById(R.id.device_adv_data);
+
+ BluetoothDevice device = mLeDevices.get(i);
+
+ DeviceInfo deviceInfo = mHashMapDevice.get(device);
+
+ final String deviceName = device.getName();
+
+ if (deviceName != null && deviceName.length() > 0) {
+ mDeviceName.setText(deviceName);
+
+ } else {
+ mDeviceName.setText("Unknow device");
+ }
+
+ mDeviceAddress.setText(device.getAddress());
+ mDeviceRssi.setText("RSSI = " + String.valueOf(deviceInfo.mRssi) + "dBm");
+ mDeviceAdvData.setText("Adv data: " + deviceInfo.mAdvData);
+
+ return view;
+ }
+
+ private class DeviceInfo {
+ private int mRssi;
+ private String mAdvData;
+
+ DeviceInfo(int rssi, String advData) {
+ mRssi = rssi;
+ mAdvData = advData;
+ }
+ }
+ }
+
+ private BluetoothAdapter.LeScanCallback mLeScanCallback =
+ new BluetoothAdapter.LeScanCallback() {
+
+ @Override
+ public void onLeScan(final BluetoothDevice device, final int rssi,
+ final byte[] scanRecord) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mDeviceListAdapter.addDevice(device, rssi, Arrays.toString(scanRecord));
+ }
+ });
+ }
+ };
+}
diff --git a/pxp-monitor/src/org/codeaurora/bluetooth/pxpservice/IPxpService.aidl b/pxp-monitor/src/org/codeaurora/bluetooth/pxpservice/IPxpService.aidl
new file mode 100644
index 0000000..d747819
--- /dev/null
+++ b/pxp-monitor/src/org/codeaurora/bluetooth/pxpservice/IPxpService.aidl
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bluetooth.pxpservice;
+
+import android.bluetooth.BluetoothDevice;
+
+import java.util.List;
+
+interface IPxpService
+{
+ /**
+ * Connect to the GATT service hosted on proximity reporter. The result of
+ * connect operation is reported asynchronously through the Bluetooth GATT
+ * callback.
+ *
+ * @param leDevice Bluetooth device
+ * @return Return true if the connection where initiated successfully.
+ */
+ boolean connect(in BluetoothDevice leDevice);
+
+ /**
+ * Disconnect an existing connection with proximity reporter. The result of
+ * disconnect operation is reported asynchronously through the Bluetooth
+ * GATT callback.
+ *
+ * @param leDevice Bluetooth device
+ * @return void
+ */
+ void disconnect(in BluetoothDevice leDevice);
+
+ /**
+ * Write link loss alert level to the remote device.
+ *
+ * @param leDevice Bluetooth remote device
+ * @param level Alert level (0, 1 or 2).
+ * @return Return true if the write operation was successful.
+ */
+ boolean setLinkLossAlertLevel(in BluetoothDevice leDevice, in int level);
+
+ /**
+ * Read link loss alert level from the remote device.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return Return value of link loss alert Level: 0 - off alert level 1 -
+ * mild alert level 2 - high alert level
+ */
+ int getLinkLossAlertLevel(in BluetoothDevice leDevice);
+
+ /**
+ * Set max value of path loss threshold.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return void
+ */
+ void setMaxPathLossThreshold(in BluetoothDevice leDevice, in int threshold);
+
+ /**
+ * Get max path loss threshold value.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return Return threshold value.
+ */
+ int getMaxPathLossThreshold(in BluetoothDevice leDevice);
+
+ /**
+ * Set max value of path loss threshold.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return void
+ */
+ void setMinPathLossThreshold(in BluetoothDevice leDevice, in int threshold);
+
+ /**
+ * Get min path loss threshold value.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return Return threshold value.
+ */
+ int getMinPathLossThreshold(in BluetoothDevice leDevice);
+
+ /**
+ * Write path loss alert level to the remote device.
+ *
+ * @param leDevice Bluetooth remote device
+ * @param level Alert level (0, 1 or 2).
+ * @return Return true if the write operation where initiated successfully.
+ */
+ boolean setPathLossAlertLevel(in BluetoothDevice leDevice, in int level);
+
+ /**
+ * Read path loss alert level from the remote device.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return Return value path loss alert Level: 0 - off alert level 1 - mild
+ * alert level 2 - high alert level
+ */
+ int getPathLossAlertLevel(in BluetoothDevice leDevice);
+
+ /**
+ * Get current connection state for a given device.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return true if device is connected
+ */
+ boolean getConnectionState(in BluetoothDevice leDevice);
+
+ /**
+ * Check if variable deviceProp for current device is set.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return true if is set
+ */
+ boolean isPropertiesSet(in BluetoothDevice leDevice);
+
+ /**
+ * Check if remote service was found on a given device
+ *
+ * @param leDevice Bluetooth remote device
+ * @param service remote service
+ * @return true if remote service was found
+ */
+ boolean checkServiceStatus(in BluetoothDevice leDevice, in int service);
+
+ /**
+ * Check status of reading Tx Power level characteristic operation.
+ *
+ * @param leDevice Bluetooth remote device
+ * @return true if reading operation failed.
+ */
+ boolean checkFailedReadTxPowerLevel(in BluetoothDevice leDevice);
+
+ /**
+ * Disconnect all connected devices.
+ */
+ void disconnectDevices();
+
+ /**
+ * List connected devices to the proximity monitor.
+ *
+ * @return Return List<BluetoothDevice> of the connected devices.
+ */
+ List<BluetoothDevice> getConnectedDevices();
+}
+