Merge changes from topic "BLE debug information implementation"
* changes:
BLE: GattService debug infomation implementation
BLE: Rename existing variables in AppScanStats
diff --git a/Android.mk b/Android.mk
index f4a0d5d..0f80f52 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,6 +26,7 @@
services.net \
libprotobuf-java-lite \
bluetooth-protos-lite \
+ guava \
LOCAL_STATIC_ANDROID_LIBRARIES := \
androidx.core_core \
diff --git a/jni/Android.bp b/jni/Android.bp
index 39b9f3f..e0034b1 100644
--- a/jni/Android.bp
+++ b/jni/Android.bp
@@ -25,11 +25,9 @@
"libchrome",
"libnativehelper",
"liblog",
- "libutils",
],
static_libs: [
"libbluetooth-types",
- "libcutils",
],
cflags: [
"-Wall",
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 34eb2bb..6908b2f 100644
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -20,7 +20,6 @@
#include "utils/Log.h"
#include "utils/misc.h"
-#include <cutils/properties.h>
#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>
@@ -598,17 +597,12 @@
acquire_wake_lock_callout, release_wake_lock_callout,
};
-#define PROPERTY_BT_LIBRARY_NAME "ro.bluetooth.library_name"
-#define DEFAULT_BT_LIBRARY_NAME "libbluetooth.so"
-
int hal_util_load_bt_library(const bt_interface_t** interface) {
const char* sym = BLUETOOTH_INTERFACE_STRING;
bt_interface_t* itf = nullptr;
// The library name is not set by default, so the preset library name is used.
- char path[PROPERTY_VALUE_MAX] = "";
- property_get(PROPERTY_BT_LIBRARY_NAME, path, DEFAULT_BT_LIBRARY_NAME);
- void* handle = dlopen(path, RTLD_NOW);
+ void* handle = dlopen("libbluetooth.so", RTLD_NOW);
if (!handle) {
const char* err_str = dlerror();
ALOGE("%s: failed to load Bluetooth library, error=%s", __func__,
@@ -1261,7 +1255,9 @@
goto done;
}
uuidBytes = env->GetByteArrayElements(uuid, nullptr);
- nativeServiceName = env->GetStringUTFChars(serviceName, nullptr);
+ if (serviceName != nullptr) {
+ nativeServiceName = env->GetStringUTFChars(serviceName, nullptr);
+ }
if (uuidBytes == nullptr) {
jniThrowIOException(env, EINVAL);
goto done;
diff --git a/src/com/android/bluetooth/AlertActivity.java b/src/com/android/bluetooth/AlertActivity.java
new file mode 100644
index 0000000..6de2cec
--- /dev/null
+++ b/src/com/android/bluetooth/AlertActivity.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 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.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * An activity that follows the visual style of an AlertDialog.
+ *
+ * @see #mAlert
+ * @see #setupAlert()
+ */
+public abstract class AlertActivity extends Activity implements DialogInterface.OnDismissListener,
+ DialogInterface.OnCancelListener {
+
+ /**
+ * The model for the alert.
+ *
+ */
+ protected AlertDialog.Builder mAlertBuilder;
+ private AlertDialog mAlert;
+
+ public AlertActivity() {}
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mAlertBuilder = new AlertDialog.Builder(this);
+ mAlertBuilder.setOnDismissListener(this);
+ mAlertBuilder.setOnCancelListener(this);
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (!isFinishing()) {
+ finish();
+ }
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (!isFinishing()) {
+ finish();
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ return dispatchPopulateAccessibilityEvent(this, event);
+ }
+
+ private static boolean dispatchPopulateAccessibilityEvent(Activity act,
+ AccessibilityEvent event) {
+ event.setClassName(Dialog.class.getName());
+ event.setPackageName(act.getPackageName());
+
+ ViewGroup.LayoutParams params = act.getWindow().getAttributes();
+ boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT)
+ && (params.height == ViewGroup.LayoutParams.MATCH_PARENT);
+ event.setFullScreen(isFullScreen);
+
+ return false;
+ }
+
+ protected void setupAlert() {
+ mAlert = mAlertBuilder.create();
+ mAlert.show();
+ }
+
+ protected void changeIconAttribute(int attrId) {
+ if (mAlert == null) return;
+ mAlert.setIconAttribute(attrId);
+ }
+ protected void changeTitle(CharSequence title) {
+ if (mAlert == null) return;
+ mAlert.setTitle(title);
+ }
+
+ protected void changeButtonVisibility(int identifier, int visibility) {
+ if (mAlert == null) return;
+ mAlert.getButton(identifier).setVisibility(visibility);
+ }
+
+ protected void changeButtonText(int identifier, CharSequence text) {
+ if (mAlert == null) return;
+ mAlert.getButton(identifier).setText(text);
+ }
+
+ protected void changeButtonEnabled(int identifier, boolean enable) {
+ if (mAlert == null) return;
+ mAlert.getButton(identifier).setEnabled(enable);
+ }
+}
diff --git a/src/com/android/bluetooth/Utils.java b/src/com/android/bluetooth/Utils.java
index 4432067..cb098ac 100644
--- a/src/com/android/bluetooth/Utils.java
+++ b/src/com/android/bluetooth/Utils.java
@@ -16,7 +16,6 @@
package com.android.bluetooth;
-import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -41,7 +40,9 @@
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
-import java.util.List;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -468,4 +469,14 @@
public static String getUidPidString() {
return "uid/pid=" + Binder.getCallingUid() + "/" + Binder.getCallingPid();
}
+
+ /**
+ * Get system local time
+ *
+ * @return "MM-dd HH:mm:ss.SSS"
+ */
+ public static String getLocalTimeString() {
+ return DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS")
+ .withZone(ZoneId.systemDefault()).format(Instant.now());
+ }
}
diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java
index cebf767..167fc10 100644
--- a/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -269,7 +269,13 @@
}
}
- boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects A2dp for the remote bluetooth device
+ *
+ * @param device is the device with which we would like to disconnect a2dp
+ * @return true if profile disconnected, false if device not connected over a2dp
+ */
+ public boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
if (DBG) {
Log.d(TAG, "disconnect(): " + device);
@@ -427,19 +433,9 @@
}
}
- private void storeActiveDeviceVolume() {
- // Make sure volume has been stored before been removed from active.
- if (mFactory.getAvrcpTargetService() != null && mActiveDevice != null) {
- mFactory.getAvrcpTargetService().storeVolumeForDevice(mActiveDevice);
- }
- }
-
private void removeActiveDevice(boolean forceStopPlayingAudio) {
BluetoothDevice previousActiveDevice = mActiveDevice;
synchronized (mStateMachines) {
- // Make sure volume has been store before device been remove from active.
- storeActiveDeviceVolume();
-
// This needs to happen before we inform the audio manager that the device
// disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
updateAndBroadcastActiveDevice(null);
@@ -494,22 +490,6 @@
}
/**
- * Early notification that Hearing Aids will be the active device. This allows the A2DP to save
- * its volume before the Audio Service starts changing its media stream.
- */
- public void earlyNotifyHearingAidActive() {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
-
- synchronized (mStateMachines) {
- // Switch active device from A2DP to Hearing Aids.
- if (DBG) {
- Log.d(TAG, "earlyNotifyHearingAidActive: Save volume for " + mActiveDevice);
- }
- storeActiveDeviceVolume();
- }
- }
-
- /**
* Set the active device.
*
* @param device the active device
@@ -548,14 +528,6 @@
codecStatus = sm.getCodecStatus();
boolean deviceChanged = !Objects.equals(device, mActiveDevice);
- if (deviceChanged) {
- // Switch from one A2DP to another A2DP device
- if (DBG) {
- Log.d(TAG, "Switch A2DP devices to " + device + " from " + mActiveDevice);
- }
- storeActiveDeviceVolume();
- }
-
// This needs to happen before we inform the audio manager that the device
// disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
updateAndBroadcastActiveDevice(device);
diff --git a/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
index 61ed75e..1a2bba7 100644
--- a/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
+++ b/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
@@ -243,24 +243,6 @@
}
/**
- * Store the current system volume for a device in order to be retrieved later.
- */
- public void storeVolumeForDevice(BluetoothDevice device) {
- if (device == null) return;
-
- List<BluetoothDevice> HAActiveDevices = null;
- if (mFactory.getHearingAidService() != null) {
- HAActiveDevices = mFactory.getHearingAidService().getActiveDevices();
- }
- if (HAActiveDevices != null
- && (HAActiveDevices.get(0) != null || HAActiveDevices.get(1) != null)) {
- Log.d(TAG, "Do not store volume when Hearing Aid devices is active");
- return;
- }
- mVolumeManager.storeVolumeForDevice(device);
- }
-
- /**
* Remove the stored volume for a device.
*/
public void removeStoredVolumeForDevice(BluetoothDevice device) {
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index ae94a4d..e3abc4d 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -223,7 +223,6 @@
mService.sBrowseTree.mRootNode.addChild(mBrowseTree.mRootNode);
BluetoothMediaBrowserService.notifyChanged(mService
.sBrowseTree.mRootNode);
- BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState());
mBrowsingConnected = true;
}
@@ -233,12 +232,10 @@
mAddressedPlayer.updateCurrentTrack(null);
mBrowseTree.mNowPlayingNode.setCached(false);
BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mNowPlayingNode);
- BluetoothMediaBrowserService.addressedPlayerChanged(null);
mService.sBrowseTree.mRootNode.removeChild(
mBrowseTree.mRootNode);
BluetoothMediaBrowserService.notifyChanged(mService
.sBrowseTree.mRootNode);
- BluetoothMediaBrowserService.trackChanged(null);
mBrowsingConnected = false;
}
@@ -299,6 +296,7 @@
@Override
public void enter() {
if (mMostRecentState == BluetoothProfile.STATE_CONNECTING) {
+ BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState());
broadcastConnectionStateChanged(BluetoothProfile.STATE_CONNECTED);
BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks);
} else {
@@ -712,6 +710,8 @@
@Override
public void enter() {
onBrowsingDisconnected();
+ BluetoothMediaBrowserService.trackChanged(null);
+ BluetoothMediaBrowserService.addressedPlayerChanged(null);
broadcastConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTING);
transitionTo(mDisconnected);
}
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index e0452bf..e4a5ae0 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -27,6 +27,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
+import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothMetadataListener;
@@ -68,10 +69,23 @@
import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.Utils;
+import com.android.bluetooth.a2dp.A2dpService;
+import com.android.bluetooth.a2dpsink.A2dpSinkService;
import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.btservice.storage.MetadataDatabase;
import com.android.bluetooth.gatt.GattService;
+import com.android.bluetooth.hearingaid.HearingAidService;
+import com.android.bluetooth.hfp.HeadsetService;
+import com.android.bluetooth.hfpclient.HeadsetClientService;
+import com.android.bluetooth.hid.HidDeviceService;
+import com.android.bluetooth.hid.HidHostService;
+import com.android.bluetooth.map.BluetoothMapService;
+import com.android.bluetooth.mapclient.MapClientService;
+import com.android.bluetooth.pan.PanService;
+import com.android.bluetooth.pbap.BluetoothPbapService;
+import com.android.bluetooth.pbapclient.PbapClientService;
+import com.android.bluetooth.sap.SapService;
import com.android.bluetooth.sdp.SdpManager;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -200,6 +214,20 @@
private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder;
+ private A2dpService mA2dpService;
+ private A2dpSinkService mA2dpSinkService;
+ private HeadsetService mHeadsetService;
+ private HeadsetClientService mHeadsetClientService;
+ private BluetoothMapService mMapService;
+ private MapClientService mMapClientService;
+ private HidDeviceService mHidDeviceService;
+ private HidHostService mHidHostService;
+ private PanService mPanService;
+ private BluetoothPbapService mPbapService;
+ private PbapClientService mPbapClientService;
+ private HearingAidService mHearingAidService;
+ private SapService mSapService;
+
/**
* Register a {@link ProfileService} with AdapterService.
*
@@ -294,6 +322,7 @@
mAdapterProperties.onBluetoothReady();
updateUuids();
setBluetoothClassFromConfig();
+ initProfileServices();
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS);
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS_BLE);
mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
@@ -769,6 +798,229 @@
}
}
+ /**
+ * Verifies whether the profile is supported by the local bluetooth adapter by checking a
+ * bitmask of its supported profiles
+ *
+ * @param remoteDeviceUuids is an array of all supported profiles by the remote device
+ * @param localDeviceUuids is an array of all supported profiles by the local device
+ * @param profile is the profile we are checking for support
+ * @param device is the remote device we wish to connect to
+ * @return true if the profile is supported by both the local and remote device, false otherwise
+ */
+ private boolean isSupported(ParcelUuid[] localDeviceUuids, ParcelUuid[] remoteDeviceUuids,
+ int profile, BluetoothDevice device) {
+ if (remoteDeviceUuids == null || remoteDeviceUuids.length == 0) {
+ Log.e(TAG, "isSupported: Remote Device Uuids Empty");
+ }
+
+ if (profile == BluetoothProfile.HEADSET) {
+ return (BluetoothUuid.isUuidPresent(localDeviceUuids, BluetoothUuid.HSP_AG)
+ && BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.HSP))
+ || (BluetoothUuid.isUuidPresent(localDeviceUuids, BluetoothUuid.Handsfree_AG)
+ && BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.Handsfree));
+ }
+ if (profile == BluetoothProfile.HEADSET_CLIENT) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.Handsfree_AG)
+ && BluetoothUuid.isUuidPresent(localDeviceUuids, BluetoothUuid.Handsfree);
+ }
+ if (profile == BluetoothProfile.A2DP) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.AdvAudioDist)
+ || BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.AudioSink);
+ }
+ if (profile == BluetoothProfile.A2DP_SINK) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.AdvAudioDist)
+ || BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.AudioSource);
+ }
+ if (profile == BluetoothProfile.OPP) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.ObexObjectPush);
+ }
+ if (profile == BluetoothProfile.HID_HOST) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.Hid)
+ || BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.Hogp);
+ }
+ if (profile == BluetoothProfile.HID_DEVICE) {
+ return mHidDeviceService.getConnectionState(device)
+ == BluetoothProfile.STATE_DISCONNECTED;
+ }
+ if (profile == BluetoothProfile.PAN) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.NAP);
+ }
+ if (profile == BluetoothProfile.MAP) {
+ return mMapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED;
+ }
+ if (profile == BluetoothProfile.PBAP) {
+ return mPbapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED;
+ }
+ if (profile == BluetoothProfile.MAP_CLIENT) {
+ return true;
+ }
+ if (profile == BluetoothProfile.PBAP_CLIENT) {
+ return BluetoothUuid.isUuidPresent(localDeviceUuids, BluetoothUuid.PBAP_PCE)
+ && BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.PBAP_PSE);
+ }
+ if (profile == BluetoothProfile.HEARING_AID) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.HearingAid);
+ }
+ if (profile == BluetoothProfile.SAP) {
+ return BluetoothUuid.isUuidPresent(remoteDeviceUuids, BluetoothUuid.SAP);
+ }
+
+ Log.e(TAG, "isSupported: Unexpected profile passed in to function: " + profile);
+ return false;
+ }
+
+ /**
+ * Checks if any profile is enabled for the given device
+ *
+ * @param device is the device for which we are checking if any profiles are enabled
+ * @return true if any profile is enabled, false otherwise
+ */
+ private boolean isAnyProfileEnabled(BluetoothDevice device) {
+
+ if (mA2dpService != null
+ && mA2dpService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mA2dpSinkService != null
+ && mA2dpSinkService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mHeadsetService != null
+ && mHeadsetService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mHeadsetClientService != null
+ && mHeadsetClientService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mMapClientService != null
+ && mMapClientService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mHidHostService != null
+ && mHidHostService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mPanService != null
+ && mPanService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mPbapClientService != null
+ && mPbapClientService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+ if (mHearingAidService != null
+ && mHearingAidService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Connects only available profiles (those with {@link BluetoothProfile#PRIORITY_ON})
+ *
+ * @param device is the device with which we are connecting the profiles
+ * @return true
+ */
+ private boolean connectEnabledProfiles(BluetoothDevice device) {
+ ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device);
+ ParcelUuid[] localDeviceUuids = getUuids();
+
+ if (mA2dpService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.A2DP, device)
+ && mA2dpService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting A2dp");
+ mA2dpService.connect(device);
+ }
+ if (mA2dpSinkService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.A2DP_SINK, device)
+ && mA2dpSinkService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink");
+ mA2dpSinkService.connect(device);
+ }
+ if (mHeadsetService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEADSET, device)
+ && mHeadsetService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting Headset Profile");
+ mHeadsetService.connect(device);
+ }
+ if (mHeadsetClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEADSET_CLIENT, device)
+ && mHeadsetClientService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting HFP");
+ mHeadsetClientService.connect(device);
+ }
+ if (mMapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.MAP_CLIENT, device)
+ && mMapClientService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting MAP");
+ mMapClientService.connect(device);
+ }
+ if (mHidHostService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HID_HOST, device)
+ && mHidHostService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting Hid Host Profile");
+ mHidHostService.connect(device);
+ }
+ if (mPanService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.PAN, device)
+ && mPanService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting Pan Profile");
+ mPanService.connect(device);
+ }
+ if (mPbapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.PBAP_CLIENT, device)
+ && mPbapClientService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting Pbap");
+ mPbapClientService.connect(device);
+ }
+ if (mHearingAidService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEARING_AID, device)
+ && mHearingAidService.getPriority(device) > BluetoothProfile.PRIORITY_OFF) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting Hearing Aid Profile");
+ mHearingAidService.connect(device);
+ }
+
+ return true;
+ }
+
+ /**
+ * Verifies that all bluetooth profile services are running
+ *
+ * @return true if all bluetooth profile services running, false otherwise
+ */
+ private boolean profileServicesRunning() {
+ if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
+ && mRegisteredProfiles.size() == mRunningProfiles.size()) {
+ return true;
+ }
+
+ Log.e(TAG, "profileServicesRunning: One or more supported services not running");
+ return false;
+ }
+
+ /**
+ * Initializes all the profile services fields
+ */
+ private void initProfileServices() {
+ Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services");
+ mA2dpService = A2dpService.getA2dpService();
+ mA2dpSinkService = A2dpSinkService.getA2dpSinkService();
+ mHeadsetService = HeadsetService.getHeadsetService();
+ mHeadsetClientService = HeadsetClientService.getHeadsetClientService();
+ mMapService = BluetoothMapService.getBluetoothMapService();
+ mMapClientService = MapClientService.getMapClientService();
+ mHidDeviceService = HidDeviceService.getHidDeviceService();
+ mHidHostService = HidHostService.getHidHostService();
+ mPanService = PanService.getPanService();
+ mPbapService = BluetoothPbapService.getBluetoothPbapService();
+ mPbapClientService = PbapClientService.getPbapClientService();
+ mHearingAidService = HearingAidService.getHearingAidService();
+ mSapService = SapService.getSapService();
+ }
+
private boolean isAvailable() {
return !mCleaningUp;
}
@@ -1240,6 +1492,34 @@
}
@Override
+ public boolean connectAllEnabledProfiles(BluetoothDevice device) {
+ if (!Utils.checkCaller()) {
+ Log.w(TAG, "connectAllEnabledProfiles() - Not allowed for non-active user");
+ return false;
+ }
+
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+ return service.connectAllEnabledProfiles(device);
+ }
+
+ @Override
+ public boolean disconnectAllEnabledProfiles(BluetoothDevice device) {
+ if (!Utils.checkCaller()) {
+ Log.w(TAG, "disconnectAllEnabledProfiles() - Not allowed for non-active user");
+ return false;
+ }
+
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+ return service.disconnectAllEnabledProfiles(device);
+ }
+
+ @Override
public String getRemoteName(BluetoothDevice device) {
if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "getRemoteName() - Not allowed for non-active user");
@@ -2144,6 +2424,202 @@
}
/**
+ * Connects all enabled and supported bluetooth profiles between the local and remote device
+ *
+ * @param device is the remote device with which to connect these profiles
+ * @return true if all profiles successfully connected, false if an error occurred
+ */
+ public boolean connectAllEnabledProfiles(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
+ if (!profileServicesRunning()) {
+ Log.e(TAG, "connectAllEnabledProfiles: Not all profile services running");
+ return false;
+ }
+
+ // Checks if any profiles are enabled and if so, only connect enabled profiles
+ if (isAnyProfileEnabled(device)) {
+ return connectEnabledProfiles(device);
+ }
+
+ int numProfilesConnected = 0;
+ ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device);
+ ParcelUuid[] localDeviceUuids = getUuids();
+
+ // All profile toggles disabled, so connects all supported profiles
+ if (mA2dpService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.A2DP, device)) {
+ mA2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting A2dp");
+ mA2dpService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mA2dpSinkService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.A2DP_SINK, device)) {
+ mA2dpSinkService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting A2dp Sink");
+ mA2dpSinkService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mHeadsetService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEADSET, device)) {
+ mHeadsetService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting Headset Profile");
+ mHeadsetService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mHeadsetClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEADSET_CLIENT, device)) {
+ mHeadsetClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting HFP");
+ mHeadsetClientService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mMapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.MAP_CLIENT, device)) {
+ mMapClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting MAP");
+ mMapClientService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mHidHostService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HID_HOST, device)) {
+ mHidHostService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG,
+ "connectAllEnabledProfiles: Connecting Hid Host Profile");
+ mHidHostService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mPanService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.PAN, device)) {
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting Pan Profile");
+ mPanService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mPbapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.PBAP_CLIENT, device)) {
+ mPbapClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ Log.i(TAG, "connectAllEnabledProfiles: Connecting Pbap");
+ mPbapClientService.connect(device);
+ numProfilesConnected++;
+ }
+ if (mHearingAidService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEARING_AID, device)) {
+ Log.i(TAG,
+ "connectAllEnabledProfiles: Connecting Hearing Aid Profile");
+ mHearingAidService.connect(device);
+ numProfilesConnected++;
+ }
+
+ Log.i(TAG, "connectAllEnabledProfiles: Number of Profiles Connected: "
+ + numProfilesConnected);
+
+ return true;
+ }
+
+ /**
+ * Disconnects all enabled and supported bluetooth profiles between the local and remote device
+ *
+ * @param device is the remote device with which to disconnect these profiles
+ * @return true if all profiles successfully disconnected, false if an error occurred
+ */
+ public boolean disconnectAllEnabledProfiles(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
+ if (!profileServicesRunning()) {
+ Log.e(TAG, "disconnectAllEnabledProfiles: Not all profile services bound");
+ return false;
+ }
+
+ ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device);
+ ParcelUuid[] localDeviceUuids = getUuids();
+
+ if (mA2dpService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.A2DP, device)) {
+ if (mA2dpService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mA2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp");
+ mA2dpService.disconnect(device);
+ }
+ if (mA2dpSinkService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.A2DP_SINK, device)) {
+ if (mA2dpSinkService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mA2dpSinkService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink");
+ mA2dpSinkService.disconnect(device);
+ }
+ if (mHeadsetService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEADSET, device)) {
+ if (mHeadsetService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mHeadsetService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG,
+ "disconnectAllEnabledProfiles: Disconnecting Headset Profile");
+ mHeadsetService.disconnect(device);
+ }
+ if (mHeadsetClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEADSET_CLIENT, device)) {
+ if (mHeadsetClientService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mHeadsetClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP");
+ mHeadsetClientService.disconnect(device);
+ }
+ if (mMapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.MAP_CLIENT, device)) {
+ if (mMapClientService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mMapClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP");
+ mMapClientService.disconnect(device);
+ }
+ if (mHidDeviceService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HID_DEVICE, device)) {
+ Log.i(TAG,
+ "disconnectAllEnabledProfiles: Disconnecting Hid Device "
+ + "Profile");
+ mHidDeviceService.disconnect(device);
+ }
+ if (mHidHostService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HID_HOST, device)) {
+ if (mHidHostService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mHidHostService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG,
+ "disconnectAllEnabledProfiles: Disconnecting Hid Host Profile");
+ mHidHostService.disconnect(device);
+ }
+ if (mPanService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.PAN, device)) {
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pan Profile");
+ mPanService.disconnect(device);
+ }
+ if (mPbapClientService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.PBAP_CLIENT, device)) {
+ if (mPbapClientService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mPbapClientService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap");
+ mPbapClientService.disconnect(device);
+ }
+ if (mHearingAidService != null && isSupported(localDeviceUuids, remoteDeviceUuids,
+ BluetoothProfile.HEARING_AID, device)) {
+ Log.i(TAG,
+ "disconnectAllEnabledProfiles: Disconnecting Hearing Aid Profile");
+ mHearingAidService.disconnect(device);
+ }
+
+ return true;
+ }
+
+ /**
* Same as API method {@link BluetoothDevice#getName()}
*
* @param device remote device of interest
@@ -2794,6 +3270,7 @@
profile.dump(sb);
}
mSilenceDeviceManager.dump(fd, writer, args);
+ mDatabaseManager.dump(writer);
writer.write(sb.toString());
writer.flush();
diff --git a/src/com/android/bluetooth/btservice/BondStateMachine.java b/src/com/android/bluetooth/btservice/BondStateMachine.java
index 382841a..3320f0e 100644
--- a/src/com/android/bluetooth/btservice/BondStateMachine.java
+++ b/src/com/android/bluetooth/btservice/BondStateMachine.java
@@ -519,7 +519,8 @@
BluetoothDevice.BOND_BONDING,
BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_PIN_REQUESTED, 0);
- infoLog("pinRequestCallback: " + address + " name:" + name + " cod:" + cod);
+ infoLog("pinRequestCallback: " + bdDevice.getAddress()
+ + " name:" + bdDevice.getName() + " cod:" + new BluetoothClass(cod));
Message msg = obtainMessage(PIN_REQUEST);
msg.obj = bdDevice;
diff --git a/src/com/android/bluetooth/btservice/Config.java b/src/com/android/bluetooth/btservice/Config.java
index 2b1f46c..0ec5b47 100644
--- a/src/com/android/bluetooth/btservice/Config.java
+++ b/src/com/android/bluetooth/btservice/Config.java
@@ -127,8 +127,8 @@
Log.v(TAG, "Adding " + config.mClass.getSimpleName());
profiles.add(config.mClass);
}
- sSupportedProfiles = profiles.toArray(new Class[profiles.size()]);
}
+ sSupportedProfiles = profiles.toArray(new Class[profiles.size()]);
}
static Class[] getSupportedProfiles() {
diff --git a/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java b/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java
index d0bddf1..e1033b9 100644
--- a/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java
+++ b/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java
@@ -37,4 +37,51 @@
public byte[] untethered_right_charging;
public byte[] untethered_case_charging;
public byte[] enhanced_settings_ui_uri;
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("manufacturer_name=")
+ .append(metadataToString(manufacturer_name))
+ .append("|model_name=")
+ .append(metadataToString(model_name))
+ .append("|software_version=")
+ .append(metadataToString(software_version))
+ .append("|hardware_version=")
+ .append(metadataToString(hardware_version))
+ .append("|companion_app=")
+ .append(metadataToString(companion_app))
+ .append("|main_icon=")
+ .append(metadataToString(main_icon))
+ .append("|is_untethered_headset=")
+ .append(metadataToString(is_untethered_headset))
+ .append("|untethered_left_icon=")
+ .append(metadataToString(untethered_left_icon))
+ .append("|untethered_right_icon=")
+ .append(metadataToString(untethered_right_icon))
+ .append("|untethered_case_icon=")
+ .append(metadataToString(untethered_case_icon))
+ .append("|untethered_left_battery=")
+ .append(metadataToString(untethered_left_battery))
+ .append("|untethered_right_battery=")
+ .append(metadataToString(untethered_right_battery))
+ .append("|untethered_case_battery=")
+ .append(metadataToString(untethered_case_battery))
+ .append("|untethered_left_charging=")
+ .append(metadataToString(untethered_left_charging))
+ .append("|untethered_right_charging=")
+ .append(metadataToString(untethered_right_charging))
+ .append("|untethered_case_charging=")
+ .append(metadataToString(untethered_case_charging))
+ .append("|enhanced_settings_ui_uri=")
+ .append(metadataToString(enhanced_settings_ui_uri));
+
+ return builder.toString();
+ }
+
+ private String metadataToString(byte[] metadata) {
+ if (metadata == null) {
+ return null;
+ }
+ return new String(metadata);
+ }
}
diff --git a/src/com/android/bluetooth/btservice/storage/DatabaseManager.java b/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
index a0e3c5a..f86adbd 100644
--- a/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
+++ b/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
@@ -39,6 +39,9 @@
import com.android.bluetooth.btservice.AdapterService;
import com.android.internal.annotations.VisibleForTesting;
+import com.google.common.collect.EvictingQueue;
+
+import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -52,8 +55,6 @@
* for Bluetooth persistent data.
*/
public class DatabaseManager {
- private static final boolean DBG = true;
- private static final boolean VERBOSE = true;
private static final String TAG = "BluetoothDatabase";
private AdapterService mAdapterService = null;
@@ -65,6 +66,8 @@
@VisibleForTesting
final Map<String, Metadata> mMetadataCache = new HashMap<>();
private final Semaphore mSemaphore = new Semaphore(1);
+ private static final int METADATA_CHANGED_LOG_MAX_SIZE = 20;
+ private final EvictingQueue<String> mMetadataChangedLog;
private static final int LOAD_DATABASE_TIMEOUT = 500; // milliseconds
private static final int MSG_LOAD_DATABASE = 0;
@@ -78,6 +81,7 @@
*/
public DatabaseManager(AdapterService service) {
mAdapterService = service;
+ mMetadataChangedLog = EvictingQueue.create(METADATA_CHANGED_LOG_MAX_SIZE);
}
class DatabaseHandler extends Handler {
@@ -218,21 +222,17 @@
}
String address = device.getAddress();
- if (VERBOSE) {
- Log.d(TAG, "setCustomMeta: " + address + ", key=" + key);
- }
if (!mMetadataCache.containsKey(address)) {
createMetadata(address);
}
Metadata data = mMetadataCache.get(address);
byte[] oldValue = data.getCustomizedMeta(key);
if (oldValue != null && Arrays.equals(oldValue, newValue)) {
- if (VERBOSE) {
- Log.d(TAG, "setCustomMeta: metadata not changed.");
- }
+ Log.v(TAG, "setCustomMeta: metadata not changed.");
return true;
}
logManufacturerInfo(device, key, newValue);
+ logMetadataChange(address, "setCustomMeta key=" + key);
data.setCustomizedMeta(key, newValue);
updateDatabase(data);
@@ -259,7 +259,7 @@
String address = device.getAddress();
if (!mMetadataCache.containsKey(address)) {
- Log.e(TAG, "getCustomMeta: device " + address + " is not in cache");
+ Log.d(TAG, "getCustomMeta: device " + address + " is not in cache");
return null;
}
@@ -302,10 +302,6 @@
}
String address = device.getAddress();
- if (VERBOSE) {
- Log.v(TAG, "setProfilePriority: " + address + ", profile=" + profile
- + ", priority = " + newPriority);
- }
if (!mMetadataCache.containsKey(address)) {
if (newPriority == BluetoothProfile.PRIORITY_UNDEFINED) {
return true;
@@ -315,11 +311,12 @@
Metadata data = mMetadataCache.get(address);
int oldPriority = data.getProfilePriority(profile);
if (oldPriority == newPriority) {
- if (VERBOSE) {
- Log.v(TAG, "setProfilePriority priority not changed.");
- }
+ Log.v(TAG, "setProfilePriority priority not changed.");
return true;
}
+ String profileStr = BluetoothProfile.getProfileName(profile);
+ logMetadataChange(address, profileStr + " priority changed: "
+ + ": " + oldPriority + " -> " + newPriority);
data.setProfilePriority(profile, newPriority);
updateDatabase(data);
@@ -355,16 +352,14 @@
String address = device.getAddress();
if (!mMetadataCache.containsKey(address)) {
- Log.e(TAG, "getProfilePriority: device " + address + " is not in cache");
+ Log.d(TAG, "getProfilePriority: device " + address + " is not in cache");
return BluetoothProfile.PRIORITY_UNDEFINED;
}
Metadata data = mMetadataCache.get(address);
int priority = data.getProfilePriority(profile);
- if (VERBOSE) {
- Log.v(TAG, "getProfilePriority: " + address + ", profile=" + profile
- + ", priority = " + priority);
- }
+ Log.v(TAG, "getProfilePriority: " + address + ", profile=" + profile
+ + ", priority = " + priority);
return priority;
}
}
@@ -402,6 +397,8 @@
if (oldValue == newValue) {
return;
}
+ logMetadataChange(address, "Supports optional codec changed: "
+ + oldValue + " -> " + newValue);
data.a2dpSupportsOptionalCodecs = newValue;
updateDatabase(data);
@@ -428,7 +425,7 @@
String address = device.getAddress();
if (!mMetadataCache.containsKey(address)) {
- Log.e(TAG, "getA2dpOptionalCodec: device " + address + " is not in cache");
+ Log.d(TAG, "getA2dpOptionalCodec: device " + address + " is not in cache");
return BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN;
}
@@ -470,6 +467,8 @@
if (oldValue == newValue) {
return;
}
+ logMetadataChange(address, "Enable optional codec changed: "
+ + oldValue + " -> " + newValue);
data.a2dpOptionalCodecsEnabled = newValue;
updateDatabase(data);
@@ -496,7 +495,7 @@
String address = device.getAddress();
if (!mMetadataCache.containsKey(address)) {
- Log.e(TAG, "getA2dpOptionalCodecEnabled: device " + address + " is not in cache");
+ Log.d(TAG, "getA2dpOptionalCodecEnabled: device " + address + " is not in cache");
return BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN;
}
@@ -525,10 +524,7 @@
* @param database the Bluetooth storage {@link MetadataDatabase}
*/
public void start(MetadataDatabase database) {
- if (DBG) {
- Log.d(TAG, "start()");
- }
-
+ Log.d(TAG, "start()");
if (mAdapterService == null) {
Log.e(TAG, "stat failed, mAdapterService is null.");
return;
@@ -582,12 +578,10 @@
}
void createMetadata(String address) {
- if (VERBOSE) {
- Log.v(TAG, "createMetadata " + address);
- }
Metadata data = new Metadata(address);
mMetadataCache.put(address, data);
updateDatabase(data);
+ logMetadataChange(address, "Metadata created");
}
@VisibleForTesting
@@ -623,14 +617,10 @@
mMigratedFromSettingsGlobal = true;
for (Metadata data : list) {
String address = data.getAddress();
- if (VERBOSE) {
- Log.v(TAG, "cacheMetadata: found device " + address);
- }
+ Log.v(TAG, "cacheMetadata: found device " + address);
mMetadataCache.put(address, data);
}
- if (VERBOSE) {
- Log.v(TAG, "cacheMetadata: Database is ready");
- }
+ Log.i(TAG, "cacheMetadata: Database is ready");
}
}
@@ -726,9 +716,7 @@
}
private void loadDatabase() {
- if (DBG) {
- Log.d(TAG, "Load Database");
- }
+ Log.d(TAG, "Load Database");
Message message = mHandler.obtainMessage(MSG_LOAD_DATABASE);
mHandler.sendMessage(message);
try {
@@ -744,20 +732,19 @@
Log.e(TAG, "updateDatabase: address is null");
return;
}
- if (DBG) {
- Log.d(TAG, "updateDatabase " + data.getAddress());
- }
+ Log.d(TAG, "updateDatabase " + data.getAddress());
Message message = mHandler.obtainMessage(MSG_UPDATE_DATABASE);
message.obj = data;
mHandler.sendMessage(message);
}
private void deleteDatabase(Metadata data) {
- if (data.getAddress() == null) {
+ String address = data.getAddress();
+ if (address == null) {
Log.e(TAG, "deleteDatabase: address is null");
return;
}
- Log.d(TAG, "deleteDatabase: " + data.getAddress());
+ logMetadataChange(address, "Metadata deleted");
Message message = mHandler.obtainMessage(MSG_DELETE_DATABASE);
message.obj = data.getAddress();
mHandler.sendMessage(message);
@@ -793,4 +780,31 @@
BluetoothProtoEnums.DEVICE_INFO_EXTERNAL, callingApp, manufacturerName, modelName,
hardwareVersion, softwareVersion);
}
+
+ private void logMetadataChange(String address, String log) {
+ String time = Utils.getLocalTimeString();
+ String uidPid = Utils.getUidPidString();
+ mMetadataChangedLog.add(time + " (" + uidPid + ") " + address + " " + log);
+ }
+
+ /**
+ * Dump database info to a PrintWriter
+ *
+ * @param writer the PrintWriter to write log
+ */
+ public void dump(PrintWriter writer) {
+ writer.println("\nBluetoothDatabase:");
+ writer.println(" Metadata Changes:");
+ for (String log : mMetadataChangedLog) {
+ writer.println(" " + log);
+ }
+ writer.println("\nMetadata:");
+ for (HashMap.Entry<String, Metadata> entry : mMetadataCache.entrySet()) {
+ if (entry.getKey().equals(LOCAL_STORAGE)) {
+ // No need to dump local storage
+ continue;
+ }
+ writer.println(" " + entry.getValue());
+ }
+ }
}
diff --git a/src/com/android/bluetooth/btservice/storage/Metadata.java b/src/com/android/bluetooth/btservice/storage/Metadata.java
index b39333f..9151ede 100644
--- a/src/com/android/bluetooth/btservice/storage/Metadata.java
+++ b/src/com/android/bluetooth/btservice/storage/Metadata.java
@@ -301,4 +301,20 @@
}
return list;
}
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(address)
+ .append(" {profile priority(")
+ .append(profilePriorities)
+ .append("), optional codec(support=")
+ .append(a2dpSupportsOptionalCodecs)
+ .append("|enabled=")
+ .append(a2dpOptionalCodecsEnabled)
+ .append("), custom metadata(")
+ .append(publicMetadata)
+ .append(")}");
+
+ return builder.toString();
+ }
}
diff --git a/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java b/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java
index f4ea719..d87fbde 100644
--- a/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java
+++ b/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java
@@ -50,4 +50,22 @@
hearing_aid_priority = BluetoothProfile.PRIORITY_UNDEFINED;
map_client_priority = BluetoothProfile.PRIORITY_UNDEFINED;
}
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("A2DP=").append(a2dp_priority)
+ .append("|A2DP_SINK=").append(a2dp_sink_priority)
+ .append("|HEADSET=").append(hfp_priority)
+ .append("|HEADSET_CLIENT=").append(hfp_client_priority)
+ .append("|HID_HOST=").append(hid_host_priority)
+ .append("|PAN=").append(pan_priority)
+ .append("|PBAP=").append(pbap_priority)
+ .append("|PBAP_CLIENT=").append(pbap_client_priority)
+ .append("|MAP=").append(map_priority)
+ .append("|MAP_CLIENT=").append(map_client_priority)
+ .append("|SAP=").append(sap_priority)
+ .append("|HEARING_AID=").append(hearing_aid_priority);
+
+ return builder.toString();
+ }
}
diff --git a/src/com/android/bluetooth/hearingaid/HearingAidService.java b/src/com/android/bluetooth/hearingaid/HearingAidService.java
index f29d9b9..3647a65 100644
--- a/src/com/android/bluetooth/hearingaid/HearingAidService.java
+++ b/src/com/android/bluetooth/hearingaid/HearingAidService.java
@@ -33,7 +33,6 @@
import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
@@ -221,7 +220,13 @@
sHearingAidService = instance;
}
- boolean connect(BluetoothDevice device) {
+ /**
+ * Connects the hearing aid profile to the passed in device
+ *
+ * @param device is the device with which we will connect the hearing aid profile
+ * @return true if hearing aid profile successfully connected, false otherwise
+ */
+ public boolean connect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
if (DBG) {
Log.d(TAG, "connect(): " + device);
@@ -281,7 +286,13 @@
return true;
}
- boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects hearing aid profile for the passed in device
+ *
+ * @param device is the device with which we want to disconnected the hearing aid profile
+ * @return true if hearing aid profile successfully disconnected, false otherwise
+ */
+ public boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
if (DBG) {
Log.d(TAG, "disconnect(): " + device);
@@ -505,15 +516,6 @@
Long deviceHiSyncId = mDeviceHiSyncIdMap.getOrDefault(device,
BluetoothHearingAid.HI_SYNC_ID_INVALID);
if (deviceHiSyncId != mActiveDeviceHiSyncId) {
- // Give an early notification to A2DP that active device is being switched
- // to Hearing Aids before the Audio Service.
- final A2dpService a2dpService = mFactory.getA2dpService();
- if (a2dpService != null) {
- if (DBG) {
- Log.d(TAG, "earlyNotifyHearingAidActive for " + device);
- }
- a2dpService.earlyNotifyHearingAidActive();
- }
mActiveDeviceHiSyncId = deviceHiSyncId;
reportActiveDevice(device);
}
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index 1dbafd0..8f9adae 100644
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -729,7 +729,13 @@
return true;
}
- boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects hfp from the passed in device
+ *
+ * @param device is the device with which we will disconnect hfp
+ * @return true if hfp is disconnected, false if the device is not connected
+ */
+ public boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
Log.i(TAG, "disconnect: device=" + device + ", " + Utils.getUidPidString());
synchronized (mStateMachines) {
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientService.java b/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
index 474d332..e7412fe 100644
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
@@ -491,7 +491,13 @@
return true;
}
- boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects hfp client for the remote bluetooth device
+ *
+ * @param device is the device with which we are attempting to disconnect the profile
+ * @return true if hfp client profile successfully disconnected, false otherwise
+ */
+ public boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
HeadsetClientStateMachine sm = getStateMachine(device);
if (sm == null) {
diff --git a/src/com/android/bluetooth/hid/HidDeviceService.java b/src/com/android/bluetooth/hid/HidDeviceService.java
index eb0de8e..b2d7e41 100644
--- a/src/com/android/bluetooth/hid/HidDeviceService.java
+++ b/src/com/android/bluetooth/hid/HidDeviceService.java
@@ -592,7 +592,13 @@
&& mHidDeviceNativeInterface.unplug();
}
- synchronized boolean connect(BluetoothDevice device) {
+ /**
+ * Connects the Hid device profile for the remote bluetooth device
+ *
+ * @param device is the device with which we would like to connect the hid device profile
+ * @return true if the connection is successful, false otherwise
+ */
+ public synchronized boolean connect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
if (DBG) {
Log.d(TAG, "connect(): device=" + device);
@@ -601,7 +607,13 @@
return checkCallingUid() && mHidDeviceNativeInterface.connect(device);
}
- synchronized boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects the hid device profile for the remote bluetooth device
+ *
+ * @param device is the device with which we would like to disconnect the hid device profile
+ * @return true if the disconnection is successful, false otherwise
+ */
+ public synchronized boolean disconnect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
if (DBG) {
Log.d(TAG, "disconnect(): device=" + device);
@@ -701,7 +713,15 @@
sHidDeviceService = instance;
}
- int getConnectionState(BluetoothDevice device) {
+ /**
+ * Gets the connections state for the hid device profile for the passed in device
+ *
+ * @param device is the device whose conenction state we want to verify
+ * @return current connection state, one of {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_CONNECTED}, or
+ * {@link BluetoothProfile#STATE_DISCONNECTING}
+ */
+ public int getConnectionState(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (mHidDevice != null && mHidDevice.equals(device)) {
return mHidDeviceState;
diff --git a/src/com/android/bluetooth/hid/HidHostService.java b/src/com/android/bluetooth/hid/HidHostService.java
index c378f8e..2e0019c 100644
--- a/src/com/android/bluetooth/hid/HidHostService.java
+++ b/src/com/android/bluetooth/hid/HidHostService.java
@@ -468,7 +468,14 @@
;
//APIs
- boolean connect(BluetoothDevice device) {
+
+ /**
+ * Connects the hid host profile for the passed in device
+ *
+ * @param device is the device with which to connect the hid host profile
+ * @return true if connection is successful, false otherwise
+ */
+ public boolean connect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "connect: " + device.getAddress());
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (getConnectionState(device) != BluetoothHidHost.STATE_DISCONNECTED) {
@@ -485,7 +492,13 @@
return true;
}
- boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects the hid host profile from the passed in device
+ *
+ * @param device is the device with which to disconnect the hid host profile
+ * @return true
+ */
+ public boolean disconnect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "disconnect: " + device.getAddress());
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT, device);
diff --git a/src/com/android/bluetooth/map/BluetoothMapService.java b/src/com/android/bluetooth/map/BluetoothMapService.java
index 71942f0..1d651ba 100644
--- a/src/com/android/bluetooth/map/BluetoothMapService.java
+++ b/src/com/android/bluetooth/map/BluetoothMapService.java
@@ -509,7 +509,12 @@
}
}
- void disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects MAP from the supplied device
+ *
+ * @param device is the device on which we want to disconnect MAP
+ */
+ public void disconnect(BluetoothDevice device) {
mSessionStatusHandler.sendMessage(
mSessionStatusHandler.obtainMessage(DISCONNECT_MAP, 0, 0, device));
}
@@ -563,7 +568,14 @@
return deviceList;
}
- int getConnectionState(BluetoothDevice device) {
+ /**
+ * Gets the connection state of MAP with the passed in device.
+ *
+ * @param device is the device whose connection state we are querying
+ * @return {@link BluetoothProfile#STATE_CONNECTED} if MAP is connected to this device,
+ * {@link BluetoothProfile#STATE_DISCONNECTED} otherwise
+ */
+ public int getConnectionState(BluetoothDevice device) {
synchronized (this) {
if (getState() == BluetoothMap.STATE_CONNECTED && getRemoteDevice().equals(device)) {
return BluetoothProfile.STATE_CONNECTED;
@@ -1197,18 +1209,6 @@
}
@Override
- public boolean connect(BluetoothDevice device) {
- if (VERBOSE) {
- Log.v(TAG, "connect()");
- }
- BluetoothMapService service = getService();
- if (service == null) {
- return false;
- }
- return false;
- }
-
- @Override
public boolean disconnect(BluetoothDevice device) {
if (VERBOSE) {
Log.v(TAG, "disconnect()");
diff --git a/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivity.java b/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivity.java
index 0253e24..8a4d149 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivity.java
@@ -32,6 +32,7 @@
package com.android.bluetooth.opp;
+import android.bluetooth.AlertActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
@@ -40,8 +41,6 @@
import android.widget.Toast;
import com.android.bluetooth.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
/**
* This class is designed to show BT enable confirmation dialog;
@@ -57,14 +56,12 @@
// Set up the "dialog"
mOppManager = BluetoothOppManager.getInstance(this);
mOppManager.mSendingFlag = false;
- final AlertController.AlertParams p = mAlertParams;
- p.mIconAttrId = android.R.attr.alertDialogIcon;
- p.mTitle = getString(R.string.bt_enable_title);
- p.mView = createView();
- p.mPositiveButtonText = getString(R.string.bt_enable_ok);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(R.string.bt_enable_cancel);
- p.mNegativeButtonListener = this;
+
+ mAlertBuilder.setIconAttribute(android.R.attr.alertDialogIcon);
+ mAlertBuilder.setTitle(getString(R.string.bt_enable_title));
+ mAlertBuilder.setView(createView());
+ mAlertBuilder.setPositiveButton(R.string.bt_enable_ok, this);
+ mAlertBuilder.setNegativeButton(R.string.bt_enable_cancel, this);
setupAlert();
}
diff --git a/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java b/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java
index 4a9a710..cde530c 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivity.java
@@ -32,6 +32,7 @@
package com.android.bluetooth.opp;
+import android.bluetooth.AlertActivity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -46,8 +47,6 @@
import android.widget.TextView;
import com.android.bluetooth.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
/**
* This class is designed to show BT enabling progress.
@@ -80,10 +79,8 @@
registerReceiver(mBluetoothReceiver, filter);
mRegistered = true;
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mTitle = getString(R.string.enabling_progress_title);
- p.mView = createView();
+ mAlertBuilder.setTitle(R.string.enabling_progress_title);
+ mAlertBuilder.setView(createView());
setupAlert();
// Add timeout for enabling progress
diff --git a/src/com/android/bluetooth/opp/BluetoothOppBtErrorActivity.java b/src/com/android/bluetooth/opp/BluetoothOppBtErrorActivity.java
index 22a8d82..f78e32d 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppBtErrorActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppBtErrorActivity.java
@@ -32,6 +32,7 @@
package com.android.bluetooth.opp;
+import android.bluetooth.AlertActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
@@ -39,8 +40,6 @@
import android.widget.TextView;
import com.android.bluetooth.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
/**
* This class is designed to show BT error messages;
@@ -48,30 +47,26 @@
public class BluetoothOppBtErrorActivity extends AlertActivity
implements DialogInterface.OnClickListener {
- private String mErrorContent;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
- String mErrorTitle = intent.getStringExtra("title");
- mErrorContent = intent.getStringExtra("content");
+ String errorTitle = intent.getStringExtra("title");
+ String errorContent = intent.getStringExtra("content");
// Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconAttrId = android.R.attr.alertDialogIcon;
- p.mTitle = mErrorTitle;
- p.mView = createView();
- p.mPositiveButtonText = getString(R.string.bt_error_btn_ok);
- p.mPositiveButtonListener = this;
+ mAlertBuilder.setIconAttribute(android.R.attr.alertDialogIcon);
+ mAlertBuilder.setTitle(errorTitle);
+ mAlertBuilder.setView(createView(errorContent));
+ mAlertBuilder.setPositiveButton(R.string.bt_error_btn_ok, this);
setupAlert();
}
- private View createView() {
+ private View createView(String errorContent) {
View view = getLayoutInflater().inflate(R.layout.confirm_dialog, null);
TextView contentView = (TextView) view.findViewById(R.id.content);
- contentView.setText(mErrorContent);
+ contentView.setText(errorContent);
return view;
}
diff --git a/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java b/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
index 1b5ffe1..8a887ee 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
@@ -32,6 +32,7 @@
package com.android.bluetooth.opp;
+import android.bluetooth.AlertActivity;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
@@ -50,8 +51,6 @@
import android.widget.Toast;
import com.android.bluetooth.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
/**
* This class is designed to ask user to confirm if accept incoming file;
@@ -106,14 +105,11 @@
return;
}
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mTitle = getString(R.string.incoming_file_confirm_content);
- p.mView = createView();
- p.mPositiveButtonText = getString(R.string.incoming_file_confirm_ok);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(R.string.incoming_file_confirm_cancel);
- p.mNegativeButtonListener = this;
+ mAlertBuilder.setTitle(getString(R.string.incoming_file_confirm_content));
+ mAlertBuilder.setView(createView());
+ mAlertBuilder.setPositiveButton(R.string.incoming_file_confirm_ok, this);
+ mAlertBuilder.setNegativeButton(R.string.incoming_file_confirm_cancel, this);
+
setupAlert();
if (V) {
Log.v(TAG, "mTimeout: " + mTimeout);
@@ -207,11 +203,14 @@
private void onTimeout() {
mTimeout = true;
- mAlert.setTitle(
- getString(R.string.incoming_file_confirm_timeout_content, mTransInfo.mDeviceName));
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
- mAlert.getButton(DialogInterface.BUTTON_POSITIVE)
- .setText(getString(R.string.incoming_file_confirm_timeout_ok));
+
+ changeTitle(getString(
+ R.string.incoming_file_confirm_timeout_content,
+ mTransInfo.mDeviceName));
+ changeButtonVisibility(DialogInterface.BUTTON_NEGATIVE, View.GONE);
+ changeButtonText(
+ DialogInterface.BUTTON_POSITIVE,
+ getString(R.string.incoming_file_confirm_timeout_ok));
mTimeoutHandler.sendMessageDelayed(mTimeoutHandler.obtainMessage(DISMISS_TIMEOUT_DIALOG),
DISMISS_TIMEOUT_DIALOG_VALUE);
diff --git a/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java b/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java
index a7c14ac..da3d100 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java
@@ -33,6 +33,7 @@
package com.android.bluetooth.opp;
import android.app.NotificationManager;
+import android.bluetooth.AlertActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.DialogInterface;
@@ -49,8 +50,6 @@
import android.widget.Toast;
import com.android.bluetooth.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
/**
* Handle all transfer related dialogs: -Ongoing transfer -Receiving one file
@@ -79,8 +78,6 @@
private TextView mPercentView;
- private AlertController.AlertParams mPara;
-
private View mView = null;
private TextView mLine1View, mLine2View, mLine3View, mLine5View;
@@ -216,33 +213,23 @@
}
private void setUpDialog() {
- // final AlertController.AlertParams p = mAlertParams;
- mPara = mAlertParams;
- mPara.mTitle = getString(R.string.download_title);
-
+ mAlertBuilder.setTitle(getString(R.string.download_title));
if ((mWhichDialog == DIALOG_RECEIVE_ONGOING) || (mWhichDialog == DIALOG_SEND_ONGOING)) {
- mPara.mPositiveButtonText = getString(R.string.download_ok);
- mPara.mPositiveButtonListener = this;
- mPara.mNegativeButtonText = getString(R.string.download_cancel);
- mPara.mNegativeButtonListener = this;
+ mAlertBuilder.setPositiveButton(R.string.download_ok, this);
+ mAlertBuilder.setNegativeButton(R.string.download_cancel, this);
} else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
- mPara.mPositiveButtonText = getString(R.string.download_succ_ok);
- mPara.mPositiveButtonListener = this;
+ mAlertBuilder.setPositiveButton(R.string.download_succ_ok, this);
} else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_FAIL) {
- mPara.mIconAttrId = android.R.attr.alertDialogIcon;
- mPara.mPositiveButtonText = getString(R.string.download_fail_ok);
- mPara.mPositiveButtonListener = this;
+ mAlertBuilder.setIconAttribute(android.R.attr.alertDialogIcon);
+ mAlertBuilder.setPositiveButton(R.string.download_fail_ok, this);
} else if (mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
- mPara.mPositiveButtonText = getString(R.string.upload_succ_ok);
- mPara.mPositiveButtonListener = this;
+ mAlertBuilder.setPositiveButton(R.string.upload_succ_ok, this);
} else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
- mPara.mIconAttrId = android.R.attr.alertDialogIcon;
- mPara.mPositiveButtonText = getString(R.string.upload_fail_ok);
- mPara.mPositiveButtonListener = this;
- mPara.mNegativeButtonText = getString(R.string.upload_fail_cancel);
- mPara.mNegativeButtonListener = this;
+ mAlertBuilder.setIconAttribute(android.R.attr.alertDialogIcon);
+ mAlertBuilder.setPositiveButton(R.string.upload_fail_ok, this);
+ mAlertBuilder.setNegativeButton(R.string.upload_fail_cancel, this);
}
- mPara.mView = createView();
+ mAlertBuilder.setView(createView());
setupAlert();
}
@@ -471,24 +458,29 @@
*/
private void updateButton() {
if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS) {
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
- mAlert.getButton(DialogInterface.BUTTON_POSITIVE)
- .setText(getString(R.string.download_succ_ok));
+ changeButtonVisibility(DialogInterface.BUTTON_NEGATIVE, View.GONE);
+ changeButtonText(
+ DialogInterface.BUTTON_POSITIVE,
+ getString(R.string.download_succ_ok));
} else if (mWhichDialog == DIALOG_RECEIVE_COMPLETE_FAIL) {
- mAlert.setIcon(mAlert.getIconAttributeResId(android.R.attr.alertDialogIcon));
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
- mAlert.getButton(DialogInterface.BUTTON_POSITIVE)
- .setText(getString(R.string.download_fail_ok));
+ changeIconAttribute(android.R.attr.alertDialogIcon);
+ changeButtonVisibility(DialogInterface.BUTTON_NEGATIVE, View.GONE);
+ changeButtonText(
+ DialogInterface.BUTTON_POSITIVE,
+ getString(R.string.download_fail_ok));
} else if (mWhichDialog == DIALOG_SEND_COMPLETE_SUCCESS) {
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
- mAlert.getButton(DialogInterface.BUTTON_POSITIVE)
- .setText(getString(R.string.upload_succ_ok));
+ changeButtonVisibility(DialogInterface.BUTTON_NEGATIVE, View.GONE);
+ changeButtonText(
+ DialogInterface.BUTTON_POSITIVE,
+ getString(R.string.upload_succ_ok));
} else if (mWhichDialog == DIALOG_SEND_COMPLETE_FAIL) {
- mAlert.setIcon(mAlert.getIconAttributeResId(android.R.attr.alertDialogIcon));
- mAlert.getButton(DialogInterface.BUTTON_POSITIVE)
- .setText(getString(R.string.upload_fail_ok));
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE)
- .setText(getString(R.string.upload_fail_cancel));
+ changeIconAttribute(android.R.attr.alertDialogIcon);
+ changeButtonText(
+ DialogInterface.BUTTON_NEGATIVE,
+ getString(R.string.upload_fail_cancel));
+ changeButtonText(
+ DialogInterface.BUTTON_POSITIVE,
+ getString(R.string.upload_fail_ok));
}
}
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java b/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java
index 5468a76..3da71e0 100644
--- a/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java
+++ b/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java
@@ -32,6 +32,7 @@
package com.android.bluetooth.pbap;
+import android.bluetooth.AlertActivity;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -47,13 +48,10 @@
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
-import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.android.bluetooth.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
/**
* PbapActivity shows two dialogues: One for accepting incoming pbap request and
@@ -83,8 +81,6 @@
private int mCurrentDialog;
- private Button mOkButton;
-
private boolean mTimeout = false;
private static final int DISMISS_TIMEOUT_DIALOG = 0;
@@ -122,18 +118,14 @@
}
private void showPbapDialog(int id) {
- final AlertController.AlertParams p = mAlertParams;
switch (id) {
case DIALOG_YES_NO_AUTH:
- p.mTitle = getString(R.string.pbap_session_key_dialog_header);
- p.mView = createView(DIALOG_YES_NO_AUTH);
- p.mPositiveButtonText = getString(android.R.string.ok);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(android.R.string.cancel);
- p.mNegativeButtonListener = this;
+ mAlertBuilder.setTitle(getString(R.string.pbap_session_key_dialog_header));
+ mAlertBuilder.setView(createView(DIALOG_YES_NO_AUTH));
+ mAlertBuilder.setPositiveButton(android.R.string.ok, this);
+ mAlertBuilder.setNegativeButton(android.R.string.cancel, this);
setupAlert();
- mOkButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
- mOkButton.setEnabled(false);
+ changeButtonEnabled(DialogInterface.BUTTON_POSITIVE, false);
break;
default:
break;
@@ -223,8 +215,8 @@
mKeyView.setVisibility(View.GONE);
mKeyView.clearFocus();
mKeyView.removeTextChangedListener(this);
- mOkButton.setEnabled(true);
- mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
+ changeButtonEnabled(DialogInterface.BUTTON_POSITIVE, true);
+ changeButtonVisibility(DialogInterface.BUTTON_NEGATIVE, View.GONE);
}
mTimeoutHandler.sendMessageDelayed(mTimeoutHandler.obtainMessage(DISMISS_TIMEOUT_DIALOG),
@@ -271,7 +263,7 @@
@Override
public void afterTextChanged(android.text.Editable s) {
if (s.length() > 0) {
- mOkButton.setEnabled(true);
+ changeButtonEnabled(DialogInterface.BUTTON_POSITIVE, true);
}
}
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
index e7dba2a..4ed499e 100644
--- a/src/com/android/bluetooth/pbap/BluetoothPbapService.java
+++ b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
@@ -417,7 +417,15 @@
}
}
- int getConnectionState(BluetoothDevice device) {
+ /**
+ * Get the current connection state of PBAP with the passed in device
+ *
+ * @param device is the device whose connection state to PBAP we are trying to get
+ * @return current connection state, one of {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_CONNECTED}, or
+ * {@link BluetoothProfile#STATE_DISCONNECTING}
+ */
+ public int getConnectionState(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (mPbapStateMachineMap == null) {
return BluetoothProfile.STATE_DISCONNECTED;
diff --git a/src/com/android/bluetooth/pbapclient/PbapClientService.java b/src/com/android/bluetooth/pbapclient/PbapClientService.java
index f150cdd..16b02e1 100644
--- a/src/com/android/bluetooth/pbapclient/PbapClientService.java
+++ b/src/com/android/bluetooth/pbapclient/PbapClientService.java
@@ -317,7 +317,13 @@
}
}
- boolean disconnect(BluetoothDevice device) {
+ /**
+ * Disconnects the pbap client profile from the passed in device
+ *
+ * @param device is the device with which we will disconnect the pbap client profile
+ * @return true if we disconnected the pbap client profile, false otherwise
+ */
+ public boolean disconnect(BluetoothDevice device) {
if (device == null) {
throw new IllegalArgumentException("Null device");
}
diff --git a/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java b/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java
index 78f4ad0..4492a45 100644
--- a/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java
@@ -39,9 +39,7 @@
import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
-import com.android.bluetooth.avrcp.AvrcpTargetService;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import org.junit.After;
@@ -78,8 +76,6 @@
@Mock private AdapterService mAdapterService;
@Mock private A2dpNativeInterface mA2dpNativeInterface;
@Mock private DatabaseManager mDatabaseManager;
- @Mock private AvrcpTargetService mAvrcpTargetService;
- @Mock private ServiceFactory mFactory;
@Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
@@ -98,13 +94,11 @@
TestUtils.setAdapterService(mAdapterService);
doReturn(MAX_CONNECTED_AUDIO_DEVICES).when(mAdapterService).getMaxConnectedAudioDevices();
doReturn(false).when(mAdapterService).isQuietModeEnabled();
- doReturn(mAvrcpTargetService).when(mFactory).getAvrcpTargetService();
mAdapter = BluetoothAdapter.getDefaultAdapter();
startService();
mA2dpService.mA2dpNativeInterface = mA2dpNativeInterface;
- mA2dpService.mFactory = mFactory;
// Override the timeout value to speed up the test
A2dpStateMachine.sConnectTimeoutMs = TIMEOUT_MS; // 1s
@@ -252,8 +246,6 @@
});
// Verify that setActiveDevice(null) was called during shutdown
verify(mA2dpNativeInterface).setActiveDevice(null);
- // Verify that storeVolumeForDevice(mTestDevice) was called during shutdown
- verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice);
// Try to restart the service. Note: must be done on the main thread.
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
@@ -796,13 +788,11 @@
Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice());
Assert.assertTrue(mA2dpService.setSilenceMode(mTestDevice, true));
verify(mA2dpNativeInterface).setSilenceDevice(mTestDevice, true);
- verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice);
Assert.assertNull(mA2dpService.getActiveDevice());
// Test whether active device been resumeed after disable silence mode.
Assert.assertTrue(mA2dpService.setSilenceMode(mTestDevice, false));
verify(mA2dpNativeInterface).setSilenceDevice(mTestDevice, false);
- verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice);
Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice());
// Test that active device should not be changed when silence a non-active device
@@ -810,13 +800,11 @@
Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice());
Assert.assertTrue(mA2dpService.setSilenceMode(otherDevice, true));
verify(mA2dpNativeInterface).setSilenceDevice(otherDevice, true);
- verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice);
Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice());
// Test that active device should not be changed when another device exits silence mode
Assert.assertTrue(mA2dpService.setSilenceMode(otherDevice, false));
verify(mA2dpNativeInterface).setSilenceDevice(otherDevice, false);
- verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice);
Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice());
}
@@ -906,28 +894,6 @@
verifySupportTime, verifyNotSupportTime, verifyEnabledTime);
}
- /**
- * Test that volume level of previous active device will be stored after set active device.
- */
- @Test
- public void testStoreVolumeAfterSetActiveDevice() {
- BluetoothDevice otherDevice = mAdapter.getRemoteDevice("05:04:03:02:01:00");
- connectDevice(otherDevice);
- connectDevice(mTestDevice);
- doReturn(true).when(mA2dpNativeInterface).setActiveDevice(any(BluetoothDevice.class));
- doReturn(true).when(mA2dpNativeInterface).setActiveDevice(null);
- Assert.assertTrue(mA2dpService.setActiveDevice(mTestDevice));
-
- // Test volume stored for previous active device an adjust for current active device
- Assert.assertTrue(mA2dpService.setActiveDevice(otherDevice));
- verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice);
- verify(mAvrcpTargetService).getRememberedVolumeForDevice(otherDevice);
-
- // Test volume store for previous active device when set active device to null
- Assert.assertTrue(mA2dpService.setActiveDevice(null));
- verify(mAvrcpTargetService).storeVolumeForDevice(otherDevice);
- }
-
private void connectDevice(BluetoothDevice device) {
connectDeviceWithCodecStatus(device, null);
}
diff --git a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
index f8ab6bb..0ca9c2a 100644
--- a/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java
@@ -151,6 +151,10 @@
IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class));
Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_DISCONNECTED);
verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine));
+ MediaControllerCompat.TransportControls transportControls =
+ BluetoothMediaBrowserService.getTransportControls();
+ Assert.assertEquals(PlaybackStateCompat.STATE_ERROR,
+ BluetoothMediaBrowserService.getPlaybackState());
}
/**
@@ -159,6 +163,11 @@
@Test
public void testControlOnly() {
int numBroadcastsSent = setUpConnectedState(true, false);
+ MediaControllerCompat.TransportControls transportControls =
+ BluetoothMediaBrowserService.getTransportControls();
+ Assert.assertNotNull(transportControls);
+ Assert.assertEquals(PlaybackStateCompat.STATE_NONE,
+ BluetoothMediaBrowserService.getPlaybackState());
StackEvent event =
StackEvent.connectionStateChanged(false, false);
mAvrcpStateMachine.disconnect();
@@ -176,6 +185,8 @@
IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class));
Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_DISCONNECTED);
verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine));
+ Assert.assertEquals(PlaybackStateCompat.STATE_ERROR,
+ BluetoothMediaBrowserService.getPlaybackState());
}
/**
@@ -186,6 +197,8 @@
Assert.assertEquals(0, mAvrcpControllerService.sBrowseTree.mRootNode.getChildrenCount());
int numBroadcastsSent = setUpConnectedState(false, true);
Assert.assertEquals(1, mAvrcpControllerService.sBrowseTree.mRootNode.getChildrenCount());
+ Assert.assertEquals(PlaybackStateCompat.STATE_NONE,
+ BluetoothMediaBrowserService.getPlaybackState());
StackEvent event =
StackEvent.connectionStateChanged(false, false);
mAvrcpStateMachine.disconnect();
@@ -203,6 +216,10 @@
IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class));
Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_DISCONNECTED);
verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine));
+ MediaControllerCompat.TransportControls transportControls =
+ BluetoothMediaBrowserService.getTransportControls();
+ Assert.assertEquals(PlaybackStateCompat.STATE_ERROR,
+ BluetoothMediaBrowserService.getPlaybackState());
}
/**