MAP MCE
am: 631768d814
Change-Id: I155fd0e8b44539bf79cec2c6ddb2a4d71b0c23d9
This commit is contained in:
@@ -117,9 +117,10 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/bluetooth/IBluetoothPan.aidl \
|
||||
core/java/android/bluetooth/IBluetoothManager.aidl \
|
||||
core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
|
||||
core/java/android/bluetooth/IBluetoothMap.aidl \
|
||||
core/java/android/bluetooth/IBluetoothMapClient.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 \
|
||||
core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \
|
||||
|
||||
@@ -1952,6 +1952,9 @@ public final class BluetoothAdapter {
|
||||
} else if (profile == BluetoothProfile.PBAP_CLIENT) {
|
||||
BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
|
||||
return true;
|
||||
} else if (profile == BluetoothProfile.MAP_CLIENT) {
|
||||
BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -2024,6 +2027,10 @@ public final class BluetoothAdapter {
|
||||
BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
|
||||
pbapClient.close();
|
||||
break;
|
||||
case BluetoothProfile.MAP_CLIENT:
|
||||
BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
|
||||
mapClient.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
415
core/java/android/bluetooth/BluetoothMapClient.java
Normal file
415
core/java/android/bluetooth/BluetoothMapClient.java
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* 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.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.net.Uri;
|
||||
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 MAP MCE Profile.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class BluetoothMapClient implements BluetoothProfile {
|
||||
|
||||
private static final String TAG = "BluetoothMapClient";
|
||||
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
|
||||
|
||||
public static final String ACTION_CONNECTION_STATE_CHANGED =
|
||||
"android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
|
||||
public static final String ACTION_MESSAGE_RECEIVED =
|
||||
"android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED";
|
||||
/* Actions to be used for pending intents */
|
||||
public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY =
|
||||
"android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY";
|
||||
public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
|
||||
"android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
|
||||
|
||||
private IBluetoothMapClient 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 BluetoothMapClient proxy object.
|
||||
*/
|
||||
/*package*/ BluetoothMapClient(Context context, ServiceListener l) {
|
||||
if (DBG) Log.d(TAG, "Create BluetoothMapClient 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(IBluetoothMapClient.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 MAP MCE 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 BluetoothMap will return default error
|
||||
* results once close() has been called. Multiple invocations of close()
|
||||
* are ok.
|
||||
*/
|
||||
public 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Map service.
|
||||
*/
|
||||
public boolean isConnected(BluetoothDevice device) {
|
||||
if (VDBG) Log.d(TAG, "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.d(TAG, Log.getStackTraceString(new Throwable()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate connection. Initiation of outgoing connections is not
|
||||
* supported for MAP server.
|
||||
*/
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.connect(device);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, e.toString());
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Proxy not attached to service");
|
||||
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate disconnect.
|
||||
*
|
||||
* @param device Remote Bluetooth Device
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "disconnect(" + device + ")");
|
||||
if (mService != null && isEnabled() &&
|
||||
isValidDevice(device)) {
|
||||
try {
|
||||
return mService.disconnect(device);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(new Throwable()));
|
||||
}
|
||||
}
|
||||
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.d(TAG, "getConnectedDevices()");
|
||||
if (mService != null && isEnabled()) {
|
||||
try {
|
||||
return mService.getConnectedDevices();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.d(TAG, "getDevicesMatchingStates()");
|
||||
if (mService != null && isEnabled()) {
|
||||
try {
|
||||
return mService.getDevicesMatchingConnectionStates(states);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get connection state of device
|
||||
*
|
||||
* @return device connection state
|
||||
*/
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "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
|
||||
* @return true if priority is set, false on error
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) Log.d(TAG, "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.d(TAG, "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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* Send an SMS message to either the contacts primary number or the telephone number specified.
|
||||
*
|
||||
* @param device Bluetooth device
|
||||
* @param contacts Uri[] of the contacts
|
||||
* @param message Message to be sent
|
||||
* @param sentIntent intent issued when message is sent
|
||||
* @param deliveredIntent intent issued when message is delivered
|
||||
* @return true if the message is enqueued, false on error
|
||||
*/
|
||||
public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
|
||||
PendingIntent sentIntent, PendingIntent deliveredIntent) {
|
||||
if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unread messages. Unread messages will be published via {@LINK #ACTION_MESSAGE_RECEIVED}.
|
||||
*
|
||||
* @param device Bluetooth device
|
||||
* @return true if the message is enqueued, false on error
|
||||
*/
|
||||
public boolean getUnreadMessages(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return mService.getUnreadMessages(device);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
mService = IBluetoothMapClient.Stub.asInterface(service);
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
|
||||
BluetoothMapClient.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
|
||||
if (DBG) Log.d(TAG, "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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 The Android Open Source Project
|
||||
* Copyright (C) 2010-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.
|
||||
@@ -136,6 +136,12 @@ public interface BluetoothProfile {
|
||||
*/
|
||||
public static final int PBAP_CLIENT = 17;
|
||||
|
||||
/**
|
||||
* MAP Messaging Client Equipment (MCE)
|
||||
* @hide
|
||||
*/
|
||||
public static final int MAP_CLIENT = 18;
|
||||
|
||||
/**
|
||||
* Max profile ID. This value should be updated whenever a new profile is added to match
|
||||
* the largest value assigned to a profile.
|
||||
|
||||
40
core/java/android/bluetooth/IBluetoothMapClient.aidl
Normal file
40
core/java/android/bluetooth/IBluetoothMapClient.aidl
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* System private API for Bluetooth MAP MCE service
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IBluetoothMapClient {
|
||||
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,in int priority);
|
||||
int getPriority(in BluetoothDevice device);
|
||||
boolean sendMessage(in BluetoothDevice device, in Uri[] contacts, in String message,
|
||||
in PendingIntent sentIntent, in PendingIntent deliveryIntent);
|
||||
boolean getUnreadMessages(in BluetoothDevice device);
|
||||
}
|
||||
@@ -8165,6 +8165,9 @@ public final class Settings {
|
||||
public static final String
|
||||
BLUETOOTH_MAP_PRIORITY_PREFIX = "bluetooth_map_priority_";
|
||||
/** {@hide} */
|
||||
public static final String
|
||||
BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX = "bluetooth_map_client_priority_";
|
||||
/** {@hide} */
|
||||
public static final String
|
||||
BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX = "bluetooth_pbap_client_priority_";
|
||||
/** {@hide} */
|
||||
@@ -8365,6 +8368,14 @@ public final class Settings {
|
||||
return BLUETOOTH_MAP_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key that retrieves a bluetooth map client priority.
|
||||
* @hide
|
||||
*/
|
||||
public static final String getBluetoothMapClientPriorityKey(String address) {
|
||||
return BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key that retrieves a bluetooth pbap client priority.
|
||||
* @hide
|
||||
@@ -8374,7 +8385,7 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key that retrieves a bluetooth map priority.
|
||||
* Get the key that retrieves a bluetooth sap priority.
|
||||
* @hide
|
||||
*/
|
||||
public static final String getBluetoothSapPriorityKey(String address) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.bluetooth.BluetoothHeadsetClient;
|
||||
import android.bluetooth.BluetoothMap;
|
||||
import android.bluetooth.BluetoothMapClient;
|
||||
import android.bluetooth.BluetoothInputDevice;
|
||||
import android.bluetooth.BluetoothPan;
|
||||
import android.bluetooth.BluetoothPbapClient;
|
||||
@@ -81,12 +82,14 @@ public final class LocalBluetoothProfileManager {
|
||||
private HeadsetProfile mHeadsetProfile;
|
||||
private HfpClientProfile mHfpClientProfile;
|
||||
private MapProfile mMapProfile;
|
||||
private MapClientProfile mMapClientProfile;
|
||||
private final HidProfile mHidProfile;
|
||||
private OppProfile mOppProfile;
|
||||
private final PanProfile mPanProfile;
|
||||
private PbapClientProfile mPbapClientProfile;
|
||||
private final PbapServerProfile mPbapProfile;
|
||||
private final boolean mUsePbapPce;
|
||||
private final boolean mUseMapClient;
|
||||
|
||||
/**
|
||||
* Mapping from profile name, e.g. "HEADSET" to profile object.
|
||||
@@ -104,6 +107,8 @@ public final class LocalBluetoothProfileManager {
|
||||
mDeviceManager = deviceManager;
|
||||
mEventManager = eventManager;
|
||||
mUsePbapPce = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
|
||||
// MAP Client is typically used in the same situations as PBAP Client
|
||||
mUseMapClient = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
|
||||
// pass this reference to adapter and event manager (circular dependency)
|
||||
mLocalAdapter.setProfileManager(this);
|
||||
mEventManager.setProfileManager(this);
|
||||
@@ -125,10 +130,15 @@ public final class LocalBluetoothProfileManager {
|
||||
BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
|
||||
|
||||
if(DEBUG) Log.d(TAG, "Adding local MAP profile");
|
||||
mMapProfile = new MapProfile(mContext, mLocalAdapter,
|
||||
mDeviceManager, this);
|
||||
addProfile(mMapProfile, MapProfile.NAME,
|
||||
BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
|
||||
if (mUseMapClient) {
|
||||
mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
|
||||
addProfile(mMapClientProfile, MapClientProfile.NAME,
|
||||
BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
|
||||
} else {
|
||||
mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
|
||||
addProfile(mMapProfile, MapProfile.NAME,
|
||||
BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
|
||||
}
|
||||
|
||||
//Create PBAP server profile, but do not add it to list of profiles
|
||||
// as we do not need to monitor the profile as part of profile list
|
||||
@@ -199,6 +209,22 @@ public final class LocalBluetoothProfileManager {
|
||||
Log.d(TAG, "Handsfree Uuid not found.");
|
||||
}
|
||||
|
||||
// Message Access Profile Client
|
||||
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
|
||||
if (mMapClientProfile == null) {
|
||||
if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
|
||||
mMapClientProfile =
|
||||
new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
|
||||
addProfile(mMapClientProfile, MapClientProfile.NAME,
|
||||
BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
|
||||
}
|
||||
} else if (mMapClientProfile != null) {
|
||||
Log.w(TAG,
|
||||
"Warning: MAP Client profile was previously added but the UUID is now missing.");
|
||||
} else {
|
||||
Log.d(TAG, "MAP Client Uuid not found.");
|
||||
}
|
||||
|
||||
// OPP
|
||||
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
|
||||
if (mOppProfile == null) {
|
||||
@@ -383,6 +409,10 @@ public final class LocalBluetoothProfileManager {
|
||||
return mMapProfile;
|
||||
}
|
||||
|
||||
public MapClientProfile getMapClientProfile() {
|
||||
return mMapClientProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in a list of LocalBluetoothProfile objects that are supported by
|
||||
* the local device and the remote device.
|
||||
@@ -465,6 +495,11 @@ public final class LocalBluetoothProfileManager {
|
||||
mMapProfile.setPreferred(device, true);
|
||||
}
|
||||
|
||||
if (mMapClientProfile != null) {
|
||||
profiles.add(mMapClientProfile);
|
||||
removedProfiles.remove(mMapClientProfile);
|
||||
}
|
||||
|
||||
if (mUsePbapPce) {
|
||||
profiles.add(mPbapClientProfile);
|
||||
removedProfiles.remove(mPbapClientProfile);
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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 com.android.settingslib.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothMapClient;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothUuid;
|
||||
import android.content.Context;
|
||||
import android.os.ParcelUuid;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MapClientProfile handles Bluetooth MAP profile.
|
||||
*/
|
||||
public final class MapClientProfile implements LocalBluetoothProfile {
|
||||
private static final String TAG = "MapClientProfile";
|
||||
private static boolean V = false;
|
||||
|
||||
private BluetoothMapClient mService;
|
||||
private boolean mIsProfileReady;
|
||||
|
||||
private final LocalBluetoothAdapter mLocalAdapter;
|
||||
private final CachedBluetoothDeviceManager mDeviceManager;
|
||||
private final LocalBluetoothProfileManager mProfileManager;
|
||||
|
||||
static final ParcelUuid[] UUIDS = {
|
||||
BluetoothUuid.MAP,
|
||||
BluetoothUuid.MNS,
|
||||
BluetoothUuid.MAS,
|
||||
};
|
||||
|
||||
static final String NAME = "MAP Client";
|
||||
|
||||
// Order of this profile in device profiles list
|
||||
private static final int ORDINAL = 0;
|
||||
|
||||
// These callbacks run on the main thread.
|
||||
private final class MapClientServiceListener
|
||||
implements BluetoothProfile.ServiceListener {
|
||||
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
if (V) Log.d(TAG,"Bluetooth service connected");
|
||||
mService = (BluetoothMapClient) proxy;
|
||||
// We just bound to the service, so refresh the UI for any connected MAP devices.
|
||||
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
|
||||
while (!deviceList.isEmpty()) {
|
||||
BluetoothDevice nextDevice = deviceList.remove(0);
|
||||
CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
|
||||
// we may add a new device here, but generally this should not happen
|
||||
if (device == null) {
|
||||
Log.w(TAG, "MapProfile found new device: " + nextDevice);
|
||||
device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
|
||||
}
|
||||
device.onProfileStateChanged(MapClientProfile.this,
|
||||
BluetoothProfile.STATE_CONNECTED);
|
||||
device.refresh();
|
||||
}
|
||||
|
||||
mProfileManager.callServiceConnectedListeners();
|
||||
mIsProfileReady=true;
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(int profile) {
|
||||
if (V) Log.d(TAG,"Bluetooth service disconnected");
|
||||
mProfileManager.callServiceDisconnectedListeners();
|
||||
mIsProfileReady=false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isProfileReady() {
|
||||
if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
|
||||
return mIsProfileReady;
|
||||
}
|
||||
|
||||
MapClientProfile(Context context, LocalBluetoothAdapter adapter,
|
||||
CachedBluetoothDeviceManager deviceManager,
|
||||
LocalBluetoothProfileManager profileManager) {
|
||||
mLocalAdapter = adapter;
|
||||
mDeviceManager = deviceManager;
|
||||
mProfileManager = profileManager;
|
||||
mLocalAdapter.getProfileProxy(context, new MapClientServiceListener(),
|
||||
BluetoothProfile.MAP_CLIENT);
|
||||
}
|
||||
|
||||
public boolean isConnectable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isAutoConnectable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (mService == null) return false;
|
||||
List<BluetoothDevice> connectedDevices = getConnectedDevices();
|
||||
if (connectedDevices != null) {
|
||||
for (BluetoothDevice connectedDevice : connectedDevices) {
|
||||
mService.disconnect(connectedDevice);
|
||||
}
|
||||
}
|
||||
return mService.connect(device);
|
||||
}
|
||||
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (mService == null) return false;
|
||||
// Downgrade priority as user is disconnecting.
|
||||
if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
|
||||
mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
|
||||
}
|
||||
return mService.disconnect(device);
|
||||
}
|
||||
|
||||
public int getConnectionStatus(BluetoothDevice device) {
|
||||
if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
|
||||
|
||||
return mService.getConnectionState(device);
|
||||
}
|
||||
|
||||
public boolean isPreferred(BluetoothDevice device) {
|
||||
if (mService == null) return false;
|
||||
return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
|
||||
}
|
||||
|
||||
public int getPreferred(BluetoothDevice device) {
|
||||
if (mService == null) return BluetoothProfile.PRIORITY_OFF;
|
||||
return mService.getPriority(device);
|
||||
}
|
||||
|
||||
public void setPreferred(BluetoothDevice device, boolean preferred) {
|
||||
if (mService == null) return;
|
||||
if (preferred) {
|
||||
if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
|
||||
mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
|
||||
}
|
||||
} else {
|
||||
mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (mService == null) return new ArrayList<BluetoothDevice>(0);
|
||||
return mService.getDevicesMatchingConnectionStates(
|
||||
new int[] {BluetoothProfile.STATE_CONNECTED,
|
||||
BluetoothProfile.STATE_CONNECTING,
|
||||
BluetoothProfile.STATE_DISCONNECTING});
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
public int getOrdinal() {
|
||||
return ORDINAL;
|
||||
}
|
||||
|
||||
public int getNameResource(BluetoothDevice device) {
|
||||
return R.string.bluetooth_profile_map;
|
||||
}
|
||||
|
||||
public int getSummaryResourceForDevice(BluetoothDevice device) {
|
||||
int state = getConnectionStatus(device);
|
||||
switch (state) {
|
||||
case BluetoothProfile.STATE_DISCONNECTED:
|
||||
return R.string.bluetooth_map_profile_summary_use_for;
|
||||
|
||||
case BluetoothProfile.STATE_CONNECTED:
|
||||
return R.string.bluetooth_map_profile_summary_connected;
|
||||
|
||||
default:
|
||||
return Utils.getConnectionStateSummary(state);
|
||||
}
|
||||
}
|
||||
|
||||
public int getDrawableResource(BluetoothClass btClass) {
|
||||
return R.drawable.ic_bt_cellphone;
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
if (V) Log.d(TAG, "finalize()");
|
||||
if (mService != null) {
|
||||
try {
|
||||
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
|
||||
mService);
|
||||
mService = null;
|
||||
}catch (Throwable t) {
|
||||
Log.w(TAG, "Error cleaning up MAP Client proxy", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user