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

Commit 3fe3e386 authored by Jack He's avatar Jack He Committed by android-build-merger
Browse files

Merge changes from topic "bt-fix-phone-policy-limit-retry" am: 0cff9baf

am: 24b2f360

Change-Id: I700bab9fc058731a45a331ee3b6c40c2c641bea2
parents ef712a64 24b2f360
Loading
Loading
Loading
Loading
+108 −72
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.pan.PanService;
import com.android.bluetooth.pan.PanService;
import com.android.internal.R;
import com.android.internal.R;


import java.util.HashSet;
import java.util.List;
import java.util.List;


// Describes the phone policy
// Describes the phone policy
@@ -78,41 +79,53 @@ class PhonePolicy {
    final private static int MESSAGE_CONNECT_OTHER_PROFILES = 3;
    final private static int MESSAGE_CONNECT_OTHER_PROFILES = 3;
    final private static int MESSAGE_ADAPTER_STATE_TURNED_ON = 4;
    final private static int MESSAGE_ADAPTER_STATE_TURNED_ON = 4;


    public static final int PROFILE_CONN_CONNECTED = 1;

    // Timeouts
    // Timeouts
    final private static int CONNECT_OTHER_PROFILES_TIMEOUT = 6000; // 6s
    final private static int CONNECT_OTHER_PROFILES_TIMEOUT = 6000; // 6s


    final private AdapterService mAdapterService;
    final private AdapterService mAdapterService;
    final private ServiceFactory mFactory;
    final private ServiceFactory mFactory;
    final private Handler mHandler;
    final private Handler mHandler;
    final private HashSet<BluetoothDevice> mHeadsetRetrySet = new HashSet<>();
    final private HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>();


    // Broadcast receiver for all changes to states of various profiles
    // Broadcast receiver for all changes to states of various profiles
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "Received intent " + intent);
            String action = intent.getAction();
            if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
            if (action == null) {
                errorLog("Received intent with null action");
                return;
            }
            switch (action) {
                case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
                                    BluetoothProfile.HEADSET,
                                    BluetoothProfile.HEADSET,
                                    -1, // No-op argument
                                    -1, // No-op argument
                                    intent)
                                    intent)
                            .sendToTarget();
                            .sendToTarget();
            } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
                    break;
                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
                                    BluetoothProfile.A2DP,
                                    BluetoothProfile.A2DP,
                                    -1, // No-op argument
                                    -1, // No-op argument
                                    intent)
                                    intent)
                            .sendToTarget();
                            .sendToTarget();
            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
                    break;
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    // Only pass the message on if the adapter has actually changed state from
                    // Only pass the message on if the adapter has actually changed state from
                    // non-ON to ON. NOTE: ON is the state depicting BREDR ON and not just BLE ON.
                    // non-ON to ON. NOTE: ON is the state depicting BREDR ON and not just BLE ON.
                    int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                    int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                    if (newState == BluetoothAdapter.STATE_ON) {
                    if (newState == BluetoothAdapter.STATE_ON) {
                        mHandler.obtainMessage(MESSAGE_ADAPTER_STATE_TURNED_ON).sendToTarget();
                        mHandler.obtainMessage(MESSAGE_ADAPTER_STATE_TURNED_ON).sendToTarget();
                    }
                    }
            } else if (BluetoothDevice.ACTION_UUID.equals(intent.getAction())) {
                    break;
                case BluetoothDevice.ACTION_UUID:
                    mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES, intent).sendToTarget();
                    mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES, intent).sendToTarget();
                    break;
                default:
                    Log.e(TAG, "Received unexpected intent, action=" + action);
                    break;
            }
            }
        }
        }
    };
    };
