Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cca43167 authored by Glenn Maynard's avatar Glenn Maynard
Browse files

Fix A2DP not connecting while asleep.

This is a port of an older fix, which was probably lost in merging:

https://github.com/zewt/android_frameworks_base/commit/111ed5d16f95163fb58bb87407c9ab7268e0893a

This bug happens on a stock 2.3.4 Nexus S; it's not a CM-specific problem.
This fix should probably go upstream at some point.

Original log:

> Some BlueTooth devices will initiate a HFP connection, and then leave it
> to the phone to initiate A2DP.  This was handled with MESSAGE_CONNECT_TO.
>
> However, this was sent using mHandler.sendMessageDelayed, which won't
> wake the phone if it's asleep.  This caused some BT devices to cleanly
> connect using HFP, but to not connect A2DP until the phone is manually
> woken up to allow the MESSAGE_CONNECT_TO message to be delivered.
>
> Replace this message with an AlarmManager alarm, which will wake the
> device properly.  Improves connection with Sony MEX-BT3800U.
>
> (Connecting is still not completely reliable; connecting sometimes still
> mysteriously fails, but this helps a lot.)

(The problem is now with CONNECT_OTHER_PROFILES.)

In case anyone in upstream QA wants to take the initiative to buy the
device for future testing, see: http://www.amazon.com/dp/B0032FOJPM

.
Note that in order to reproduce this problem, the phone must actually
be asleep; any unrelated application holding a stray wakelock can mask
this bug.

This may not be the ideal way to approach this: it uses AlarmManager to
schedule the connection, but the scheduled intent then queues the actual
connection to the event loop.  In principle, the phone may go to sleep
again in the interim.  It would be better to actually handle the connection
from the intent handler, as the original patch did, so we can be sure a
wakelock is held for the duration.

It's not clear to me how to do that with the HierarchicalStateMachine,
however, and I havn't yet had any problems with doing it like this; at any
rate it shouldn't cause any regressions.

Change-Id: I41353abd87127cd04d68b15754655c57d3928499
Signed-off-by: default avatarGlenn Maynard <glenn@zewt.org>
parent 2770abd7
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -16,12 +16,15 @@

package android.bluetooth;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.server.BluetoothA2dpService;
import android.server.BluetoothService;
import android.util.Log;
@@ -85,6 +88,9 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
    private static final long INIT_INCOMING_REJECT_TIMER = 1000; // 1 sec
    private static final long MAX_INCOMING_REJECT_TIMER = 3600 * 1000 * 4; // 4 hours

    private static final String ACTION_CONNECT = "android.bluetooth.profile_state.CONNECT";
    private static final String ACTION_CONNECT_TYPE = "android.bluetooth.profile_state.CONNECT_TYPE";

    private static final String PREFS_NAME = "ConnectionAccess";

    private BondedDevice mBondedDevice = new BondedDevice();
@@ -165,6 +171,11 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
                Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_REPLY);
                msg.arg1 = val;
                sendMessage(msg);
            } else if (action.equals(ACTION_CONNECT)) {
                Message msg = new Message();
                msg.what = CONNECT_OTHER_PROFILES;
                msg.arg1 = intent.getIntExtra(ACTION_CONNECT_TYPE, -1);
                sendMessage(msg);
            }
      }
    };
@@ -206,6 +217,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
        filter.addAction(ACTION_CONNECT);

        mContext.registerReceiver(mBroadcastReceiver, filter);

@@ -806,6 +818,15 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
    }

    private void scheduleConnect(int type) {
        AlarmManager mgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(ACTION_CONNECT);
        i.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
        i.putExtra(ACTION_CONNECT_TYPE, type);
        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
        mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + CONNECT_OTHER_PROFILES_DELAY, pi);
    }

    private int getTrust() {
        String address = mDevice.getAddress();
        if (mIncomingConnections != null) return mIncomingConnections.first;
@@ -999,10 +1020,8 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
                if (mA2dpService.getSinkPriority(mDevice) == BluetoothA2dp.PRIORITY_ON ||
                        mA2dpService.getSinkPriority(mDevice) ==
                            BluetoothA2dp.PRIORITY_AUTO_CONNECT) {
                    Message msg = new Message();
                    msg.what = CONNECT_OTHER_PROFILES;
                    msg.arg1 = CONNECT_A2DP_OUTGOING;
                    sendMessageDelayed(msg, CONNECT_OTHER_PROFILES_DELAY);
                    Log.i(TAG, "Queueing CONNECT_A2DP_OUTGOING");
                    scheduleConnect(CONNECT_A2DP_OUTGOING);
                }
                break;
            case CONNECT_A2DP_INCOMING:
@@ -1012,10 +1031,8 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
                if (mHeadsetService.getPriority(mDevice) == BluetoothHeadset.PRIORITY_ON
                        || mHeadsetService.getPriority(mDevice) ==
                            BluetoothHeadset.PRIORITY_AUTO_CONNECT) {
                    Message msg = new Message();
                    msg.what = CONNECT_OTHER_PROFILES;
                    msg.arg1 = CONNECT_HFP_OUTGOING;
                    sendMessageDelayed(msg, CONNECT_OTHER_PROFILES_DELAY);
                    Log.i(TAG, "Queueing CONNECT_HFP_OUTGOING");
                    scheduleConnect(CONNECT_HFP_OUTGOING);
                }
                break;
            default: