Add sl4a support for automatically accepting Bluetooth MAP connection.
Change sl4a to run with system uid.
Add handling logic in paring helper.
Other tweaks.
Change-Id: Ia701648f041a92459ad9d8aa7e5c7a2523925f26
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothAvrcpFacade.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothAvrcpFacade.java
index 1fc26aa..334ff51 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothAvrcpFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothAvrcpFacade.java
@@ -13,6 +13,7 @@
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
+import com.googlecode.android_scripting.rpc.RpcParameter;
public class BluetoothAvrcpFacade extends RpcReceiver {
static final ParcelUuid[] AVRCP_UUIDS = {
@@ -56,6 +57,18 @@
return sAvrcpProfile.getConnectedDevices();
}
+ @Rpc(description = "Send AVRPC passthrough command.")
+ public void bluetoothAvrcpSendPassThroughCmd(
+ @RpcParameter(name = "deviceID", description = "Name or MAC address of a bluetooth device.")
+ String deviceID,
+ @RpcParameter(name = "keyCode")
+ Integer keyCode,
+ @RpcParameter(name = "keyState")
+ Integer keyState) throws Exception {
+ BluetoothDevice mDevice = BluetoothFacade.getDevice(sAvrcpProfile.getConnectedDevices(), deviceID);
+ sAvrcpProfile.sendPassThroughCmd(mDevice, keyCode, keyState);
+ }
+
@Override
public void shutdown() {
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothConnectionFacade.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothConnectionFacade.java
index b19ab0d..1deef1e 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothConnectionFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothConnectionFacade.java
@@ -37,7 +37,6 @@
private final EventFacade mEventFacade;
private final IntentFilter mDiscoverConnectFilter;
- private final IntentFilter mConnectionStateChangeFilter;
private final IntentFilter mPairingFilter;
private final IntentFilter mBondFilter;
private final IntentFilter mA2dpStateChangeFilter;
@@ -56,7 +55,7 @@
mService = manager.getService();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mPairingHelper = new BluetoothPairingHelper();
- // Use a synchronized map to avoid running problems
+ // Use a synchronized map to avoid racing problems
listeningDevices = Collections.synchronizedMap(new HashMap<String, BroadcastReceiver>());
mEventFacade = manager.getReceiver(EventFacade.class);
@@ -68,15 +67,13 @@
mDiscoverConnectFilter.addAction(BluetoothDevice.ACTION_UUID);
mDiscoverConnectFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- mConnectionStateChangeFilter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
- mConnectionStateChangeFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-
mPairingFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
+ mPairingFilter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST);
+ mPairingFilter.setPriority(999);
mBondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mBondFilter.addAction(BluetoothDevice.ACTION_FOUND);
mBondFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- mBondFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1);
mA2dpStateChangeFilter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
mHidStateChangeFilter = new IntentFilter(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
@@ -86,6 +83,8 @@
mGoodNews.putBoolean("Status", true);
mBadNews = new Bundle();
mBadNews.putBoolean("Status", false);
+
+ mService.registerReceiver(mPairingHelper, mPairingFilter);
}
/**
@@ -218,7 +217,9 @@
if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1);
if (state == BluetoothA2dp.STATE_CONNECTED) {
- mEventFacade.postEvent("A2dpConnect" + mDeviceID, mGoodNews);
+ Bundle a2dpGoodNews = (Bundle) mGoodNews.clone();
+ a2dpGoodNews.putString("Type", "a2dp");
+ mEventFacade.postEvent("A2dpConnect" + mDeviceID, a2dpGoodNews);
mService.unregisterReceiver(listeningDevices.remove("A2dpConnecting"
+ mDeviceID));
} else if (state == BluetoothA2dp.STATE_CONNECTING) {
@@ -242,9 +243,12 @@
}
private void connectProfile(BluetoothDevice device, String deviceID) {
+ mService.registerReceiver(mPairingHelper, mPairingFilter);
ParcelUuid[] deviceUuids = device.getUuids();
Log.d("Device uuid is " + deviceUuids);
- mService.registerReceiver(mPairingHelper, mPairingFilter);
+ if (deviceUuids == null) {
+ mEventFacade.postEvent("Connect", mBadNews);
+ }
if (BluetoothUuid.containsAnyUuid(BluetoothA2dpFacade.SINK_UUIDS, deviceUuids)) {
Log.d("Connecting to " + device.getAliasName());
boolean status = mA2dpProfile.a2dpConnect(device);
@@ -255,10 +259,12 @@
listeningDevices.put("A2dpConnecting" + deviceID, receiver);
} else {
Log.d("Failed starting A2dp connection.");
- mEventFacade.postEvent("A2dpConnect", mBadNews);
+ Bundle a2dpBadNews = (Bundle) mBadNews.clone();
+ a2dpBadNews.putString("Type", "a2dp");
+ mEventFacade.postEvent("Connect", a2dpBadNews);
}
}
- if (BluetoothUuid.containsAnyUuid(BluetoothHidFacade.HID_UUID, deviceUuids)) {
+ if (BluetoothUuid.containsAnyUuid(BluetoothHidFacade.UUIDS, deviceUuids)) {
boolean status = mHidProfile.hidConnect(device);
if (status) {
Log.d("Connecting Hid...");
@@ -270,7 +276,7 @@
mEventFacade.postEvent("HidConnect", mBadNews);
}
}
- if (BluetoothUuid.containsAnyUuid(BluetoothHspFacade.HSP_UUIDS, deviceUuids)) {
+ if (BluetoothUuid.containsAnyUuid(BluetoothHspFacade.UUIDS, deviceUuids)) {
boolean status = mHspProfile.hspConnect(device);
if (status) {
Log.d("Connecting Hsp...");
@@ -296,7 +302,7 @@
return results;
}
- @Rpc(description = "Return ture if a bluetooth device is connected.")
+ @Rpc(description = "Return true if a bluetooth device is connected.")
public Boolean bluetoothIsDeviceConnected(String deviceID) {
for (BluetoothDevice bd : mBluetoothAdapter.getBondedDevices()) {
if (BluetoothFacade.deviceMatch(bd, deviceID)) {
@@ -367,10 +373,21 @@
String deviceID) throws Exception {
BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(),
deviceID);
+ mDevice.setTrust(true);
connectProfile(mDevice, deviceID);
}
+//
+// @Rpc(description = "Register pairing helper.")
+// public void bluetoothAutoAccept() {
+// mService.registerReceiver(mPairingHelper, mPairingFilter);
+// }
@Override
public void shutdown() {
+ for(BroadcastReceiver receiver : listeningDevices.values()) {
+ mService.unregisterReceiver(receiver);
+ }
+ listeningDevices.clear();
+ mService.unregisterReceiver(mPairingHelper);
}
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHidFacade.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHidFacade.java
index e456933..37875d6 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHidFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHidFacade.java
@@ -18,7 +18,7 @@
import com.googlecode.android_scripting.rpc.RpcParameter;
public class BluetoothHidFacade extends RpcReceiver {
- public final static ParcelUuid[] HID_UUID = { BluetoothUuid.Hid };
+ public final static ParcelUuid[] UUIDS = { BluetoothUuid.Hid };
private final Service mService;
private final BluetoothAdapter mBluetoothAdapter;
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java
index e9e10d2..8f39491 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothHspFacade.java
@@ -17,7 +17,7 @@
import com.googlecode.android_scripting.rpc.RpcParameter;
public class BluetoothHspFacade extends RpcReceiver {
- static final ParcelUuid[] HSP_UUIDS = {
+ static final ParcelUuid[] UUIDS = {
BluetoothUuid.HSP, BluetoothUuid.Handsfree
};
diff --git a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothPairingHelper.java b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothPairingHelper.java
index 12a25d6..1e98a15 100644
--- a/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothPairingHelper.java
+++ b/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothPairingHelper.java
@@ -10,24 +10,49 @@
public class BluetoothPairingHelper extends BroadcastReceiver {
public BluetoothPairingHelper() {
super();
+ Log.d("Pairing helper created.");
}
/**
- * Blindly confirm passkey
+ * Blindly confirm bluetooth connection/bonding requests.
*/
@Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
- int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
- Log.d("Bluetooth pairing intent received: " + action + " with type " + type);
- BluetoothDevice mBtDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ Log.d("Bluetooth pairing intent received: " + action);
+ BluetoothDevice mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
- Log.d("Processing Action Paring Request.");
+ int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
+ Log.d("Processing Action Paring Request with type " + type);
if(type == BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION ||
type == BluetoothDevice.PAIRING_VARIANT_CONSENT) {
- mBtDevice.setPairingConfirmation(true);
+ mDevice.setPairingConfirmation(true);
Log.d("Connection confirmed");
abortBroadcast(); // Abort the broadcast so Settings app doesn't get it.
}
}
+ else if(action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) {
+ int type = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, BluetoothDevice.ERROR);
+ Log.d("Processing Action Connection Access Request type " + type);
+ if(type == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS ||
+ type == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS ||
+ type == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) {
+ Intent newIntent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
+ String mReturnPackage = intent.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME);
+ String mReturnClass = intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME);
+ int mRequestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
+ BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS);
+ if (mReturnPackage != null && mReturnClass != null) {
+ newIntent.setClassName(mReturnPackage, mReturnClass);
+ }
+ newIntent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
+ BluetoothDevice.CONNECTION_ACCESS_YES);
+ newIntent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true);
+ newIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+ newIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType);
+ Log.d("Sending connection access acceptance intent.");
+ abortBroadcast();
+ c.sendBroadcast(newIntent, android.Manifest.permission.BLUETOOTH_ADMIN);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/ScriptingLayerForAndroid/AndroidManifest.xml b/ScriptingLayerForAndroid/AndroidManifest.xml
index eed2992..a69bf92 100644
--- a/ScriptingLayerForAndroid/AndroidManifest.xml
+++ b/ScriptingLayerForAndroid/AndroidManifest.xml
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.googlecode.android_scripting" android:installLocation="auto" android:versionCode="603" android:versionName="6x03">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.googlecode.android_scripting" android:installLocation="auto" android:versionCode="603" android:versionName="6x03"
+ android:sharedUserId="android.uid.system">
+ <permission android:name="com.android.permission.WHITELIST_BLUETOOTH_DEVICE"
+ android:protectionLevel="signature" />
+ <permission android:name="android.permission.ACCESS_BLUETOOTH_SHARE"
+ android:protectionLevel="signature" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="net.dinglisch.android.tasker.PERMISSION_RUN_TASKS" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
@@ -26,16 +31,17 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
+ <uses-permission android:name="android.permission.ACCESS_BLUETOOTH_SHARE" />
+ <uses-permission android:name="com.android.permission.WHITELIST_BLUETOOTH_DEVICE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.HARDWARE_TEST" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
@@ -80,6 +86,7 @@
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
+ <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-sdk android:targetSdkVersion="10" android:minSdkVersion="3" />
<application android:icon="@drawable/sl4a_logo_48" android:label="@string/application_title" android:name=".Sl4aApplication">
<activity android:name=".activity.ScriptManager" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="adjustResize" android:launchMode="singleTop">
@@ -165,9 +172,12 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
- <receiver android:name=".facade.bluetooth.BluetoothPairingHelper">
- <intent-filter android:priority="100">
+ <receiver android:name=".facade.bluetooth.BluetoothPairingHelper"
+ android:permission="android.permission.BLUETOOTH_ADMIN">
+ <intent-filter android:priority="999">
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
+ <action android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
+ <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>