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

Commit 428fd96f authored by Andre Eisenbach's avatar Andre Eisenbach Committed by Gerrit Code Review
Browse files

Merge "Add intent handler for HF battery indicator (2/2)"

parents d0209bc6 823b03b4
Loading
Loading
Loading
Loading
+3 −7
Original line number Original line Diff line number Diff line
@@ -216,12 +216,6 @@ public class AdapterService extends Service {
                debugLog("AdapterService() - REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount);
                debugLog("AdapterService() - REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount);
            }
            }
        }
        }

        // This is initialized at the beginning in order to prevent
        // NullPointerException from happening if AdapterService
        // functions are called before BLE is turned on due to
        // |mRemoteDevices| being null.
        mRemoteDevices = new RemoteDevices(this);
    }
    }


    public void addProfile(ProfileService profile) {
    public void addProfile(ProfileService profile) {
@@ -401,6 +395,8 @@ public class AdapterService extends Service {
    public void onCreate() {
    public void onCreate() {
        super.onCreate();
        super.onCreate();
        debugLog("onCreate()");
        debugLog("onCreate()");
        mRemoteDevices = new RemoteDevices(this);
        mRemoteDevices.init();
        mBinder = new AdapterServiceBinder(this);
        mBinder = new AdapterServiceBinder(this);
        mAdapterProperties = new AdapterProperties(this);
        mAdapterProperties = new AdapterProperties(this);
        mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);
        mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);
@@ -494,7 +490,7 @@ public class AdapterService extends Service {
        // turned off then on. The same effect can be achieved by
        // turned off then on. The same effect can be achieved by
        // calling cleanup but this may not be necessary at all
        // calling cleanup but this may not be necessary at all
        // We should figure out why this is needed later
        // We should figure out why this is needed later
        mRemoteDevices.cleanup();
        mRemoteDevices.reset();
        mAdapterProperties.init(mRemoteDevices);
        mAdapterProperties.init(mRemoteDevices);


        debugLog("BleOnProcessStart() - Make Bond State Machine");
        debugLog("BleOnProcessStart() - Make Bond State Machine");
+59 −2
Original line number Original line Diff line number Diff line
@@ -19,7 +19,11 @@ package com.android.bluetooth.btservice;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Handler;
import android.os.Message;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.ParcelUuid;
@@ -27,6 +31,8 @@ import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.Log;
import com.android.bluetooth.R;
import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.hfp.HeadsetHalConstants;

import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.LinkedList;
@@ -47,9 +53,25 @@ final class RemoteDevices {
    private static final int UUID_INTENT_DELAY = 6000;
    private static final int UUID_INTENT_DELAY = 6000;
    private static final int MESSAGE_UUID_INTENT = 1;
    private static final int MESSAGE_UUID_INTENT = 1;


    private HashMap<String, DeviceProperties> mDevices;
    private final HashMap<String, DeviceProperties> mDevices;
    private Queue<String> mDeviceQueue;
    private Queue<String> mDeviceQueue;


    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "Received intent: " + intent);
            String action = intent.getAction();
            switch (action) {
                case BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED:
                    onHfIndicatorValueChanged(intent);
                    break;
                default:
                    Log.w(TAG, "Unhandled intent: " + intent);
                    break;
            }
        }
    };

    RemoteDevices(AdapterService service) {
    RemoteDevices(AdapterService service) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAdapterService = service;
        mAdapterService = service;
@@ -58,8 +80,29 @@ final class RemoteDevices {
        mDeviceQueue = new LinkedList<String>();
        mDeviceQueue = new LinkedList<String>();
    }
    }


    /**
     * Init should be called before using this RemoteDevices object
     */
    void init() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED);
        mAdapterService.registerReceiver(mReceiver, filter);
    }


    /**
     * Clean up should be called when this object is no longer needed, must be called after init()
     */
    void cleanup() {
    void cleanup() {
        // Unregister receiver first, mAdapterService is never null
        mAdapterService.unregisterReceiver(mReceiver);
        reset();
    }

    /**
     * Reset should be called when the state of this object needs to be cleared
     * RemoteDevices is still usable after reset
     */
    void reset() {
        if (mSdpTracker !=null)
        if (mSdpTracker !=null)
            mSdpTracker.clear();
            mSdpTracker.clear();


@@ -346,7 +389,7 @@ final class RemoteDevices {
    @VisibleForTesting
    @VisibleForTesting
    void resetBatteryLevel(BluetoothDevice device) {
    void resetBatteryLevel(BluetoothDevice device) {
        if (device == null) {
        if (device == null) {
            warnLog("device is null");
            warnLog("Device is null");
            return;
            return;
        }
        }
        DeviceProperties deviceProperties = getDeviceProperties(device);
        DeviceProperties deviceProperties = getDeviceProperties(device);
@@ -518,6 +561,20 @@ final class RemoteDevices {
        mHandler.sendMessage(message);
        mHandler.sendMessage(message);
    }
    }


    @VisibleForTesting
    void onHfIndicatorValueChanged(Intent intent) {
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        if (device == null) {
            Log.e(TAG, "onHfIndicatorValueChanged() remote device is null");
            return;
        }
        int indicatorId = intent.getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1);
        int indicatorValue = intent.getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -1);
        if (indicatorId == HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS) {
            updateBatteryLevel(device, indicatorValue);
        }
    }

    private final Handler mHandler = new Handler() {
    private final Handler mHandler = new Handler() {
        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -67,5 +67,5 @@ final public class HeadsetHalConstants {


    // Match up with bthf_hf_ind_type_t of bt_hf.h
    // Match up with bthf_hf_ind_type_t of bt_hf.h
    final static int HF_INDICATOR_ENHANCED_DRIVER_SAFETY = 1;
    final static int HF_INDICATOR_ENHANCED_DRIVER_SAFETY = 1;
    final static int HF_INDICATOR_BATTERY_LEVEL_STATUS = 2;
    public final static int HF_INDICATOR_BATTERY_LEVEL_STATUS = 2;
}
}
+12 −12
Original line number Original line Diff line number Diff line
@@ -3024,11 +3024,16 @@ final class HeadsetStateMachine extends StateMachine {
        }
        }
    }
    }


    private void sendIndicatorIntent(BluetoothDevice device, int ind_id, String ind_value) {
    /**
     * Send HF indicator value changed intent
     * @param device Device whose HF indicator value has changed
     * @param ind_id Indicator ID [0-65535]
     * @param ind_value Indicator Value [0-65535], -1 means invalid but ind_id is supported
     */
    private void sendIndicatorIntent(BluetoothDevice device, int ind_id, int ind_value) {
        Intent intent = new Intent(BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED);
        Intent intent = new Intent(BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, ind_id);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, ind_id);
        if (ind_value != null)
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, ind_value);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, ind_value);


        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
