From 3f41673265dcaaef058703311c5481e8a51fd8be Mon Sep 17 00:00:00 2001 From: Jiafa Liu Date: Thu, 2 Jul 2009 16:36:02 +0800 Subject: frameworks/base: Add PBAP support - Update according to comments - Add aidl support in frameworks for Settings to retrieve current PBAP transaction status. - Add status bar support for PBAP --- core/java/android/bluetooth/BluetoothPbap.java | 261 ++++++++++++++++++++++++ core/java/android/bluetooth/IBluetoothPbap.aidl | 30 +++ 2 files changed, 291 insertions(+) create mode 100644 core/java/android/bluetooth/BluetoothPbap.java create mode 100644 core/java/android/bluetooth/IBluetoothPbap.aidl (limited to 'core/java/android/bluetooth') diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java new file mode 100644 index 0000000..d604414 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -0,0 +1,261 @@ +/* + * 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 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.RemoteException; +import android.os.IBinder; +import android.os.ServiceManager; +import android.util.Log; + +/** + * The Android Bluetooth API is not finalized, and *will* change. Use at your + * own risk. + * + * Public API for controlling the Bluetooth Pbap Service. This includes + * Bluetooth Phone book Access profile. + * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap + * Service via IPC. + * + * Creating a BluetoothPbap object will create a binding with the + * BluetoothPbap service. Users of this object should call close() when they + * are finished with the BluetoothPbap, so that this proxy object can unbind + * from the service. + * + * This BluetoothPbap object is not immediately bound to the + * BluetoothPbap service. Use the ServiceListener interface to obtain a + * notification when it is bound, this is especially important if you wish to + * immediately call methods on BluetoothPbap after construction. + * + * Android only supports one connected Bluetooth Pce at a time. + * + * @hide + */ +public class BluetoothPbap { + + private static final String TAG = "BluetoothPbap"; + private static final boolean DBG = false; + + /** int extra for PBAP_STATE_CHANGED_ACTION */ + public static final String PBAP_STATE = + "android.bluetooth.pbap.intent.PBAP_STATE"; + /** int extra for PBAP_STATE_CHANGED_ACTION */ + public static final String PBAP_PREVIOUS_STATE = + "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE"; + + /** Indicates the state of an pbap connection state has changed. + * This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and + * BluetoothIntent.ADDRESS extras. + */ + public static final String PBAP_STATE_CHANGED_ACTION = + "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED"; + + private IBluetoothPbap mService; + private final Context mContext; + private final ServiceListener mServiceListener; + + /** There was an error trying to obtain the state */ + public static final int STATE_ERROR = -1; + /** No headset currently connected */ + public static final int STATE_DISCONNECTED = 0; + /** Connection attempt in progress */ + public static final int STATE_CONNECTING = 1; + /** A headset is currently connected */ + public static final int STATE_CONNECTED = 2; + + 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; + + public static final int PRIORITY_AUTO = 100; + public static final int PRIORITY_OFF = 0; + /** + * An interface for notifying Bluetooth PCE IPC clients when they have + * been connected to the BluetoothHeadset service. + */ + public interface ServiceListener { + /** + * Called to notify the client when this proxy object has been + * connected to the BluetoothPbap service. Clients must wait for + * this callback before making IPC calls on the BluetoothPbap + * service. + */ + public void onServiceConnected(); + + /** + * Called to notify the client that this proxy object has been + * disconnected from the BluetoothPbap service. Clients must not + * make IPC calls on the BluetoothPbap service after this callback. + * This callback will currently only occur if the application hosting + * the BluetoothPbap service, but may be called more often in future. + */ + public void onServiceDisconnected(); + } + + /** + * Create a BluetoothHeadset proxy object. + */ + public BluetoothPbap(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + if (!context.bindService(new Intent(IBluetoothPbap.class.getName()), mConnection, 0)) { + Log.e(TAG, "Could not bind to Bluetooth Pbap Service"); + } + } + + protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } + + /** + * Close the connection to the backing service. + * Other public functions of BluetoothHeadset will return default error + * results once close() has been called. Multiple invocations of close() + * are ok. + */ + public synchronized void close() { + if (mConnection != null) { + mContext.unbindService(mConnection); + mConnection = null; + } + } + + /** + * Get the current state of the Bluetooth Headset service. + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy + * object is currently not connected to the Headset service. + */ + public int getState() { + if (DBG) 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 BluetoothHeadset.STATE_ERROR; + } + + /** + * Get the Bluetooth address of the current headset. + * @return The Bluetooth address, or null if not in connected or connecting + * state, or if this proxy object is not connected to the Headset + * service. + */ + public String getPceAddress() { + if (DBG) log("getPceAddress()"); + if (mService != null) { + try { + return mService.getPceAddress(); + } 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 headset is connected (does not include + * connecting). Returns false if not connected, or if this proxy object + * if not currently connected to the headset service. + */ + public boolean isConnected(String address) { + if (DBG) log("isConnected(" + address + ")"); + if (mService != null) { + try { + return mService.isConnected(address); + } 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; + } + + /** + * Disconnects the current headset. Currently this call blocks, it may soon + * be made asynchornous. Returns false if this proxy object is + * not currently connected to the Headset service. + */ + public boolean disconnectPce() { + if (DBG) log("disconnectPce()"); + if (mService != null) { + try { + mService.disconnectPce(); + return true; + } 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; + } + + /** + * Check class bits for possible PBAP support. + * This is a simple heuristic that tries to guess if a device with the + * given class bits might support PBAP. It is not accurate for all + * devices. It tries to err on the side of false positives. + * @return True if this device might support PBAP. + */ + public static boolean doesClassMatchSink(int btClass) { + // TODO optimize the rule + switch (BluetoothClass.Device.getDevice(btClass)) { + case BluetoothClass.Device.COMPUTER_DESKTOP: + case BluetoothClass.Device.COMPUTER_LAPTOP: + case BluetoothClass.Device.COMPUTER_SERVER: + case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: + return true; + default: + return false; + } + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) log("Proxy object connected"); + mService = IBluetoothPbap.Stub.asInterface(service); + if (mServiceListener != null) { + mServiceListener.onServiceConnected(); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) log("Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(); + } + } + }; + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/bluetooth/IBluetoothPbap.aidl b/core/java/android/bluetooth/IBluetoothPbap.aidl new file mode 100644 index 0000000..06cdb7b --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothPbap.aidl @@ -0,0 +1,30 @@ +/* + * 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; + +/** + * System private API for Bluetooth pbap service + * + * {@hide} + */ +interface IBluetoothPbap { + int getState(); + String getPceAddress(); + boolean connectPce(in String address); + void disconnectPce(); + boolean isConnected(in String address); +} -- cgit v1.1