import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
+import android.provider.Settings;
import android.util.Log;
import android.provider.ContactsContract;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
} catch (Exception e) {
Log.w(TAG,"Unable to unregister sap receiver",e);
}
- mClient.handleDisconnect(null);
+ mClient.disconnect(null);
return true;
}
String action = intent.getAction();
if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- connect(device);
- }
- else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
+ if(getPriority(device) >= BluetoothProfile.PRIORITY_ON) {
+ connect(device);
+ }
+ } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
disconnect(device);
}
}
}
-
-
-
-
-
/**
* Handler for incoming service calls
*/
}
return service.getConnectionState(device);
}
+
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ PbapClientService service = getService();
+ if (service == null) {
+ return false;
+ }
+ return service.setPriority(device, priority);
+ }
+
+ public int getPriority(BluetoothDevice device) {
+ PbapClientService service = getService();
+ if (service == null) {
+ return BluetoothProfile.PRIORITY_UNDEFINED;
+ }
+ return service.getPriority(device);
+ }
+
+
}
connectionState == BluetoothProfile.STATE_CONNECTING) {
return false;
}
- mClient.handleConnect(device);
- return true;
+ if (getPriority(device)>BluetoothProfile.PRIORITY_OFF) {
+ mClient.connect(device);
+ return true;
+ }
+ return false;
}
boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
- mClient.handleDisconnect(device);
+ mClient.disconnect(device);
return true;
}
public List<BluetoothDevice> getConnectedDevices() {
private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
int clientState = mClient.getConnectionState();
+ Log.d(TAG,"getDevicesMatchingConnectionStates " + Arrays.toString(states) + " == " + clientState);
List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
for (int state : states) {
if (clientState == state) {
}
return BluetoothProfile.STATE_DISCONNECTED;
}
+
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ Settings.Global.putInt(getContentResolver(),
+ Settings.Global.getBluetoothPbapClientPriorityKey(device.getAddress()),
+ priority);
+ if (DBG) {
+ Log.d(TAG,"Saved priority " + device + " = " + priority);
+ }
+ return true;
+ }
+
+ public int getPriority(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int priority = Settings.Global.getInt(getContentResolver(),
+ Settings.Global.getBluetoothPbapClientPriorityKey(device.getAddress()),
+ BluetoothProfile.PRIORITY_UNDEFINED);
+ return priority;
+ }
+
}
import android.util.Pair;
import com.android.vcard.VCardEntry;
-import com.android.bluetooth.pbapclient.BluetoothPbapClient;
+import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.R;
import java.util.ArrayDeque;
private BluetoothPbapClient mClient;
private boolean mClientConnected = false;
private PbapHandler mHandler;
- private Handler mSelfHandler;
+ private ConnectionHandler mConnectionHandler;
private PullRequest mLastPull;
private HandlerThread mContactHandlerThread;
private Handler mContactHandler;
PbapPCEClient(Context context) {
mContext = context;
- mSelfHandler = new Handler(mContext.getMainLooper());
+ mConnectionHandler = new ConnectionHandler(mContext.getMainLooper());
mHandler = new PbapHandler(this);
mAccountManager = AccountManager.get(mContext);
mContactHandlerThread = new HandlerThread("PBAP contact handler",
mClientConnected = status;
if (mClientConnected == false) {
// If we are disconnected then whatever the current device is we should simply clean up.
- handleDisconnect(null);
+ onConnectionStateChanged(mDevice, BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTED);
+ disconnect(null);
}
if (mClientConnected == true) {
+ onConnectionStateChanged(mDevice, BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_CONNECTED);
processNextRequest();
}
}
- public void handleConnect(BluetoothDevice device) {
- if (device == null) {
- throw new IllegalStateException(TAG + ":Connect with null device!");
- } else if (mDevice != null && !mDevice.equals(device)) {
- // Check that we are not already connected to an existing different device.
- // Since the device can be connected to multiple external devices -- we use the honor
- // protocol and only accept the first connecting device.
- Log.e(TAG, ":Got a connected event when connected to a different device. " +
- "existing = " + mDevice + " new = " + device);
- return;
- } else if (device.equals(mDevice)) {
- Log.w(TAG, "Got a connected event for the same device. Ignoring!");
- return;
+ private class ConnectionHandler extends Handler {
+ public static final int EVENT_CONNECT = 1;
+ public static final int EVENT_DISCONNECT = 2;
+
+ public ConnectionHandler(Looper looper) {
+ super(looper);
}
- // Update the device.
- mDevice = device;
- mClient = new BluetoothPbapClient(mDevice, mAccount, mHandler);
- // Add the account. This should give us a place to stash the data.
- mAccount = new Account(device.getAddress(), mContext.getString(R.string.pbap_account_type));
- mContactHandler.obtainMessage(ContactHandler.EVENT_ADD_ACCOUNT,mAccount).sendToTarget();
- downloadPhoneBook();
- downloadCallLogs();
- mClient.connect();
- }
- public void handleDisconnect(BluetoothDevice device) {
- Log.w(TAG, "pbap disconnecting from = " + device);
+ @Override
+ public void handleMessage(Message msg) {
+ if (DBG) {
+ Log.d(TAG, "Connection Handler Message " + msg.what + " with " + msg.obj);
+ }
+ switch (msg.what) {
+ case EVENT_CONNECT:
+ if (msg.obj instanceof BluetoothDevice) {
+ BluetoothDevice device = (BluetoothDevice) msg.obj;
+ int oldState = getConnectionState();
+ if (oldState != BluetoothProfile.STATE_DISCONNECTED) {
+ return;
+ }
+ onConnectionStateChanged(device, oldState,
+ BluetoothProfile.STATE_CONNECTING);
+ handleConnect(device);
+ } else {
+ Log.e(TAG, "Invalid instance in Connection Handler:Connect");
+ }
+ break;
- if (device == null) {
- // If we have a null device then disconnect the current device.
- device = mDevice;
- } else if (mDevice == null) {
- Log.w(TAG, "No existing device connected to service - ignoring device = " + device);
- return;
- } else if (!mDevice.equals(device)) {
- Log.w(TAG, "Existing device different from disconnected device. existing = " + mDevice +
- " disconnecting device = " + device);
- return;
+ case EVENT_DISCONNECT:
+ if (mDevice == null) {
+ return;
+ }
+ if (msg.obj == null || msg.obj instanceof BluetoothDevice) {
+ BluetoothDevice device = (BluetoothDevice) msg.obj;
+ if (!mDevice.equals(device)) {
+ return;
+ }
+ int oldState = getConnectionState();
+ handleDisconnect(device);
+ int newState = getConnectionState();
+ if (device != null) {
+ onConnectionStateChanged(device, oldState, newState);
+ }
+ } else {
+ Log.e(TAG, "Invalid instance in Connection Handler:Disconnect");
+ }
+ break;
+
+ default:
+ Log.e(TAG, "Unknown Request to Connection Handler");
+ break;
+ }
+ }
+
+ private void handleConnect(BluetoothDevice device) {
+ if (device == null) {
+ throw new IllegalStateException(TAG + ":Connect with null device!");
+ } else if (mDevice != null && !mDevice.equals(device)) {
+ // Check that we are not already connected to an existing different device.
+ // Since the device can be connected to multiple external devices -- we use the honor
+ // protocol and only accept the first connecting device.
+ Log.e(TAG, ":Got a connected event when connected to a different device. " +
+ "existing = " + mDevice + " new = " + device);
+ return;
+ } else if (device.equals(mDevice)) {
+ Log.w(TAG, "Got a connected event for the same device. Ignoring!");
+ return;
+ }
+ // Update the device.
+ mDevice = device;
+ mClient = new BluetoothPbapClient(mDevice, mAccount, mHandler);
+ // Add the account. This should give us a place to stash the data.
+ mAccount = new Account(device.getAddress(), mContext.getString(R.string.pbap_account_type));
+ mContactHandler.obtainMessage(ContactHandler.EVENT_ADD_ACCOUNT,mAccount).sendToTarget();
+ downloadPhoneBook();
+ downloadCallLogs();
+ mClient.connect();
+ }
+
+ private void handleDisconnect(BluetoothDevice device) {
+ Log.w(TAG, "pbap disconnecting from = " + device);
+
+ if (device == null) {
+ // If we have a null device then disconnect the current device.
+ device = mDevice;
+ } else if (mDevice == null) {
+ Log.w(TAG, "No existing device connected to service - ignoring device = " + device);
+ return;
+ } else if (!mDevice.equals(device)) {
+ Log.w(TAG, "Existing device different from disconnected device. existing = " + mDevice +
+ " disconnecting device = " + device);
+ return;
+ }
+ resetState();
}
- resetState();
+ }
+
+ private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
+ Intent intent = new Intent(android.bluetooth.BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
+ intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
+ intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
+ Log.d(TAG,"Connection state " + device + ": " + prevState + "->" + state);
+ }
+
+ public void connect(BluetoothDevice device) {
+ mConnectionHandler.obtainMessage(ConnectionHandler.EVENT_CONNECT,device).sendToTarget();
+ }
+
+ public void disconnect(BluetoothDevice device) {
+ mConnectionHandler.obtainMessage(ConnectionHandler.EVENT_DISCONNECT,device).sendToTarget();
}
public void start() {
if (msg.obj instanceof Account) {
Account account = (Account) msg.obj;
addAccount(account);
+ } else {
+ Log.e(TAG, "invalid Instance in Contact Handler: Add Account");
}
break;
if (msg.obj instanceof PullRequest) {
PullRequest req = (PullRequest) msg.obj;
req.onPullComplete();
- }
- else {
- Log.w(TAG, "invalid Instance in contact handler");
+ } else {
+ Log.e(TAG, "invalid Instance in Contact Handler: Add Contacts");
}
break;