From 22ffff6a6dc471bd81df7a850a494fa0d7240528 Mon Sep 17 00:00:00 2001 From: Casper Bonde Date: Thu, 19 Mar 2015 11:24:37 +0100 Subject: Add support for Bluetooth Sim Access Profile (4/4) Change-Id: I28ca9cdc68ac11b7f696a668ae966bf4a42fd040 --- res/values/strings.xml | 11 ++ .../bluetooth/BluetoothPermissionActivity.java | 14 ++ .../bluetooth/BluetoothPermissionRequest.java | 20 +- .../settings/bluetooth/CachedBluetoothDevice.java | 25 ++- src/com/android/settings/bluetooth/SapProfile.java | 216 +++++++++++++++++++++ 5 files changed, 281 insertions(+), 5 deletions(-) create mode 100644 src/com/android/settings/bluetooth/SapProfile.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 292355ece..989219d74 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -389,6 +389,11 @@ %1$s wants to access your messages. Give access to %2$s? + + "SIM Access request" + + + %1$s wants to access your SIM card. Give access to %2$s? Date & time @@ -1257,6 +1262,8 @@ Internet connection sharing Message Access + + SIM Access %1$s will be disconnected from media audio. @@ -1292,6 +1299,8 @@ Connected to file transfer server Connected to map + + Connected to sap Not connected to file transfer server @@ -1317,6 +1326,8 @@ Use for Internet access Use for map + + Use for sap Dock Settings diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java index f43d176c8..3c250f0f9 100755 --- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java +++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java @@ -99,6 +99,8 @@ public class BluetoothPermissionActivity extends AlertActivity implements showDialog(getString(R.string.bluetooth_phonebook_request), mRequestType); } else if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) { showDialog(getString(R.string.bluetooth_map_request), mRequestType); + } else if (mRequestType == BluetoothDevice.REQUEST_TYPE_SIM_ACCESS) { + showDialog(getString(R.string.bluetooth_sap_request), mRequestType); } else { Log.e(TAG, "Error: bad request type: " + mRequestType); @@ -127,6 +129,9 @@ public class BluetoothPermissionActivity extends AlertActivity implements case BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS: p.mView = createMapDialogView(); break; + case BluetoothDevice.REQUEST_TYPE_SIM_ACCESS: + p.mView = createSapDialogView(); + break; } p.mPositiveButtonText = getString(R.string.yes); p.mPositiveButtonListener = this; @@ -181,6 +186,15 @@ public class BluetoothPermissionActivity extends AlertActivity implements return mView; } + private View createSapDialogView() { + String mRemoteName = createRemoteName(); + mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null); + messageView = (TextView)mView.findViewById(R.id.message); + messageView.setText(getString(R.string.bluetooth_sap_acceptance_dialog_text, + mRemoteName, mRemoteName)); + return mView; + } + private void onPositive() { if (DEBUG) Log.d(TAG, "onPositive"); sendReplyIntentToReceiver(true, true); diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java index 12c1d77eb..0cf8cc800 100644 --- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java +++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java @@ -41,6 +41,7 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { private static final String NOTIFICATION_TAG_PBAP = "Phonebook Access" ; private static final String NOTIFICATION_TAG_MAP = "Message Access"; + private static final String NOTIFICATION_TAG_SAP = "SIM Access"; Context mContext; @@ -181,6 +182,8 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { return NOTIFICATION_TAG_PBAP; } else if(mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) { return NOTIFICATION_TAG_MAP; + } else if(mRequestType == BluetoothDevice.REQUEST_TYPE_SIM_ACCESS) { + return NOTIFICATION_TAG_SAP; } return null; } @@ -195,7 +198,8 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { // ignore if it is something else than phonebook/message settings it wants us to remember if (mRequestType != BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS - && mRequestType != BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) { + && mRequestType != BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS + && mRequestType != BluetoothDevice.REQUEST_TYPE_SIM_ACCESS) { if (DEBUG) Log.d(TAG, "checkUserChoice(): Unknown RequestType " + mRequestType); return processed; } @@ -239,6 +243,20 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { } else { Log.e(TAG, "Bad messagePermission: " + messagePermission); } + } else if(mRequestType == BluetoothDevice.REQUEST_TYPE_SIM_ACCESS) { + int simPermission = cachedDevice.getSimPermissionChoice(); + + if (simPermission == CachedBluetoothDevice.ACCESS_UNKNOWN) { + // Leave 'processed' as false. + } else if (simPermission == CachedBluetoothDevice.ACCESS_ALLOWED) { + sendReplyIntentToReceiver(true); + processed = true; + } else if (simPermission == CachedBluetoothDevice.ACCESS_REJECTED) { + sendReplyIntentToReceiver(false); + processed = true; + } else { + Log.e(TAG, "Bad simPermission: " + simPermission); + } } if (DEBUG) Log.d(TAG,"checkUserChoice(): returning " + processed); return processed; diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java index c8b9c5b22..cf289a75d 100755 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -66,10 +66,6 @@ final class CachedBluetoothDevice implements Comparable { private boolean mVisible; - private int mPhonebookPermissionChoice; - - private int mMessagePermissionChoice; - private int mMessageRejectionCount; private final Collection mCallbacks = new ArrayList(); @@ -553,6 +549,7 @@ final class CachedBluetoothDevice implements Comparable { mConnectAfterPairing = false; // cancel auto-connect setPhonebookPermissionChoice(ACCESS_UNKNOWN); setMessagePermissionChoice(ACCESS_UNKNOWN); + setSimPermissionChoice(ACCESS_UNKNOWN); mMessageRejectionCount = 0; saveMessageRejectionCount(); } @@ -709,6 +706,26 @@ final class CachedBluetoothDevice implements Comparable { editor.commit(); } + int getSimPermissionChoice() { + int permission = mDevice.getSimAccessPermission(); + if (permission == BluetoothDevice.ACCESS_ALLOWED) { + return ACCESS_ALLOWED; + } else if (permission == BluetoothDevice.ACCESS_REJECTED) { + return ACCESS_REJECTED; + } + return ACCESS_UNKNOWN; + } + + void setSimPermissionChoice(int permissionChoice) { + int permission = BluetoothDevice.ACCESS_UNKNOWN; + if (permissionChoice == ACCESS_ALLOWED) { + permission = BluetoothDevice.ACCESS_ALLOWED; + } else if (permissionChoice == ACCESS_REJECTED) { + permission = BluetoothDevice.ACCESS_REJECTED; + } + mDevice.setSimAccessPermission(permission); + } + int getMessagePermissionChoice() { int permission = mDevice.getMessageAccessPermission(); if (permission == BluetoothDevice.ACCESS_ALLOWED) { diff --git a/src/com/android/settings/bluetooth/SapProfile.java b/src/com/android/settings/bluetooth/SapProfile.java new file mode 100644 index 000000000..95dfd1f2f --- /dev/null +++ b/src/com/android/settings/bluetooth/SapProfile.java @@ -0,0 +1,216 @@ +/* + * 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.settings.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSap; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothUuid; +import android.content.Context; +import android.os.ParcelUuid; +import android.util.Log; + +import com.android.settings.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * SapProfile handles Bluetooth SAP profile. + */ +final class SapProfile implements LocalBluetoothProfile { + private static final String TAG = "SapProfile"; + private static boolean V = true; + + private BluetoothSap mService; + private boolean mIsProfileReady; + + private final LocalBluetoothAdapter mLocalAdapter; + private final CachedBluetoothDeviceManager mDeviceManager; + private final LocalBluetoothProfileManager mProfileManager; + + static final ParcelUuid[] UUIDS = { + BluetoothUuid.SAP, + }; + + static final String NAME = "SAP"; + + // Order of this profile in device profiles list + private static final int ORDINAL = 10; + + // These callbacks run on the main thread. + private final class SapServiceListener + implements BluetoothProfile.ServiceListener { + + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (V) Log.d(TAG,"Bluetooth service connected"); + mService = (BluetoothSap) proxy; + // We just bound to the service, so refresh the UI for any connected SAP devices. + List 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, "SapProfile found new device: " + nextDevice); + device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice); + } + device.onProfileStateChanged(SapProfile.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() { + return mIsProfileReady; + } + + SapProfile(Context context, LocalBluetoothAdapter adapter, + CachedBluetoothDeviceManager deviceManager, + LocalBluetoothProfileManager profileManager) { + mLocalAdapter = adapter; + mDeviceManager = deviceManager; + mProfileManager = profileManager; + mLocalAdapter.getProfileProxy(context, new SapServiceListener(), + BluetoothProfile.SAP); + } + + public boolean isConnectable() { + return true; + } + + public boolean isAutoConnectable() { + return true; + } + + public boolean connect(BluetoothDevice device) { + if (mService == null) return false; + List sinks = mService.getConnectedDevices(); + if (sinks != null) { + for (BluetoothDevice sink : sinks) { + mService.disconnect(sink); + } + } + return mService.connect(device); + } + + public boolean disconnect(BluetoothDevice device) { + if (mService == null) return false; + List deviceList = mService.getConnectedDevices(); + if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) { + if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) { + mService.setPriority(device, BluetoothProfile.PRIORITY_ON); + } + return mService.disconnect(device); + } else { + return false; + } + } + + public int getConnectionStatus(BluetoothDevice device) { + if (mService == null) return BluetoothProfile.STATE_DISCONNECTED; + List deviceList = mService.getConnectedDevices(); + + return !deviceList.isEmpty() && deviceList.get(0).equals(device) + ? mService.getConnectionState(device) + : BluetoothProfile.STATE_DISCONNECTED; + } + + 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 getConnectedDevices() { + if (mService == null) return new ArrayList(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_sap; + } + + public int getSummaryResourceForDevice(BluetoothDevice device) { + int state = getConnectionStatus(device); + switch (state) { + case BluetoothProfile.STATE_DISCONNECTED: + return R.string.bluetooth_sap_profile_summary_use_for; + + case BluetoothProfile.STATE_CONNECTED: + return R.string.bluetooth_sap_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.SAP, + mService); + mService = null; + }catch (Throwable t) { + Log.w(TAG, "Error cleaning up SAP proxy", t); + } + } + } +} -- cgit v1.2.3