@@ -132,17 +145,16 @@ class PhonePolicy {
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            switch (msg.what) {
                case MESSAGE_PROFILE_INIT_PRIORITIES: {
                case MESSAGE_PROFILE_INIT_PRIORITIES: {
                    Intent intent = (Intent) msg.obj;
                    BluetoothDevice device =
                    BluetoothDevice device =
                            (BluetoothDevice) ((Intent) msg.obj)
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                                    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
                    Parcelable[] uuids =
                    debugLog("Received ACTION_UUID for device " + device);
                            ((Intent) msg.obj).getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);

                    Log.d(TAG, "UUIDs on ACTION_UUID: " + uuids + " for device " + device);
                    if (uuids != null) {
                    if (uuids != null) {
                        ParcelUuid[] uuidsToSend = new ParcelUuid[uuids.length];
                        ParcelUuid[] uuidsToSend = new ParcelUuid[uuids.length];
                        for (int i = 0; i < uuidsToSend.length; i++) {
                        for (int i = 0; i < uuidsToSend.length; i++) {
                            uuidsToSend[i] = (ParcelUuid) uuids[i];
                            uuidsToSend[i] = (ParcelUuid) uuids[i];
                            debugLog("index=" + i + "uuid=" + uuidsToSend[i]);
                        }
                        }
                        processInitProfilePriorities(device, uuidsToSend);
                        processInitProfilePriorities(device, uuidsToSend);
                    }
                    }
@@ -165,6 +177,7 @@ class PhonePolicy {


                case MESSAGE_ADAPTER_STATE_TURNED_ON:
                case MESSAGE_ADAPTER_STATE_TURNED_ON:
                    // Call auto connect when adapter switches state to ON
                    // Call auto connect when adapter switches state to ON
                    resetStates();
                    autoConnect();
                    autoConnect();
                    break;
                    break;
            }
            }
@@ -182,6 +195,7 @@ class PhonePolicy {
    }
    }
    protected void cleanup() {
    protected void cleanup() {
        mAdapterService.unregisterReceiver(mReceiver);
        mAdapterService.unregisterReceiver(mReceiver);
        resetStates();
    }
    }


    PhonePolicy(AdapterService service, ServiceFactory factory) {
    PhonePolicy(AdapterService service, ServiceFactory factory) {
@@ -192,7 +206,7 @@ class PhonePolicy {


    // Policy implementation, all functions MUST be private
    // Policy implementation, all functions MUST be private
    private void processInitProfilePriorities(BluetoothDevice device, ParcelUuid[] uuids) {
    private void processInitProfilePriorities(BluetoothDevice device, ParcelUuid[] uuids) {
        debugLog("processInitProfilePriorities() - device " + device + " UUIDs " + uuids);
        debugLog("processInitProfilePriorities() - device " + device);
        HidService hidService = mFactory.getHidService();
        HidService hidService = mFactory.getHidService();
        A2dpService a2dpService = mFactory.getA2dpService();
        A2dpService a2dpService = mFactory.getA2dpService();
        HeadsetService headsetService = mFactory.getHeadsetService();
        HeadsetService headsetService = mFactory.getHeadsetService();
@@ -235,23 +249,35 @@ class PhonePolicy {


    private void processProfileStateChanged(
    private void processProfileStateChanged(
            BluetoothDevice device, int profileId, int nextState, int prevState) {
            BluetoothDevice device, int profileId, int nextState, int prevState) {
        // Profiles relevant to phones.
        debugLog("processProfileStateChanged, device=" + device + ", profile=" + profileId + ", "
                + prevState + " -> " + nextState);
        if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET))
        if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET))
                && (nextState == BluetoothProfile.STATE_CONNECTED)) {
                && (nextState == BluetoothProfile.STATE_CONNECTED)) {
            debugLog("Profile connected id: " + profileId
            switch (profileId) {
                    + " Schedule missing profile connection if any");
                case BluetoothProfile.A2DP:
                    mA2dpRetrySet.remove(device);
                    break;
                case BluetoothProfile.HEADSET:
                    mHeadsetRetrySet.remove(device);
                    break;
            }
            connectOtherProfile(device);
            connectOtherProfile(device);
            setProfileAutoConnectionPriority(device, profileId);
            setProfileAutoConnectionPriority(device, profileId);
        }
        }
    }
    }


    private void resetStates() {
        mHeadsetRetrySet.clear();
        mA2dpRetrySet.clear();
    }

    private void autoConnect() {
    private void autoConnect() {
        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
            errorLog("autoConnect() - BT is not ON. Exiting autoConnect");
            errorLog("autoConnect() - BT is not ON. Exiting autoConnect");
            return;
            return;
        }
        }


        if (mAdapterService.isQuietModeEnabled() == false) {
        if (!mAdapterService.isQuietModeEnabled()) {
            debugLog("autoConnect() - Initiate auto connection on BT on...");
            debugLog("autoConnect() - Initiate auto connection on BT on...");
            // Phone profiles.
            // Phone profiles.
            autoConnectHeadset();
            autoConnectHeadset();
@@ -262,45 +288,48 @@ class PhonePolicy {
    }
    }


    private void autoConnectHeadset() {
    private void autoConnectHeadset() {
        HeadsetService hsService = mFactory.getHeadsetService();
        final HeadsetService hsService = mFactory.getHeadsetService();
        if (hsService == null) {
        if (hsService == null) {
            errorLog("autoConnectHeadset() - service is null");
            errorLog("autoConnectHeadset, service is null");
            return;
            return;
        }
        }

        final BluetoothDevice bondedDevices[] = mAdapterService.getBondedDevices();
        BluetoothDevice bondedDevices[] = mAdapterService.getBondedDevices();
        if (bondedDevices == null) {
        if (bondedDevices == null) {
            errorLog("autoConnectHeadset() - devices are null");
            errorLog("autoConnectHeadset, bondedDevices are null");
            return;
            return;
        }
        }

        debugLog("autoConnectHeadset() - bondedDevices: " + bondedDevices);
        for (BluetoothDevice device : bondedDevices) {
        for (BluetoothDevice device : bondedDevices) {
            debugLog("autoConnectHeadset() - attempt autoconnect with device " + device);
            debugLog("autoConnectHeadset, attempt auto-connect with device " + device);
            if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
            if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
                debugLog("autoConnectHeadset() - Connecting HFP with " + device.toString());
                debugLog("autoConnectHeadset, Connecting HFP with " + device);
                hsService.connect(device);
                hsService.connect(device);
            }
            }
        }
        }
    }
    }


    private void autoConnectA2dp() {
    private void autoConnectA2dp() {
        A2dpService a2dpSservice = mFactory.getA2dpService();
        final A2dpService a2dpService = mFactory.getA2dpService();
        BluetoothDevice bondedDevices[] = mAdapterService.getBondedDevices();
        if (a2dpService == null) {
        if ((bondedDevices == null) || (a2dpSservice == null)) {
            errorLog("autoConnectA2dp, service is null");
            return;
        }
        final BluetoothDevice bondedDevices[] = mAdapterService.getBondedDevices();
        if (bondedDevices == null) {
            errorLog("autoConnectA2dp, bondedDevices are null");
            return;
            return;
        }
        }
        for (BluetoothDevice device : bondedDevices) {
        for (BluetoothDevice device : bondedDevices) {
            if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
            debugLog("autoConnectA2dp, attempt auto-connect with device " + device);
                debugLog("autoConnectA2dp() - Connecting A2DP with " + device.toString());
            if (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
                a2dpSservice.connect(device);
                debugLog("autoConnectA2dp, connecting A2DP with " + device);
                a2dpService.connect(device);
            }
            }
        }
        }
    }
    }


    public void connectOtherProfile(BluetoothDevice device) {
    private void connectOtherProfile(BluetoothDevice device) {
        if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false)
        if ((!mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES))
                && (mAdapterService.isQuietModeEnabled() == false)) {
                && (!mAdapterService.isQuietModeEnabled())) {
            Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES);
            Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES);
            m.obj = device;
            m.obj = device;
            mHandler.sendMessageDelayed(m, CONNECT_OTHER_PROFILES_TIMEOUT);
            mHandler.sendMessageDelayed(m, CONNECT_OTHER_PROFILES_TIMEOUT);
