diff options
8 files changed, 347 insertions, 52 deletions
diff --git a/res/layout/bluetooth_access.xml b/res/layout/bluetooth_access.xml index 3bfb689..f398cef 100644 --- a/res/layout/bluetooth_access.xml +++ b/res/layout/bluetooth_access.xml @@ -40,7 +40,8 @@ style="?android:attr/textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="2dip" + android:layout_marginTop="20dip" + android:layout_marginBottom="20dip" android:text="@string/bluetooth_remember_choice" /> </LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index ad3e5be..4b3e261 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -276,6 +276,8 @@ <string name="bluetooth_connected_no_headset">Connected (no phone)</string> <!-- Bluetooth settings. Message when connected to a device, except for media audio. [CHAR LIMIT=40] --> <string name="bluetooth_connected_no_a2dp">Connected (no media)</string> + <!-- Bluetooth settings. Message when connected to a device, except for map. [CHAR LIMIT=40] --> + <string name="bluetooth_connected_no_map">Connected (no message access)</string> <!-- Bluetooth settings. Message when connected to a device, except for phone/media audio. [CHAR LIMIT=40] --> <string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)</string> <!-- Bluetooth settings. Message when a device is disconnected --> @@ -349,7 +351,7 @@ <string name="bluetooth_connection_dialog_text">"Do you want to connect to \u0022<xliff:g id="device_name">%1$s</xliff:g>\u0022?"</string> <!-- Activity label of BluetoothPbPermissionActivity, also used as Strings in the permission dialog [CHAR LIMIT=none] --> - <string name="bluetooth_phonebook_request">"Phone book request"</string> + <string name="bluetooth_phonebook_request">"Phone book access request"</string> <!-- Bluetooth phone book permission Alert Activity text [CHAR LIMIT=none] --> <string name="bluetooth_pb_acceptance_dialog_text">%1$s wants to access your contacts and call history. Give access to %2$s?</string> @@ -360,7 +362,7 @@ <string name="bluetooth_pb_remember_choice">Don\'t ask again</string> <!-- Activity label of BluetoothMessagePermissionActivity, also used as Strings in the permission dialog [CHAR LIMIT=none] --> - <string name="bluetooth_map_request">"Message request"</string> + <string name="bluetooth_map_request">"Message access request"</string> <!-- Bluetooth message permission Alert Activity text [CHAR LIMIT=none] --> <string name="bluetooth_map_acceptance_dialog_text">%1$s wants to access your messages. Give access to %2$s?</string> @@ -1147,6 +1149,8 @@ <string name="bluetooth_profile_pan">Internet access</string> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (sharing this device's Internet connection). [CHAR LIMIT=40]--> <string name="bluetooth_profile_pan_nap">Internet connection sharing</string> + <!-- Bluetooth settings. The user-visible string that is used whenever referring to the map profile. --> + <string name="bluetooth_profile_map">Message Access</string> <!-- Bluetooth settings. Message for disconnecting from the A2DP profile. [CHAR LIMIT=80] --> <string name="bluetooth_disconnect_a2dp_profile"><xliff:g id="device_name">%1$s</xliff:g> will be disconnected from media audio.</string> @@ -1179,6 +1183,8 @@ <string name="bluetooth_headset_profile_summary_connected">Connected to phone audio</string> <!-- Bluetooth settings. Connection options screen. The summary for the OPP checkbox preference when OPP is connected. --> <string name="bluetooth_opp_profile_summary_connected">Connected to file transfer server</string> + <!-- Bluetooth settings. Connection options screen. The summary for the map checkbox preference when map is connected. --> + <string name="bluetooth_map_profile_summary_connected">Connected to map</string> <!-- Bluetooth settings. Connection options screen. The summary for the OPP checkbox preference when OPP is not connected. --> <string name="bluetooth_opp_profile_summary_not_connected">Not connected to file transfer server</string> <!-- Bluetooth settings. Connection options screen. The summary for the HID checkbox preference when HID is connected. --> @@ -1202,6 +1208,8 @@ for the PAN checkbox preference that describes how checking it will set the PAN profile as preferred. --> <string name="bluetooth_pan_profile_summary_use_for">Use for Internet access</string> + <!-- Bluetooth settings. Connection options screen. The summary for the map checkbox preference that describes how checking it will set the map profile as preferred. --> + <string name="bluetooth_map_profile_summary_use_for">Use for map</string> <!-- Bluetooth settings. Dock Setting Title --> <string name="bluetooth_dock_settings">Dock Settings</string> diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java index aac1d4e..012aff0 100755 --- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java +++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java @@ -28,7 +28,6 @@ import android.util.Log; import android.view.View; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.EditText; import android.widget.TextView; import android.widget.Button; import android.widget.CompoundButton.OnCheckedChangeListener; @@ -64,6 +63,9 @@ public class BluetoothPermissionActivity extends AlertActivity implements public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)) { + int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, + BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); + if (requestType != mRequestType) return; BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (mDevice.equals(device)) dismissDialog(); } @@ -94,6 +96,8 @@ public class BluetoothPermissionActivity extends AlertActivity implements mRequestType = i.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); + if(DEBUG) Log.i(TAG, "onCreate() Request type: " + mRequestType); + if (mRequestType == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) { showDialog(getString(R.string.bluetooth_connection_permission_request), mRequestType); } else if (mRequestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) { @@ -117,6 +121,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements final AlertController.AlertParams p = mAlertParams; p.mIconId = android.R.drawable.ic_dialog_info; p.mTitle = title; + if(DEBUG) Log.i(TAG, "showDialog() Request type: " + mRequestType + " this: " + this); switch(requestType) { case BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION: @@ -137,15 +142,16 @@ public class BluetoothPermissionActivity extends AlertActivity implements setupAlert(); } - - private String createDisplayText(String message) { - String mMessage1 = message; - return mMessage1; + @Override + public void onBackPressed() { + /*we need an answer so ignore back button presses during auth */ + if(DEBUG) Log.i(TAG, "Back button pressed! ignoring"); + return; } - private String createRemoteName() { String mRemoteName = mDevice != null ? mDevice.getAliasName() : null; + if (mRemoteName == null) mRemoteName = getString(R.string.unknown); return mRemoteName; } @@ -154,8 +160,8 @@ public class BluetoothPermissionActivity extends AlertActivity implements String mRemoteName = createRemoteName(); mView = getLayoutInflater().inflate(R.layout.bluetooth_connection_access, null); messageView = (TextView)mView.findViewById(R.id.message); - messageView.setText(createDisplayText(getString(R.string.bluetooth_connection_dialog_text, - mRemoteName))); + messageView.setText(getString(R.string.bluetooth_connection_dialog_text, + mRemoteName)); return mView; } @@ -177,8 +183,8 @@ public class BluetoothPermissionActivity extends AlertActivity implements String mRemoteName = createRemoteName(); mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null); messageView = (TextView)mView.findViewById(R.id.message); - messageView.setText(createDisplayText(getString(R.string.bluetooth_pb_acceptance_dialog_text, - mRemoteName, mRemoteName))); + messageView.setText(getString(R.string.bluetooth_pb_acceptance_dialog_text, + mRemoteName, mRemoteName)); createCheckbox(R.id.bluetooth_remember_choice); return mView; } @@ -186,8 +192,8 @@ public class BluetoothPermissionActivity extends AlertActivity implements String mRemoteName = createRemoteName(); mView = getLayoutInflater().inflate(R.layout.bluetooth_access, null); messageView = (TextView)mView.findViewById(R.id.message); - messageView.setText(createDisplayText(getString(R.string.bluetooth_map_acceptance_dialog_text, - mRemoteName, mRemoteName))); + messageView.setText(getString(R.string.bluetooth_map_acceptance_dialog_text, + mRemoteName, mRemoteName)); createCheckbox(R.id.bluetooth_remember_choice); return mView; } @@ -221,6 +227,8 @@ public class BluetoothPermissionActivity extends AlertActivity implements if (mReturnPackage != null && mReturnClass != null) { intent.setClassName(mReturnPackage, mReturnClass); } + if(DEBUG) Log.i(TAG, "sendIntentToReceiver() Request type: " + mRequestType + + " mReturnPackage" + mReturnPackage + " mReturnClass" + mReturnClass); intent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, allowed ? BluetoothDevice.CONNECTION_ACCESS_YES : @@ -230,6 +238,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements intent.putExtra(extraName, extraValue); } intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType); sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN); } @@ -271,12 +280,11 @@ public class BluetoothPermissionActivity extends AlertActivity implements bluetoothManager.getProfileManager(), mDevice); } - if (permissionType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS){ + if(permissionType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS){ cachedDevice.setPhonebookPermissionChoice(permissionChoice); }else if (permissionType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS){ cachedDevice.setMessagePermissionChoice(permissionChoice); } - } } diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java index 343018e..c3b93be 100644 --- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java +++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java @@ -36,7 +36,11 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { private static final String TAG = "BluetoothPermissionRequest"; private static final boolean DEBUG = Utils.V; - public static final int NOTIFICATION_ID = android.R.drawable.stat_sys_data_bluetooth; + private static final int NOTIFICATION_ID = android.R.drawable.stat_sys_data_bluetooth; + + private static final String NOTIFICATION_TAG_PBAP = "Phonebook Access" ; + private static final String NOTIFICATION_TAG_MAP = "Message Access"; + Context mContext; int mRequestType; @@ -49,7 +53,7 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { mContext = context; String action = intent.getAction(); - if (DEBUG) Log.d(TAG, "onReceive"); + if (DEBUG) Log.d(TAG, "onReceive" + action); if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) { // convert broadcast intent into activity intent (same action string) @@ -59,14 +63,8 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { mReturnPackage = intent.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME); mReturnClass = intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME); - Intent connectionAccessIntent = new Intent(action); - connectionAccessIntent.setClass(context, BluetoothPermissionActivity.class); - connectionAccessIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, - mRequestType); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_PACKAGE_NAME, mReturnPackage); - connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_CLASS_NAME, mReturnClass); + if (DEBUG) Log.d(TAG, "onReceive request type: " + mRequestType + " return " + + mReturnPackage + "," + mReturnClass); // Check if user had made decisions on accepting or rejecting the phonebook access // request. If there is, reply the request and return, no need to start permission @@ -75,8 +73,22 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { return; } - String deviceAddress = mDevice != null ? mDevice.getAddress() : null; + Intent connectionAccessIntent = new Intent(action); + connectionAccessIntent.setClass(context, BluetoothPermissionActivity.class); + // We use the FLAG_ACTIVITY_MULTIPLE_TASK since we can have multiple concurrent access requests + connectionAccessIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + connectionAccessIntent.setType(Integer.toString(mRequestType)); /* This is needed to create two pending + intents to the same activity. + The value is not used in the activity. */ + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, + mRequestType); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_PACKAGE_NAME, mReturnPackage); + connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_CLASS_NAME, mReturnClass); + String deviceAddress = mDevice != null ? mDevice.getAddress() : null; + String title = null; + String message = null; PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); @@ -93,31 +105,59 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { deleteIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); deleteIntent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, BluetoothDevice.CONNECTION_ACCESS_NO); - - Notification notification = new Notification( - android.R.drawable.stat_sys_data_bluetooth, - context.getString(R.string.bluetooth_connection_permission_request), - System.currentTimeMillis()); + deleteIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType); String deviceName = mDevice != null ? mDevice.getAliasName() : null; - notification.setLatestEventInfo(context, - context.getString(R.string.bluetooth_connection_permission_request), - context.getString(R.string.bluetooth_connection_notif_message, deviceName), - PendingIntent.getActivity(context, 0, connectionAccessIntent, 0)); - notification.flags = Notification.FLAG_AUTO_CANCEL | - Notification.FLAG_ONLY_ALERT_ONCE; - notification.defaults = Notification.DEFAULT_SOUND; - notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0); + switch (mRequestType) { + case BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS: + title = context.getString(R.string.bluetooth_phonebook_request); + message = context.getString(R.string.bluetooth_pb_acceptance_dialog_text, deviceName, deviceName); + break; + case BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS: + title = context.getString(R.string.bluetooth_map_request); + message = context.getString(R.string.bluetooth_map_acceptance_dialog_text, deviceName, deviceName); + break; + default: + title = context.getString(R.string.bluetooth_connection_permission_request); + message = context.getString(R.string.bluetooth_connection_dialog_text, deviceName, deviceName); + break; + } + Notification notification = new Notification.Builder(context) + .setContentTitle(title) + .setTicker(message) + .setContentText(message) + .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth) + .setAutoCancel(true) + .setPriority(Notification.PRIORITY_MAX) + .setOnlyAlertOnce(false) + .setDefaults(Notification.DEFAULT_ALL) + .setContentIntent(PendingIntent.getActivity(context, 0, connectionAccessIntent, 0)) + .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0)) + .build(); + + notification.flags |= Notification.FLAG_NO_CLEAR; /* cannot be set with the builder */ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.notify(NOTIFICATION_ID, notification); + + notificationManager.notify(getNotificationTag(mRequestType),NOTIFICATION_ID, notification); } } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL)) { // Remove the notification NotificationManager manager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); - manager.cancel(NOTIFICATION_ID); + mRequestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, + BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); + manager.cancel(getNotificationTag(mRequestType), NOTIFICATION_ID); + } + } + + private String getNotificationTag(int requestType) { + if(requestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) { + return NOTIFICATION_TAG_PBAP; + } else if(mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) { + return NOTIFICATION_TAG_MAP; } + return null; } /** @@ -185,6 +225,7 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { Log.e(TAG, "Bad messagePermission: " + messagePermission); } } + if(DEBUG) Log.d(TAG,"checkUserChoice(): returning " + processed); return processed; } @@ -204,6 +245,7 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver { intent.putExtra(extraName, extraValue); } intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, mRequestType); mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN); } } diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java index 9742027..a9fd5ed 100755 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -140,6 +140,18 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> { mLocalNapRoleConnected = true; } } + if (profile instanceof MapProfile) { + profile.setPreferred(mDevice, true); + refresh(); + } + } else if (profile instanceof MapProfile && + newProfileState == BluetoothProfile.STATE_DISCONNECTED) { + if (mProfiles.contains(profile)) { + mRemovedProfiles.add(profile); + mProfiles.remove(profile); + } + profile.setPreferred(mDevice, false); + refresh(); } else if (mLocalNapRoleConnected && profile instanceof PanProfile && ((PanProfile) profile).isLocalRoleNap(mDevice) && newProfileState == BluetoothProfile.STATE_DISCONNECTED) { diff --git a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java index 6f4a765..f00b801 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java @@ -20,14 +20,15 @@ import android.app.QueuedWork; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; +import android.util.Log; /** * LocalBluetoothPreferences provides an interface to the preferences * related to Bluetooth. */ final class LocalBluetoothPreferences { -// private static final String TAG = "LocalBluetoothPreferences"; - + private static final String TAG = "LocalBluetoothPreferences"; + private static final boolean DEBUG = Utils.D; private static final String SHARED_PREFERENCES_NAME = "bluetooth_settings"; // If a device was picked from the device picker or was in discoverable mode @@ -61,6 +62,7 @@ final class LocalBluetoothPreferences { String deviceAddress) { LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context); if (manager == null) { + if(DEBUG) Log.v(TAG, "manager == null - do not show dialog."); return false; } @@ -72,6 +74,7 @@ final class LocalBluetoothPreferences { // If in appliance mode, do not show dialog in foreground. if ((context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_TYPE_APPLIANCE) == Configuration.UI_MODE_TYPE_APPLIANCE) { + if (DEBUG) Log.v(TAG, "in appliance mode - do not show dialog."); return false; } @@ -109,6 +112,7 @@ final class LocalBluetoothPreferences { } } } + if (DEBUG) Log.v(TAG, "Found no reason to show the dialog - do not show dialog."); return false; } diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java index 59a6944..78d6441 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java @@ -19,6 +19,7 @@ package com.android.settings.bluetooth; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothPbap; @@ -44,7 +45,7 @@ import java.util.List; */ final class LocalBluetoothProfileManager { private static final String TAG = "LocalBluetoothProfileManager"; - + private static final boolean DEBUG = Utils.D; /** Singleton instance. */ private static LocalBluetoothProfileManager sInstance; @@ -79,6 +80,7 @@ final class LocalBluetoothProfileManager { private A2dpProfile mA2dpProfile; private HeadsetProfile mHeadsetProfile; + private MapProfile mMapProfile; private final HidProfile mHidProfile; private OppProfile mOppProfile; private final PanProfile mPanProfile; @@ -119,11 +121,17 @@ final class LocalBluetoothProfileManager { addPanProfile(mPanProfile, PanProfile.NAME, 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); + //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 mPbapProfile = new PbapServerProfile(context); - Log.d(TAG, "LocalBluetoothProfileManager construction complete"); + if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete"); } /** @@ -137,7 +145,7 @@ final class LocalBluetoothProfileManager { // A2DP if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) { if (mA2dpProfile == null) { - Log.d(TAG, "Adding local A2DP profile"); + if(DEBUG) Log.d(TAG, "Adding local A2DP profile"); mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this); addProfile(mA2dpProfile, A2dpProfile.NAME, BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); @@ -150,7 +158,7 @@ final class LocalBluetoothProfileManager { if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) || BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) { if (mHeadsetProfile == null) { - Log.d(TAG, "Adding local HEADSET profile"); + if (DEBUG) Log.d(TAG, "Adding local HEADSET profile"); mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter, mDeviceManager, this); addProfile(mHeadsetProfile, HeadsetProfile.NAME, @@ -163,7 +171,7 @@ final class LocalBluetoothProfileManager { // OPP if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) { if (mOppProfile == null) { - Log.d(TAG, "Adding local OPP profile"); + if(DEBUG) Log.d(TAG, "Adding local OPP profile"); mOppProfile = new OppProfile(); // Note: no event handler for OPP, only name map. mProfileNameMap.put(OppProfile.NAME, mOppProfile); @@ -301,7 +309,6 @@ final class LocalBluetoothProfileManager { return mPbapProfile; } - /** * Fill in a list of LocalBluetoothProfile objects that are supported by * the local device and the remote device. @@ -354,7 +361,7 @@ final class LocalBluetoothProfileManager { } if(isPanNapConnected) - Log.d(TAG, "Valid PAN-NAP connection exists."); + if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists."); if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) && mPanProfile != null) || isPanNapConnected) { profiles.add(mPanProfile); diff --git a/src/com/android/settings/bluetooth/MapProfile.java b/src/com/android/settings/bluetooth/MapProfile.java new file mode 100644 index 0000000..fb1b180 --- /dev/null +++ b/src/com/android/settings/bluetooth/MapProfile.java @@ -0,0 +1,213 @@ +/* + * 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.BluetoothMap; +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; + +/** + * MapProfile handles Bluetooth MAP profile. + */ +final class MapProfile implements LocalBluetoothProfile { + private static final String TAG = "MapProfile"; + private static boolean V = true; + + private BluetoothMap 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"; + + // Order of this profile in device profiles list + + // These callbacks run on the main thread. + private final class MapServiceListener + implements BluetoothProfile.ServiceListener { + + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (V) Log.d(TAG,"Bluetooth service connected"); + mService = (BluetoothMap) 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(MapProfile.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; + } + + MapProfile(Context context, LocalBluetoothAdapter adapter, + CachedBluetoothDeviceManager deviceManager, + LocalBluetoothProfileManager profileManager) { + mLocalAdapter = adapter; + mDeviceManager = deviceManager; + mProfileManager = profileManager; + mLocalAdapter.getProfileProxy(context, new MapServiceListener(), + BluetoothProfile.MAP); + } + + public boolean isConnectable() { + return true; + } + + public boolean isAutoConnectable() { + return true; + } + + public boolean connect(BluetoothDevice device) { + if(V)Log.d(TAG,"connect() - should not get called"); + return true; // MAP never connects out + } + + public boolean disconnect(BluetoothDevice device) { + if (mService == null) return false; + List<BluetoothDevice> 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<BluetoothDevice> deviceList = mService.getConnectedDevices(); + if(V) Log.d(TAG,"getConnectionStatus: status is: "+ mService.getConnectionState(device)); + + 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<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 BluetoothProfile.MAP; + } + + 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, + mService); + mService = null; + }catch (Throwable t) { + Log.w(TAG, "Error cleaning up MAP proxy", t); + } + } + } +} |