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

Commit 460d9fc6 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge changes Id1239782,Ic0b5cdab,I0a0db29e,I78d0a1df

* changes:
  leaudio: Make use of leAudioHealthStatus module
  leaudio: Add way to handle invalid CSIS member device
  leaudio: Add health based action to java layer
  LeAudioHealthStatus: Initial Implementation
parents 27d74299 bfbc6439
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ static jmethodID method_onAudioConf;
static jmethodID method_onSinkAudioLocationAvailable;
static jmethodID method_onAudioLocalCodecCapabilities;
static jmethodID method_onAudioGroupCodecConf;
static jmethodID method_onHealthBasedRecommendationAction;
static jmethodID method_onHealthBasedGroupRecommendationAction;

static struct {
  jclass clazz;
@@ -270,6 +272,43 @@ class LeAudioClientCallbacksImpl : public LeAudioClientCallbacks {
        inputCodecConfigObj, outputCodecConfigObj,
        inputSelectableCodecConfigArray, outputSelectableCodecConfigArray);
  }

  void OnHealthBasedRecommendationAction(
      const RawAddress& bd_addr,
      bluetooth::le_audio::LeAudioHealthBasedAction action) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    CallbackEnv sCallbackEnv(__func__);
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;

    ScopedLocalRef<jbyteArray> addr(
        sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
    if (!addr.get()) {
      LOG(ERROR) << "Failed to new jbyteArray bd addr for group status";
      return;
    }

    sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
                                     (jbyte*)&bd_addr);
    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_onHealthBasedRecommendationAction,
                                 addr.get(), (jint)action);
  }

  void OnHealthBasedGroupRecommendationAction(
      int group_id,
      bluetooth::le_audio::LeAudioHealthBasedAction action) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    CallbackEnv sCallbackEnv(__func__);
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;

    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_onHealthBasedGroupRecommendationAction,
                                 (jint)group_id, (jint)action);
  }
};

static LeAudioClientCallbacksImpl sLeAudioClientCallbacks;
@@ -301,6 +340,10 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
                       "Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
                       "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
                       "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V");
  method_onHealthBasedRecommendationAction =
      env->GetMethodID(clazz, "onHealthBasedRecommendationAction", "([BI)V");
  method_onHealthBasedGroupRecommendationAction = env->GetMethodID(
      clazz, "onHealthBasedGroupRecommendationAction", "(II)V");
}