@@ -312,8 +341,9 @@ class PhonePolicy {
    // connect to the device that initiated the connection.  In the event that this function is
    // connect to the device that initiated the connection.  In the event that this function is
    // invoked and there are no current bluetooth connections no new profiles will be connected.
    // invoked and there are no current bluetooth connections no new profiles will be connected.
    private void processConnectOtherProfiles(BluetoothDevice device) {
    private void processConnectOtherProfiles(BluetoothDevice device) {
        debugLog("processConnectOtherProfiles() - device " + device);
        debugLog("processConnectOtherProfiles, device=" + device);
        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
            warnLog("processConnectOtherProfiles, adapter is not ON " + mAdapterService.getState());
            return;
            return;
        }
        }
        HeadsetService hsService = mFactory.getHeadsetService();
        HeadsetService hsService = mFactory.getHeadsetService();
@@ -338,29 +368,31 @@ class PhonePolicy {
            allProfilesEmpty = allProfilesEmpty && panConnDevList.isEmpty();
            allProfilesEmpty = allProfilesEmpty && panConnDevList.isEmpty();
        }
        }


        debugLog("processConnectOtherProfiles() - allProfilesEmpty " + allProfilesEmpty + " device "
                + device);

        if (allProfilesEmpty) {
        if (allProfilesEmpty) {
            // must have connected then disconnected, don't bother connecting others.
            // considered as fully disconnected, don't bother connecting others.
            debugLog("processConnectOtherProfiles, all profiles disconnected for " + device);
            // reset retry status so that in the next round we can start retrying connections again
            resetStates();
            return;
            return;
        }
        }


        if (hsService != null) {
        if (hsService != null) {
            if (hsConnDevList.isEmpty()
            if (hsConnDevList.isEmpty() && !mHeadsetRetrySet.contains(device)
                    && (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
                    && (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
                    && (hsService.getConnectionState(device)
                    && (hsService.getConnectionState(device)
                               == BluetoothProfile.STATE_DISCONNECTED)) {
                               == BluetoothProfile.STATE_DISCONNECTED)) {
                debugLog("Retrying connection to HS with device " + device);
                debugLog("Retrying connection to Headset with device " + device);
                mHeadsetRetrySet.add(device);
                hsService.connect(device);
                hsService.connect(device);
            }
            }
        }
        }
        if (a2dpService != null) {
        if (a2dpService != null) {
            if (a2dpConnDevList.isEmpty()
            if (a2dpConnDevList.isEmpty() && !mA2dpRetrySet.contains(device)
                    && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
                    && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
                    && (a2dpService.getConnectionState(device)
                    && (a2dpService.getConnectionState(device)
                               == BluetoothProfile.STATE_DISCONNECTED)) {
                               == BluetoothProfile.STATE_DISCONNECTED)) {
                debugLog("Retrying connection to A2DP with device " + device);
                debugLog("Retrying connection to A2DP with device " + device);
                mA2dpRetrySet.add(device);
                a2dpService.connect(device);
                a2dpService.connect(device);
            }
            }
        }
        }
@@ -369,21 +401,13 @@ class PhonePolicy {
                    && (panService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
                    && (panService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
                    && (panService.getConnectionState(device)
                    && (panService.getConnectionState(device)
                               == BluetoothProfile.STATE_DISCONNECTED)) {
                               == BluetoothProfile.STATE_DISCONNECTED)) {
                debugLog("Retrying connection to HF with device " + device);
                debugLog("Retrying connection to PAN with device " + device);
                panService.connect(device);
                panService.connect(device);
            }
            }
        }
        }
    }
    }


    private void debugLog(String msg) {
    private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId) {
        if (DBG) Log.d(TAG, msg);
    }

    private void errorLog(String msg) {
        Log.e(TAG, msg);
    }

    void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId) {
        switch (profileId) {
        switch (profileId) {
            case BluetoothProfile.HEADSET:
            case BluetoothProfile.HEADSET:
                HeadsetService hsService = mFactory.getHeadsetService();
                HeadsetService hsService = mFactory.getHeadsetService();
@@ -406,7 +430,7 @@ class PhonePolicy {
                break;
                break;


            default:
            default:
                Log.w(TAG, "Attempting to set Auto Connect priority on invalid profile");
                Log.w(TAG, "Tried to set AutoConnect priority on invalid profile " + profileId);
                break;
                break;
        }
        }
    }
    }
@@ -430,4 +454,16 @@ class PhonePolicy {
            }
            }
        }
        }
    }
    }

    private static void debugLog(String msg) {
        if (DBG) Log.d(TAG, msg);
    }

    private static void warnLog(String msg) {
        Log.w(TAG, msg);
    }

    private static void errorLog(String msg) {
        Log.e(TAG, msg);
    }
}
}