Merge "Add BluetoothProfile for PBAP PCE role." into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d91859d246
@@ -117,6 +117,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/bluetooth/IBluetoothManager.aidl \
|
||||
core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
|
||||
core/java/android/bluetooth/IBluetoothPbap.aidl \
|
||||
core/java/android/bluetooth/IBluetoothPbapClient.aidl \
|
||||
core/java/android/bluetooth/IBluetoothMap.aidl \
|
||||
core/java/android/bluetooth/IBluetoothSap.aidl \
|
||||
core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 The Android Open Source Project
|
||||
* Copyright (C) 2009-2016 The Android Open Source Project
|
||||
* Copyright (C) 2015 Samsung LSI
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -1837,6 +1837,9 @@ public final class BluetoothAdapter {
|
||||
} else if (profile == BluetoothProfile.SAP) {
|
||||
BluetoothSap sap = new BluetoothSap(context, listener);
|
||||
return true;
|
||||
} else if (profile == BluetoothProfile.PBAP_CLIENT) {
|
||||
BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1905,6 +1908,10 @@ public final class BluetoothAdapter {
|
||||
BluetoothSap sap = (BluetoothSap)proxy;
|
||||
sap.close();
|
||||
break;
|
||||
case BluetoothProfile.PBAP_CLIENT:
|
||||
BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
|
||||
pbapClient.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
331
core/java/android/bluetooth/BluetoothPbapClient.java
Normal file
331
core/java/android/bluetooth/BluetoothPbapClient.java
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.List;
|
||||
import java.util.ArrayList;
|
||||
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.util.Log;
|
||||
|
||||
/**
|
||||
* This class provides the APIs to control the Bluetooth PBAP Client Profile.
|
||||
*@hide
|
||||
*/
|
||||
public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
|
||||
private static final String TAG = "BluetoothPbapClient";
|
||||
private static final boolean DBG = false;
|
||||
private static final boolean VDBG = false;
|
||||
|
||||
public static final String ACTION_CONNECTION_STATE_CHANGED =
|
||||
"android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
|
||||
|
||||
private IBluetoothPbapClient mService;
|
||||
private BluetoothDevice mDevice;
|
||||
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: PBAP CLIENT 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 BluetoothPbapClient proxy object.
|
||||
*/
|
||||
BluetoothPbapClient(Context context, ServiceListener l) {
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Create BluetoothPbapClient 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();
|
||||
}
|
||||
|
||||
private boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothPbapClient.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 PBAP Client 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 BluetoothPbapClient 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate connection.
|
||||
* Upon successful connection to remote PBAP server the Client will
|
||||
* attempt to automatically download the users phonebook and call log.
|
||||
*
|
||||
* @param device a remote device we want connect to
|
||||
* @return <code>true</code> if command has been issued successfully;
|
||||
* <code>false</code> otherwise;
|
||||
*/
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) {
|
||||
log("connect(" + device + ") for PBAP Client.");
|
||||
}
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
mDevice = device;
|
||||
return mService.connect(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate disconnect.
|
||||
*
|
||||
* @param device Remote Bluetooth Device
|
||||
* @return false on error,
|
||||
* true otherwise
|
||||
*/
|
||||
public boolean disconnect() {
|
||||
if (DBG) {
|
||||
log("disconnect(" + mDevice + ")");
|
||||
}
|
||||
if (mService != null && isEnabled() && isValidDevice(mDevice)) {
|
||||
try {
|
||||
mService.disconnect(mDevice);
|
||||
return true;
|
||||
} 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
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
*/
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) {
|
||||
log("Proxy object connected");
|
||||
}
|
||||
mService = IBluetoothPbapClient.Stub.asInterface(service);
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, BluetoothPbapClient.this);
|
||||
}
|
||||
}
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) {
|
||||
log("Proxy object disconnected");
|
||||
}
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -130,6 +130,12 @@ public interface BluetoothProfile {
|
||||
*/
|
||||
public static final int HEADSET_CLIENT = 16;
|
||||
|
||||
/**
|
||||
* PBAP Client
|
||||
* @hide
|
||||
*/
|
||||
public static final int PBAP_CLIENT = 17;
|
||||
|
||||
/**
|
||||
* Default priority for devices that we try to auto-connect to and
|
||||
* and allow incoming connections for the profile
|
||||
|
||||
32
core/java/android/bluetooth/IBluetoothPbapClient.aidl
Normal file
32
core/java/android/bluetooth/IBluetoothPbapClient.aidl
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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;
|
||||
|
||||
/**
|
||||
* API for Bluetooth Phone Book Access Provile Client Side
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IBluetoothPbapClient {
|
||||
boolean connect(in BluetoothDevice device);
|
||||
boolean disconnect(in BluetoothDevice device);
|
||||
List<BluetoothDevice> getConnectedDevices();
|
||||
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
|
||||
int getConnectionState(in BluetoothDevice device);
|
||||
}
|
||||
Reference in New Issue
Block a user