std::vector<btle_audio_codec_config_t> prepareCodecPreferences(
+26 −0
Original line number Diff line number Diff line
@@ -219,6 +219,32 @@ public class LeAudioNativeInterface {
        sendMessageToService(event);
    }

    @VisibleForTesting
    void onHealthBasedRecommendationAction(byte[] address, int action) {
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION);
        event.device = getDevice(address);
        event.valueInt1 = action;

        if (DBG) {
            Log.d(TAG, "onHealthBasedRecommendationAction: " + event);
        }
        sendMessageToService(event);
    }

    @VisibleForTesting
    void onHealthBasedGroupRecommendationAction(int groupId, int action) {
        LeAudioStackEvent event =
                new LeAudioStackEvent(
                        LeAudioStackEvent.EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION);
        event.valueInt1 = groupId;
        event.valueInt2 = action;

        if (DBG) {
            Log.d(TAG, "onHealthBasedGroupRecommendationAction: " + event);
        }
        sendMessageToService(event);
    }
    /**
     * Initializes the native interface.
     *
+32 −0
Original line number Diff line number Diff line
@@ -1564,6 +1564,32 @@ public class LeAudioService extends ProfileService {
        }
    }

    private void handleDeviceHealthAction(BluetoothDevice device, int action) {
        // To implement
        if (DBG) {
            Log.d(
                    TAG,
                    "handleDeviceHealthAction: "
                            + device
                            + " action: "
                            + action
                            + ", not implemented");
        }
    }

    private void handleGroupHealthAction(int groupId, int action) {
        // To implement
        if (DBG) {
            Log.d(
                    TAG,
                    "handleGroupHealthAction: groupId: "
                            + groupId
                            + " action: "
                            + action
                            + ", not implemented");
        }
    }

    private void handleGroupTransitToActive(int groupId) {
        synchronized (mGroupLock) {
            LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId);
@@ -1971,6 +1997,12 @@ public class LeAudioService extends ProfileService {
                default:
                    break;
            }
        } else if (stackEvent.type
                == LeAudioStackEvent.EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION) {
            handleDeviceHealthAction(stackEvent.device, stackEvent.valueInt1);
        } else if (stackEvent.type
                == LeAudioStackEvent.EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION) {
            handleGroupHealthAction(stackEvent.valueInt1, stackEvent.valueInt2);
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED) {
            int broadcastId = stackEvent.valueInt1;
            boolean success = stackEvent.valueBool1;
+33 −2
Original line number Diff line number Diff line
@@ -37,8 +37,10 @@ public class LeAudioStackEvent {
    public static final int EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED = 6;
    public static final int EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED = 7;
    public static final int EVENT_TYPE_NATIVE_INITIALIZED = 8;
    public static final int EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION = 9;
    public static final int EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION = 10;
    // -------- DO NOT PUT ANY NEW UNICAST EVENTS BELOW THIS LINE-------------
    public static final int EVENT_TYPE_UNICAST_MAX = 9;
    public static final int EVENT_TYPE_UNICAST_MAX = 11;

    // Broadcast related events
    public static final int EVENT_TYPE_BROADCAST_CREATED = EVENT_TYPE_UNICAST_MAX + 1;
@@ -53,6 +55,11 @@ public class LeAudioStackEvent {
    static final int CONNECTION_STATE_CONNECTED = 2;
    static final int CONNECTION_STATE_DISCONNECTING = 3;

    // Health based recommendation
    static final int HEALTH_RECOMMENDATION_ACTION_NONE = 0;
    static final int HEALTH_RECOMMENDATION_ACTION_DISABLE = 1;
    static final int HEALTH_RECOMMENDATION_ACTION_CONSIDER_DISABLING = 2;

    static final int GROUP_STATUS_INACTIVE = 0;
    static final int GROUP_STATUS_ACTIVE = 1;
    static final int GROUP_STATUS_TURNED_IDLE_DURING_CALL = 2;
@@ -140,6 +147,10 @@ public class LeAudioStackEvent {
                return "EVENT_TYPE_AUDIO_GROUP_CODEC_CONFIG_CHANGED";
            case EVENT_TYPE_NATIVE_INITIALIZED:
                return "EVENT_TYPE_NATIVE_INITIALIZED";
            case EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION:
                return "EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION";
            case EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION:
                return "EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION";
            default:
                return "EVENT_TYPE_UNKNOWN:" + type;
        }
@@ -179,6 +190,17 @@ public class LeAudioStackEvent {
                // same as EVENT_TYPE_BROADCAST_STATE
            case EVENT_TYPE_BROADCAST_STATE:
                return "{broadcastId:" + value + "}";
            case EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION:
                return "{group_id: " + value + "}";
            case EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION:
                switch (value) {
                    case HEALTH_RECOMMENDATION_ACTION_NONE:
                        return "ACTION_DISABLE";
                    case HEALTH_RECOMMENDATION_ACTION_CONSIDER_DISABLING:
                        return "ACTION_CONSIDER_DISABLING";
                    default:
                        return "UNKNOWN";
                }
            default:
                break;
        }
@@ -212,6 +234,15 @@ public class LeAudioStackEvent {
                return "{group_id:" + Integer.toString(value) + "}";
            case EVENT_TYPE_BROADCAST_STATE:
                return "{state:" + broadcastStateToString(value) + "}";
            case EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION:
                switch (value) {
                    case HEALTH_RECOMMENDATION_ACTION_NONE:
                        return "ACTION_DISABLE";
                    case HEALTH_RECOMMENDATION_ACTION_CONSIDER_DISABLING:
                        return "ACTION_CONSIDER_DISABLING";
                    default:
                        return "UNKNOWN";
                }
            default:
                break;
        }
+30 −0
Original line number Diff line number Diff line
@@ -1299,6 +1299,36 @@ public class LeAudioServiceTest {
        assertThat(intent).isNull();
    }

    /**
     * Test native interface health base action message handling. It does not much, just chects
     * stack even and that service not crash
     */
    @Test
    public void testHealthBaseDeviceAction() {
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mSingleDevice, testGroupId);

        LeAudioStackEvent healthBaseDevAction =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_HEALTH_BASED_DEV_RECOMMENDATION);
        healthBaseDevAction.device = mSingleDevice;
        healthBaseDevAction.valueInt1 = LeAudioStackEvent.HEALTH_RECOMMENDATION_ACTION_DISABLE;
        mService.messageFromNative(healthBaseDevAction);
        assertThat(mService.mLeAudioNativeIsInitialized).isTrue();
    }

    @Test
    public void testHealthBasedGroupAction() {
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mSingleDevice, testGroupId);

        LeAudioStackEvent healthBasedGroupAction =
                new LeAudioStackEvent(
                        LeAudioStackEvent.EVENT_TYPE_HEALTH_BASED_GROUP_RECOMMENDATION);
        healthBasedGroupAction.valueInt1 = testGroupId;
        healthBasedGroupAction.valueInt2 = LeAudioStackEvent.HEALTH_RECOMMENDATION_ACTION_DISABLE;
        mService.messageFromNative(healthBasedGroupAction);
        assertThat(mService.mLeAudioNativeIsInitialized).isTrue();
    }

    private void sendEventAndVerifyIntentForGroupStatusChanged(int groupId, int groupStatus) {

Loading