@@ -3047,7 +3052,7 @@ final class HeadsetStateMachine extends StateMachine {
            String id = at_string.substring(iter, iter1);
            String id = at_string.substring(iter, iter1);


            try {
            try {
                ind_id = new Integer(id);
                ind_id = Integer.valueOf(id);
            } catch (NumberFormatException e) {
            } catch (NumberFormatException e) {
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
            }
            }
@@ -3056,12 +3061,12 @@ final class HeadsetStateMachine extends StateMachine {
                case HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY:
                case HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY:
                    log("Send Broadcast intent for the"
                    log("Send Broadcast intent for the"
                            + "Enhanced Driver Safety indicator.");
                            + "Enhanced Driver Safety indicator.");
                    sendIndicatorIntent(device, ind_id, null);
                    sendIndicatorIntent(device, ind_id, -1);
                    break;
                    break;
                case HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS:
                case HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS:
                    log("Send Broadcast intent for the"
                    log("Send Broadcast intent for the"
                            + "Battery Level indicator.");
                            + "Battery Level indicator.");
                    sendIndicatorIntent(device, ind_id, null);
                    sendIndicatorIntent(device, ind_id, -1);
                    break;
                    break;
                default:
                default:
                    log("Invalid HF Indicator Received");
                    log("Invalid HF Indicator Received");
@@ -3074,12 +3079,7 @@ final class HeadsetStateMachine extends StateMachine {


    private void processAtBiev(int ind_id, int ind_value, BluetoothDevice device) {
    private void processAtBiev(int ind_id, int ind_value, BluetoothDevice device) {
        log(" Process AT + BIEV Command : " + ind_id + ", " + ind_value);
        log(" Process AT + BIEV Command : " + ind_id + ", " + ind_value);

        sendIndicatorIntent(device, ind_id, ind_value);
        String ind_value_str = Integer.toString(ind_value);

        Intent intent = new Intent(BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        sendIndicatorIntent(device, ind_id, ind_value_str);
    }
    }


    private void onConnectionStateChanged(int state, byte[] address) {
    private void onConnectionStateChanged(int state, byte[] address) {
+40 −0
Original line number Original line Diff line number Diff line
@@ -10,11 +10,13 @@ import static org.mockito.Mockito.when;


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.content.Intent;
import android.content.Intent;
import android.os.Looper;
import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.AndroidJUnit4;


import com.android.bluetooth.Utils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.hfp.HeadsetHalConstants;


import org.junit.Assert;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Before;
@@ -211,6 +213,35 @@ public class RemoteDevicesTest {
        verifyNoMoreInteractions(mAdapterService);
        verifyNoMoreInteractions(mAdapterService);
    }
    }


    @Test
    public void testHfIndicatorParser_testCorrectValue() {
        int batteryLevel = 10;

        // Verify that device property is null initially
        Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1));

        // Verify that ACTION_HF_INDICATORS_VALUE_CHANGED intent updates battery level
        mRemoteDevices.onHfIndicatorValueChanged(getHfIndicatorIntent(
                mDevice1, batteryLevel, HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS));
        verify(mAdapterService).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture());
        verfyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument);
        Assert.assertEquals(AdapterService.BLUETOOTH_PERM, mStringArgument.getValue());
    }

    @Test
    public void testHfIndicatorParser_testWrongIndicatorId() {
        int batteryLevel = 10;

        // Verify that device property is null initially
        Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1));

        // Verify that ACTION_HF_INDICATORS_VALUE_CHANGED intent updates battery level
        mRemoteDevices.onHfIndicatorValueChanged(getHfIndicatorIntent(mDevice1, batteryLevel, 3));
        verify(mAdapterService, never()).sendBroadcast(any(), anyString());
        // Verify that device property is still null after invalid update
        Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1));
    }

    private static void verfyBatteryLevelChangedIntent(
    private static void verfyBatteryLevelChangedIntent(
            BluetoothDevice device, int batteryLevel, ArgumentCaptor<Intent> intentArgument) {
            BluetoothDevice device, int batteryLevel, ArgumentCaptor<Intent> intentArgument) {
        Assert.assertEquals(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED,
        Assert.assertEquals(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED,
@@ -222,4 +253,13 @@ public class RemoteDevicesTest {
        Assert.assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT,
        Assert.assertEquals(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT,
                intentArgument.getValue().getFlags());
                intentArgument.getValue().getFlags());
    }
    }

    private static Intent getHfIndicatorIntent(
            BluetoothDevice device, int batteryLevel, int indicatorId) {
        Intent intent = new Intent(BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, indicatorId);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, batteryLevel);
        return intent;
    }
}
}