diff options
3 files changed, 104 insertions, 0 deletions
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 66e89237ac6d..a1ef831523b1 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1186,4 +1186,7 @@ <!-- Name of the this device. [CHAR LIMIT=30] --> <string name="media_transfer_this_device_name">This device</string> + + <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] --> + <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off & back on</string> </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 98db7c8fb59c..2507a3486f2b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -24,6 +24,9 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.SharedPreferences; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.ParcelUuid; import android.os.SystemClock; import android.text.TextUtils; @@ -55,6 +58,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> // Some Hearing Aids (especially the 2nd device) needs more time to do service discovery private static final long MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT = 15000; private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000; + private static final long MAX_MEDIA_PROFILE_CONNECT_DELAY = 60000; private final Context mContext; private final BluetoothAdapter mLocalAdapter; @@ -90,9 +94,35 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private boolean mIsActiveDeviceA2dp = false; private boolean mIsActiveDeviceHeadset = false; private boolean mIsActiveDeviceHearingAid = false; + // Media profile connect state + private boolean mIsA2dpProfileConnectedFail = false; + private boolean mIsHeadsetProfileConnectedFail = false; + private boolean mIsHearingAidProfileConnectedFail = false; // Group second device for Hearing Aid private CachedBluetoothDevice mSubDevice; + private final Handler mHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case BluetoothProfile.A2DP: + mIsA2dpProfileConnectedFail = true; + break; + case BluetoothProfile.HEADSET: + mIsHeadsetProfileConnectedFail = true; + break; + case BluetoothProfile.HEARING_AID: + mIsHearingAidProfileConnectedFail = true; + break; + default: + Log.w(TAG, "handleMessage(): unknown message : " + msg.what); + break; + } + Log.w(TAG, "Connect to profile : " + msg.what + " timeout, show error message !"); + refresh(); + } + }; + CachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager, BluetoothDevice device) { mContext = context; @@ -133,6 +163,35 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } synchronized (mProfileLock) { + if (profile instanceof A2dpProfile || profile instanceof HeadsetProfile + || profile instanceof HearingAidProfile) { + setProfileConnectedStatus(profile.getProfileId(), false); + switch (newProfileState) { + case BluetoothProfile.STATE_CONNECTED: + mHandler.removeMessages(profile.getProfileId()); + break; + case BluetoothProfile.STATE_CONNECTING: + mHandler.sendEmptyMessageDelayed(profile.getProfileId(), + MAX_MEDIA_PROFILE_CONNECT_DELAY); + break; + case BluetoothProfile.STATE_DISCONNECTING: + if (mHandler.hasMessages(profile.getProfileId())) { + mHandler.removeMessages(profile.getProfileId()); + } + break; + case BluetoothProfile.STATE_DISCONNECTED: + if (mHandler.hasMessages(profile.getProfileId())) { + mHandler.removeMessages(profile.getProfileId()); + setProfileConnectedStatus(profile.getProfileId(), true); + } + break; + default: + Log.w(TAG, "onProfileStateChanged(): unknown profile state : " + + newProfileState); + break; + } + } + if (newProfileState == BluetoothProfile.STATE_CONNECTED) { if (profile instanceof MapProfile) { profile.setPreferred(mDevice, true); @@ -162,6 +221,24 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> fetchActiveDevices(); } + @VisibleForTesting + void setProfileConnectedStatus(int profileId, boolean isFailed) { + switch (profileId) { + case BluetoothProfile.A2DP: + mIsA2dpProfileConnectedFail = isFailed; + break; + case BluetoothProfile.HEADSET: + mIsHeadsetProfileConnectedFail = isFailed; + break; + case BluetoothProfile.HEARING_AID: + mIsHearingAidProfileConnectedFail = isFailed; + break; + default: + Log.w(TAG, "setProfileConnectedStatus(): unknown profile id : " + profileId); + break; + } + } + public void disconnect() { synchronized (mProfileLock) { for (LocalBluetoothProfile profile : mProfiles) { @@ -844,6 +921,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> int leftBattery = -1; int rightBattery = -1; + if (isProfileConnectedFail() && isConnected()) { + return mContext.getString(R.string.profile_connect_timeout_subtext); + } + synchronized (mProfileLock) { for (LocalBluetoothProfile profile : getProfiles()) { int connectionStatus = getProfileConnectionState(profile); @@ -943,6 +1024,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> return leftBattery >= 0 && rightBattery >= 0; } + private boolean isProfileConnectedFail() { + return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail + || mIsHeadsetProfileConnectedFail; + } + /** * @return resource for android auto string that describes the connection state of this device. */ diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 93dcbfeab172..5c89a019bf82 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -31,6 +32,8 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.media.AudioManager; +import com.android.settingslib.R; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -922,4 +925,16 @@ public class CachedBluetoothDeviceTest { assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1); assertThat(subCachedDevice.mDevice).isEqualTo(mDevice); } + + @Test + public void getConnectionSummary_profileConnectedFail_showErrorMessage() { + final A2dpProfile profle = mock(A2dpProfile.class); + mCachedDevice.onProfileStateChanged(profle, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.setProfileConnectedStatus(BluetoothProfile.A2DP, true); + + when(profle.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED); + + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + mContext.getString(R.string.profile_connect_timeout_subtext)); + } } |