Loading Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ core/java/android/bluetooth/IBluetoothSap.aidl \ core/java/android/content/IClipboard.aidl \ core/java/android/content/IContentService.aidl \ core/java/android/content/IIntentReceiver.aidl \ Loading core/java/android/bluetooth/BluetoothAdapter.java +7 −0 Original line number Diff line number Diff line Loading @@ -1178,6 +1178,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.PAN) { BluetoothPan pan = new BluetoothPan(context, listener); return true; } else if (profile == BluetoothProfile.SAP) { BluetoothSap sap = new BluetoothSap(context, listener); return true; } else if (profile == BluetoothProfile.HEALTH) { BluetoothHealth health = new BluetoothHealth(context, listener); return true; Loading Loading @@ -1217,6 +1220,10 @@ public final class BluetoothAdapter { BluetoothPan pan = (BluetoothPan)proxy; pan.close(); break; case BluetoothProfile.SAP: BluetoothSap sap = (BluetoothSap)proxy; sap.close(); break; case BluetoothProfile.HEALTH: BluetoothHealth health = (BluetoothHealth)proxy; health.close(); Loading core/java/android/bluetooth/BluetoothDevice.java +2 −0 Original line number Diff line number Diff line Loading @@ -259,6 +259,8 @@ public final class BluetoothDevice implements Parcelable { public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT"; /** @hide */ public static final String EXTRA_SECURE_PAIRING = "codeaurora.bluetooth.device.extra.SECURE"; /** @hide */ public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY"; /** Loading core/java/android/bluetooth/BluetoothProfile.java +6 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,12 @@ public interface BluetoothProfile { */ static public final int GATT_SERVER = 8; /** * SAP * @hide */ public static final int SAP = 20; /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile Loading core/java/android/bluetooth/BluetoothSap.java 0 → 100644 +279 −0 Original line number Diff line number Diff line /* * 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 android.bluetooth; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; import java.util.List; /** * This class provides the APIs to control the Bluetooth Sap * Profile. * *<p>BluetoothSap is a proxy object for controlling the Bluetooth SAP * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothSap proxy object. * *<p>Each method is protected with its appropriate permission. *@hide */ public final class BluetoothSap implements BluetoothProfile { private static final String TAG = "BluetoothSap"; private static final boolean DBG = false; private static final boolean VDBG = false; /** * Intent used to broadcast the change in connection state of the Sap * profile. * * <p>This intent will have 3 extras: * <ul> * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTED}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "codeaurora.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; private IBluetoothSap mSapService; /** * Create a BluetoothSap proxy object for interacting with the local * Bluetooth Service which handles the Sap profile * */ /*package*/ BluetoothSap(Context context, ServiceListener l) { mContext = context; mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); try { mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); } catch (RemoteException re) { Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); } Log.d(TAG, "BluetoothSap() call bindService"); if (!context.bindService(new Intent(IBluetoothSap.class.getName()), mConnection, 0)) { Log.e(TAG, "Could not bind to Bluetooth SAP Service"); } Log.d(TAG, "BluetoothSap(), bindService called"); } /*package*/ void close() { if (VDBG) log("close()"); mServiceListener = null; IBluetoothManager mgr = mAdapter.getBluetoothManager(); if (mgr != null) { try { mgr.unregisterStateChangeCallback(mStateChangeCallback); } catch (RemoteException re) { Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); } } synchronized (mConnection) { if ( mSapService != null) { try { mSapService = null; mContext.unbindService(mConnection); } catch (Exception re) { Log.e(TAG,"",re); } } } } protected void finalize() { close(); } private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { @Override public void onBluetoothStateChange(boolean on) throws RemoteException { //Handle enable request to bind again. if (on) { Log.d(TAG, "onBluetoothStateChange(on) call bindService"); if (!mContext.bindService(new Intent(IBluetoothSap.class.getName()), mConnection, 0)) { Log.e(TAG, "Could not bind to Bluetooth SAP Service"); } Log.d(TAG, "BluetoothSap(), bindService called"); } else { if (VDBG) Log.d(TAG,"Unbinding service..."); synchronized (mConnection) { if ( mSapService != null) { try { mSapService = null; mContext.unbindService(mConnection); } catch (Exception re) { Log.e(TAG,"",re); } } } } } }; /** * Initiate disconnection from SAP server. * * <p> Once the disconnection is initiated by any device either local host * or remote device, the state will transition from {@link #STATE_CONNECTED} * to {@link #STATE_DISCONNECTED}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Remote Bluetooth Device * @return false on immediate error, * true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); if (mSapService != null && isEnabled() && isValidDevice(device)) { try { return mSapService.disconnect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return false; } /** * {@inheritDoc} */ public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mSapService != null && isEnabled()) { try { return mSapService.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } /** * {@inheritDoc} */ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mSapService != null && isEnabled()) { try { return mSapService.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } /** * {@inheritDoc} */ public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); if (mSapService != null && isEnabled() && isValidDevice(device)) { try { return mSapService.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "BluetoothSAP Proxy object connected"); mSapService = IBluetoothSap.Stub.asInterface(service); if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this); } } public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "BluetoothSAP Proxy object disconnected"); mSapService = null; if (mServiceListener != null) { mServiceListener.onServiceDisconnected(BluetoothProfile.SAP); } } }; private boolean isEnabled() { if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; return false; } private boolean isValidDevice(BluetoothDevice device) { if (device == null) return false; if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; return false; } private static void log(String msg) { Log.d(TAG, msg); } } Loading
Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ core/java/android/bluetooth/IBluetoothSap.aidl \ core/java/android/content/IClipboard.aidl \ core/java/android/content/IContentService.aidl \ core/java/android/content/IIntentReceiver.aidl \ Loading
core/java/android/bluetooth/BluetoothAdapter.java +7 −0 Original line number Diff line number Diff line Loading @@ -1178,6 +1178,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.PAN) { BluetoothPan pan = new BluetoothPan(context, listener); return true; } else if (profile == BluetoothProfile.SAP) { BluetoothSap sap = new BluetoothSap(context, listener); return true; } else if (profile == BluetoothProfile.HEALTH) { BluetoothHealth health = new BluetoothHealth(context, listener); return true; Loading Loading @@ -1217,6 +1220,10 @@ public final class BluetoothAdapter { BluetoothPan pan = (BluetoothPan)proxy; pan.close(); break; case BluetoothProfile.SAP: BluetoothSap sap = (BluetoothSap)proxy; sap.close(); break; case BluetoothProfile.HEALTH: BluetoothHealth health = (BluetoothHealth)proxy; health.close(); Loading
core/java/android/bluetooth/BluetoothDevice.java +2 −0 Original line number Diff line number Diff line Loading @@ -259,6 +259,8 @@ public final class BluetoothDevice implements Parcelable { public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT"; /** @hide */ public static final String EXTRA_SECURE_PAIRING = "codeaurora.bluetooth.device.extra.SECURE"; /** @hide */ public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY"; /** Loading
core/java/android/bluetooth/BluetoothProfile.java +6 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,12 @@ public interface BluetoothProfile { */ static public final int GATT_SERVER = 8; /** * SAP * @hide */ public static final int SAP = 20; /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile Loading
core/java/android/bluetooth/BluetoothSap.java 0 → 100644 +279 −0 Original line number Diff line number Diff line /* * 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 android.bluetooth; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; import java.util.List; /** * This class provides the APIs to control the Bluetooth Sap * Profile. * *<p>BluetoothSap is a proxy object for controlling the Bluetooth SAP * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothSap proxy object. * *<p>Each method is protected with its appropriate permission. *@hide */ public final class BluetoothSap implements BluetoothProfile { private static final String TAG = "BluetoothSap"; private static final boolean DBG = false; private static final boolean VDBG = false; /** * Intent used to broadcast the change in connection state of the Sap * profile. * * <p>This intent will have 3 extras: * <ul> * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTED}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "codeaurora.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; private IBluetoothSap mSapService; /** * Create a BluetoothSap proxy object for interacting with the local * Bluetooth Service which handles the Sap profile * */ /*package*/ BluetoothSap(Context context, ServiceListener l) { mContext = context; mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); try { mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); } catch (RemoteException re) { Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); } Log.d(TAG, "BluetoothSap() call bindService"); if (!context.bindService(new Intent(IBluetoothSap.class.getName()), mConnection, 0)) { Log.e(TAG, "Could not bind to Bluetooth SAP Service"); } Log.d(TAG, "BluetoothSap(), bindService called"); } /*package*/ void close() { if (VDBG) log("close()"); mServiceListener = null; IBluetoothManager mgr = mAdapter.getBluetoothManager(); if (mgr != null) { try { mgr.unregisterStateChangeCallback(mStateChangeCallback); } catch (RemoteException re) { Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); } } synchronized (mConnection) { if ( mSapService != null) { try { mSapService = null; mContext.unbindService(mConnection); } catch (Exception re) { Log.e(TAG,"",re); } } } } protected void finalize() { close(); } private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { @Override public void onBluetoothStateChange(boolean on) throws RemoteException { //Handle enable request to bind again. if (on) { Log.d(TAG, "onBluetoothStateChange(on) call bindService"); if (!mContext.bindService(new Intent(IBluetoothSap.class.getName()), mConnection, 0)) { Log.e(TAG, "Could not bind to Bluetooth SAP Service"); } Log.d(TAG, "BluetoothSap(), bindService called"); } else { if (VDBG) Log.d(TAG,"Unbinding service..."); synchronized (mConnection) { if ( mSapService != null) { try { mSapService = null; mContext.unbindService(mConnection); } catch (Exception re) { Log.e(TAG,"",re); } } } } } }; /** * Initiate disconnection from SAP server. * * <p> Once the disconnection is initiated by any device either local host * or remote device, the state will transition from {@link #STATE_CONNECTED} * to {@link #STATE_DISCONNECTED}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Remote Bluetooth Device * @return false on immediate error, * true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); if (mSapService != null && isEnabled() && isValidDevice(device)) { try { return mSapService.disconnect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return false; } /** * {@inheritDoc} */ public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mSapService != null && isEnabled()) { try { return mSapService.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } /** * {@inheritDoc} */ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mSapService != null && isEnabled()) { try { return mSapService.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } /** * {@inheritDoc} */ public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); if (mSapService != null && isEnabled() && isValidDevice(device)) { try { return mSapService.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } if (mSapService == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "BluetoothSAP Proxy object connected"); mSapService = IBluetoothSap.Stub.asInterface(service); if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this); } } public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "BluetoothSAP Proxy object disconnected"); mSapService = null; if (mServiceListener != null) { mServiceListener.onServiceDisconnected(BluetoothProfile.SAP); } } }; private boolean isEnabled() { if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; return false; } private boolean isValidDevice(BluetoothDevice device) { if (device == null) return false; if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; return false; } private static void log(String msg) { Log.d(TAG, msg); } }