diff options
author | Casper Bonde <c.bonde@samsung.com> | 2015-03-19 10:36:45 +0100 |
---|---|---|
committer | Andre Eisenbach <eisenbach@google.com> | 2015-04-15 10:54:08 -0700 |
commit | d05bd467ba191833522e5b78da54bc5eab7bab2c (patch) | |
tree | 9822822d3316154fd061bd0e31d5c5552d056482 /core/java/android/bluetooth | |
parent | 6ddbb5e55f72e870899731ff12af9945fa970e6e (diff) | |
download | frameworks_base-d05bd467ba191833522e5b78da54bc5eab7bab2c.zip frameworks_base-d05bd467ba191833522e5b78da54bc5eab7bab2c.tar.gz frameworks_base-d05bd467ba191833522e5b78da54bc5eab7bab2c.tar.bz2 |
Add support for Bluetooth Sim Access Profile (2/4)
Change-Id: I6c634aa38d31a7b5a98c9089840557257fd58209
Diffstat (limited to 'core/java/android/bluetooth')
-rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 7 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothDevice.java | 41 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothProfile.java | 10 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothSap.java | 389 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothUuid.java | 9 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetooth.aidl | 2 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothSap.aidl | 37 |
7 files changed, 491 insertions, 4 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 88bb626..d7705a4 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1746,6 +1746,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.HEADSET_CLIENT) { BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener); return true; + } else if (profile == BluetoothProfile.SAP) { + BluetoothSap sap = new BluetoothSap(context, listener); + return true; } else { return false; } @@ -1810,6 +1813,10 @@ public final class BluetoothAdapter { BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy; headsetClient.close(); break; + case BluetoothProfile.SAP: + BluetoothSap sap = (BluetoothSap)proxy; + sap.close(); + break; } } diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 1e82c03..bfc374f 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -382,6 +382,9 @@ public final class BluetoothDevice implements Parcelable { /**@hide*/ public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3; + /**@hide*/ + public static final int REQUEST_TYPE_SIM_ACCESS = 4; + /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents, * Contains package name to return reply intent to. @@ -1270,6 +1273,44 @@ public final class BluetoothDevice implements Parcelable { } /** + * Requires {@link android.Manifest.permission#BLUETOOTH}. + * @return Whether the Sim access is allowed to this device. Can be + * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. + * @hide + */ + public int getSimAccessPermission() { + if (sService == null) { + return ACCESS_UNKNOWN; + } + try { + return sService.getSimAccessPermission(this); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return ACCESS_UNKNOWN; + } + + /** + * Sets whether the Sim access is allowed to this device. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or + * {@link #ACCESS_REJECTED}. + * @return Whether the value has been successfully set. + * @hide + */ + public boolean setSimAccessPermission(int value) { + if (sService == null) { + return false; + } + try { + return sService.setSimAccessPermission(this, value); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** * Create an RFCOMM {@link BluetoothSocket} ready to start a secure * outgoing connection to this remote device on given channel. * <p>The remote device will be authenticated and communication on this diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 1367405..eecb073 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -103,17 +103,23 @@ public interface BluetoothProfile { */ public static final int MAP = 9; + /* + * SAP Profile + * @hide + */ + public static final int SAP = 10; + /** * A2DP Sink Profile * @hide */ - public static final int A2DP_SINK = 10; + public static final int A2DP_SINK = 11; /** * AVRCP Controller Profile * @hide */ - public static final int AVRCP_CONTROLLER = 11; + public static final int AVRCP_CONTROLLER = 12; /** * Headset Client - HFP HF Role diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java new file mode 100644 index 0000000..6052884 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import java.util.ArrayList; +import java.util.List; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.ServiceManager; +import android.util.Log; + + +public final class BluetoothSap implements BluetoothProfile { + + private static final String TAG = "BluetoothSap"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; + + private IBluetoothSap mService; + private final Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + + /** There was an error trying to obtain the state */ + public static final int STATE_ERROR = -1; + + public static final int RESULT_FAILURE = 0; + public static final int RESULT_SUCCESS = 1; + /** Connection canceled before completion. */ + public static final int RESULT_CANCELED = 2; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + doBind(); + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + + /** + * Create a BluetoothSap proxy object. + */ + /*package*/ BluetoothSap(Context context, ServiceListener l) { + if (DBG) Log.d(TAG, "Create BluetoothSap proxy object"); + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothMap.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent); + return false; + } + return true; + } + + protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } + + /** + * Close the connection to the backing service. + * Other public functions of BluetoothSap will return default error + * results once close() has been called. Multiple invocations of close() + * are ok. + */ + public synchronized void close() { + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + mServiceListener = null; + } + + /** + * Get the current state of the BluetoothSap service. + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy + * object is currently not connected to the Sap service. + */ + public int getState() { + if (VDBG) log("getState()"); + if (mService != null) { + try { + return mService.getState(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return BluetoothSap.STATE_ERROR; + } + + /** + * Get the currently connected remote Bluetooth device (PCE). + * @return The remote Bluetooth device, or null if not in connected or + * connecting state, or if this proxy object is not connected to + * the Sap service. + */ + public BluetoothDevice getClient() { + if (VDBG) log("getClient()"); + if (mService != null) { + try { + return mService.getClient(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return null; + } + + /** + * Returns true if the specified Bluetooth device is connected. + * Returns false if not connected, or if this proxy object is not + * currently connected to the Sap service. + */ + public boolean isConnected(BluetoothDevice device) { + if (VDBG) log("isConnected(" + device + ")"); + if (mService != null) { + try { + return mService.isConnected(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Initiate connection. Initiation of outgoing connections is not + * supported for SAP server. + */ + public boolean connect(BluetoothDevice device) { + if (DBG) log("connect(" + device + ")" + "not supported for SAPS"); + return false; + } + + /** + * Initiate disconnect. + * + * @param device Remote Bluetooth Device + * @return false on error, + * true otherwise + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Get the list of connected devices. Currently at most one. + * + * @return list of connected devices + */ + public List<BluetoothDevice> getConnectedDevices() { + if (DBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * Get the list of devices matching specified states. Currently at most one. + * + * @return list of matching devices + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (DBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * Get connection state of device + * + * @return device connection state + */ + public int getConnectionState(BluetoothDevice device) { + if (DBG) log("getConnectionState(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + /** + * Set priority of the profile + * + * <p> The device should already be paired. + * Priority can be one of {@link #PRIORITY_ON} or + * {@link #PRIORITY_OFF}, + * + * @param device Paired bluetooth device + * @param priority + * @return true if priority is set, false on error + */ + public boolean setPriority(BluetoothDevice device, int priority) { + if (DBG) log("setPriority(" + device + ", " + priority + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF && + priority != BluetoothProfile.PRIORITY_ON) { + return false; + } + try { + return mService.setPriority(device, priority); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Get the priority of the profile. + * + * <p> The priority can be any of: + * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, + * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} + * + * @param device Bluetooth device + * @return priority of the device + */ + public int getPriority(BluetoothDevice device) { + if (VDBG) log("getPriority(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getPriority(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return PRIORITY_OFF; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return PRIORITY_OFF; + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) log("Proxy object connected"); + mService = IBluetoothSap.Stub.asInterface(service); + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) log("Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.SAP); + } + } + }; + + private static void log(String msg) { + Log.d(TAG, msg); + } + + private boolean isEnabled() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + + if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) + return true; + log("Bluetooth is Not enabled"); + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) + return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) + return true; + return false; + } + +} diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 194a53e..2ded4c8 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -76,7 +76,9 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid MAS = ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); - + public static final ParcelUuid SAP = + ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); + public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); @@ -89,7 +91,7 @@ public final class BluetoothUuid { public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, - ObexObjectPush, PANU, NAP, MAP, MNS, MAS}; + ObexObjectPush, PANU, NAP, MAP, MNS, MAS, SAP}; public static boolean isAudioSource(ParcelUuid uuid) { return uuid.equals(AudioSource); @@ -143,6 +145,9 @@ public final class BluetoothUuid { public static boolean isMas(ParcelUuid uuid) { return uuid.equals(MAS); } + public static boolean isSap(ParcelUuid uuid) { + return uuid.equals(SAP); + } /** * Returns true if ParcelUuid is present in uuidArray diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index 90df198..f6001bf 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -79,6 +79,8 @@ interface IBluetooth boolean setPhonebookAccessPermission(in BluetoothDevice device, int value); int getMessageAccessPermission(in BluetoothDevice device); boolean setMessageAccessPermission(in BluetoothDevice device, int value); + int getSimAccessPermission(in BluetoothDevice device); + boolean setSimAccessPermission(in BluetoothDevice device, int value); void sendConnectionStateChange(in BluetoothDevice device, int profile, int state, int prevState); diff --git a/core/java/android/bluetooth/IBluetoothSap.aidl b/core/java/android/bluetooth/IBluetoothSap.aidl new file mode 100644 index 0000000..8970639 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothSap.aidl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.bluetooth.BluetoothDevice; + +/** + * System private API for Bluetooth SAP service + * + * {@hide} + */ +interface IBluetoothSap { + int getState(); + BluetoothDevice getClient(); + boolean connect(in BluetoothDevice device); + boolean disconnect(in BluetoothDevice device); + boolean isConnected(in BluetoothDevice device); + List<BluetoothDevice> getConnectedDevices(); + List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); + boolean setPriority(in BluetoothDevice device, int priority); + int getPriority(in BluetoothDevice device); +} |