Loading Android.bp +3 −2 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ java_defaults { "-Xep:UnusedMethod:ERROR", "-Xep:UnusedNestedClass:ERROR", "-Xep:UnusedVariable:ERROR", "-Xep:VariableNameSameAsType:ERROR", "-Xep:WaitNotInLoop:ERROR", "-Xep:WakelockReleasedDangerously:ERROR", Loading @@ -172,8 +173,8 @@ java_defaults { "-XepExcludedPaths:.*/srcjars/.*", // The @InlineMe annotation could be made available, but it would // apply on external facing API. This is not desired. For more // context, see https://r.android.com/3303475 // apply on external facing API. This is not desired. // For more context, see https://r.android.com/3303475 "-Xep:InlineMeSuggester:OFF", ], }, Loading android/app/jni/com_android_bluetooth_vc.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; static jfieldID sCallbacksField; class VolumeControlCallbacksImpl : public VolumeControlCallbacks { public: ~VolumeControlCallbacksImpl() = default; Loading Loading @@ -221,8 +223,8 @@ public: (jint)ext_output_id, description, addr.get()); } void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val, uint8_t gain_mode, Mute mute) override { void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_setting, Mute mute, uint8_t gain_mode) override { log::info(""); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); Loading @@ -241,7 +243,7 @@ public: sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), reinterpret_cast<const jbyte*>(&bd_addr)); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStateChanged, (jint)ext_input_id, (jint)gain_val, (jint)gain_mode, (jint)mute, addr.get()); (jint)gain_setting, (jint)mute, (jint)gain_mode, addr.get()); } void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id, Loading Loading @@ -362,7 +364,8 @@ static void initNative(JNIEnv* env, jobject object) { mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { if ((mCallbacksObj = env->NewGlobalRef(env->GetObjectField(object, sCallbacksField))) == nullptr) { log::error("Failed to allocate Global Ref for Volume control Callbacks"); return; } Loading Loading @@ -779,8 +782,9 @@ static jboolean setExtAudioInDescriptionNative(JNIEnv* env, jobject /* object */ return JNI_TRUE; } static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, jbyteArray address, jint ext_input_id, jint gain_val) { static jboolean setExtAudioInGainSettingNative(JNIEnv* env, jobject /* object */, jbyteArray address, jint ext_input_id, jint gain_setting) { log::info(""); std::shared_lock<std::shared_timed_mutex> lock(interface_mutex); if (!sVolumeControlInterface) { Loading @@ -794,7 +798,7 @@ static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, } RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr); sVolumeControlInterface->SetExtAudioInGainValue(*tmpraw, ext_input_id, gain_val); sVolumeControlInterface->SetExtAudioInGainSetting(*tmpraw, ext_input_id, gain_setting); env->ReleaseByteArrayElements(address, addr, 0); return JNI_TRUE; } Loading Loading @@ -875,8 +879,8 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { reinterpret_cast<void*>(getExtAudioInDescriptionNative)}, {"setExtAudioInDescriptionNative", "([BILjava/lang/String;)Z", reinterpret_cast<void*>(setExtAudioInDescriptionNative)}, {"setExtAudioInGainValueNative", "([BII)Z", reinterpret_cast<void*>(setExtAudioInGainValueNative)}, {"setExtAudioInGainSettingNative", "([BII)Z", reinterpret_cast<void*>(setExtAudioInGainSettingNative)}, {"setExtAudioInGainModeNative", "([BIZ)Z", reinterpret_cast<void*>(setExtAudioInGainModeNative)}, {"setExtAudioInGainMuteNative", "([BIZ)Z", Loading @@ -888,6 +892,12 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { return result; } jclass jniVolumeControlNativeInterfaceClass = env->FindClass("com/android/bluetooth/vc/VolumeControlNativeInterface"); sCallbacksField = env->GetFieldID(jniVolumeControlNativeInterfaceClass, "mNativeCallback", "Lcom/android/bluetooth/vc/VolumeControlNativeCallback;"); env->DeleteLocalRef(jniVolumeControlNativeInterfaceClass); const JNIJavaMethod javaMethods[] = { {"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged}, {"onVolumeStateChanged", "(IZI[BZ)V", &method_onVolumeStateChanged}, Loading @@ -904,7 +914,7 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { {"onExtAudioInDescriptionChanged", "(ILjava/lang/String;[B)V", &method_onExtAudioInDescriptionChanged}, }; GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeInterface", javaMethods); GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeCallback", javaMethods); return 0; } Loading android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +10 −9 Original line number Diff line number Diff line Loading @@ -43,14 +43,14 @@ class VolumeControlInputDescriptor { int mType = AudioInputType.UNSPECIFIED; int mGainValue = 0; int mGainSetting = 0; int mGainMode = GainMode.MANUAL_ONLY; int mMute = Mute.DISABLED; /* See AICS 1.0 * The Gain_Setting (mGainValue) field is a signed value for which a single increment or * The Gain_Setting (mGainSetting) field is a signed value for which a single increment or * decrement should result in a corresponding increase or decrease of the input amplitude by * the value of the Gain_Setting_Units (mGainSettingsUnits) field of the Gain Setting * Properties characteristic value. Loading Loading @@ -105,9 +105,9 @@ class VolumeControlInputDescriptor { return mVolumeInputs[id].mType; } int getGain(int id) { int getGainSetting(int id) { if (!isValidId(id)) return 0; return mVolumeInputs[id].mGainValue; return mVolumeInputs[id].mGainSetting; } int getMute(int id) { Loading @@ -123,17 +123,18 @@ class VolumeControlInputDescriptor { mVolumeInputs[id].mGainSettingsMaxSetting = gainMax; } void setState(int id, int gainValue, int gainMode, int mute) { void setState(int id, int gainSetting, int mute, int gainMode) { if (!isValidId(id)) return; Descriptor desc = mVolumeInputs[id]; if (gainValue > desc.mGainSettingsMaxSetting || gainValue < desc.mGainSettingsMinSetting) { Log.e(TAG, "Request fail. Illegal gainValue argument: " + gainValue); if (gainSetting > desc.mGainSettingsMaxSetting || gainSetting < desc.mGainSettingsMinSetting) { Log.e(TAG, "Request fail. Illegal gainSetting argument: " + gainSetting); return; } desc.mGainValue = gainValue; desc.mGainSetting = gainSetting; desc.mGainMode = gainMode; desc.mMute = mute; } Loading @@ -145,7 +146,7 @@ class VolumeControlInputDescriptor { ProfileService.println(sb, " description: " + desc.mDescription); ProfileService.println(sb, " type: " + desc.mType); ProfileService.println(sb, " status: " + desc.mStatus); ProfileService.println(sb, " gainValue: " + desc.mGainValue); ProfileService.println(sb, " gainSetting: " + desc.mGainSetting); ProfileService.println(sb, " gainMode: " + desc.mGainMode); ProfileService.println(sb, " mute: " + desc.mMute); ProfileService.println(sb, " units:" + desc.mGainSettingsUnits); Loading android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java 0 → 100644 +208 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.vc; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED; import static java.util.Objects.requireNonNull; import android.bluetooth.BluetoothDevice; import android.util.Log; import com.android.bluetooth.btservice.AdapterService; import com.android.internal.annotations.VisibleForTesting; class VolumeControlNativeCallback { private static final String TAG = VolumeControlNativeCallback.class.getSimpleName(); private final AdapterService mAdapterService; private final VolumeControlService mVolumeControlService; VolumeControlNativeCallback( AdapterService adapterService, VolumeControlService volumeControlService) { mAdapterService = requireNonNull(adapterService); mVolumeControlService = requireNonNull(volumeControlService); } private BluetoothDevice getDevice(byte[] address) { return mAdapterService.getDeviceFromByte(address); } @VisibleForTesting void onConnectionStateChanged(int state, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = state; Log.d(TAG, "onConnectionStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onVolumeStateChanged( int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = -1; event.valueInt2 = volume; event.valueInt3 = flags; event.valueBool1 = mute; event.valueBool2 = isAutonomous; Log.d(TAG, "onVolumeStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED); event.device = null; event.valueInt1 = groupId; event.valueInt2 = volume; event.valueBool1 = mute; event.valueBool2 = isAutonomous; Log.d(TAG, "onGroupVolumeStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_DEVICE_AVAILABLE); event.device = getDevice(address); event.valueInt1 = numOfExternalOutputs; event.valueInt2 = numOfExternalInputs; Log.d(TAG, "onDeviceAvailable: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED); event.device = getDevice(address); event.valueInt1 = externalOutputId; event.valueInt2 = offset; Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED); event.device = getDevice(address); event.valueInt1 = externalOutputId; event.valueInt2 = location; Log.d(TAG, "onExtAudioOutLocationChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED); event.device = getDevice(address); event.valueInt1 = externalOutputId; event.valueString1 = descr; Log.d(TAG, "onExtAudioOutLocationChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInStateChanged( int externalInputId, int gainSetting, int mute, int gainMode, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = gainSetting; event.valueInt3 = gainMode; event.valueInt4 = mute; Log.d(TAG, "onExtAudioInStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInStatusChanged(int externalInputId, int status, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = status; Log.d(TAG, "onExtAudioInStatusChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInTypeChanged(int externalInputId, int type, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = type; Log.d(TAG, "onExtAudioInTypeChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInDescriptionChanged(int externalInputId, String descr, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueString1 = descr; Log.d(TAG, "onExtAudioInDescriptionChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInGainPropsChanged( int externalInputId, int unit, int min, int max, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = unit; event.valueInt3 = min; event.valueInt4 = max; Log.d(TAG, "onExtAudioInGainPropsChanged: " + event); mVolumeControlService.messageFromNative(event); } } Loading
Android.bp +3 −2 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ java_defaults { "-Xep:UnusedMethod:ERROR", "-Xep:UnusedNestedClass:ERROR", "-Xep:UnusedVariable:ERROR", "-Xep:VariableNameSameAsType:ERROR", "-Xep:WaitNotInLoop:ERROR", "-Xep:WakelockReleasedDangerously:ERROR", Loading @@ -172,8 +173,8 @@ java_defaults { "-XepExcludedPaths:.*/srcjars/.*", // The @InlineMe annotation could be made available, but it would // apply on external facing API. This is not desired. For more // context, see https://r.android.com/3303475 // apply on external facing API. This is not desired. // For more context, see https://r.android.com/3303475 "-Xep:InlineMeSuggester:OFF", ], }, Loading
android/app/jni/com_android_bluetooth_vc.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; static jfieldID sCallbacksField; class VolumeControlCallbacksImpl : public VolumeControlCallbacks { public: ~VolumeControlCallbacksImpl() = default; Loading Loading @@ -221,8 +223,8 @@ public: (jint)ext_output_id, description, addr.get()); } void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val, uint8_t gain_mode, Mute mute) override { void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_setting, Mute mute, uint8_t gain_mode) override { log::info(""); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); Loading @@ -241,7 +243,7 @@ public: sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), reinterpret_cast<const jbyte*>(&bd_addr)); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStateChanged, (jint)ext_input_id, (jint)gain_val, (jint)gain_mode, (jint)mute, addr.get()); (jint)gain_setting, (jint)mute, (jint)gain_mode, addr.get()); } void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id, Loading Loading @@ -362,7 +364,8 @@ static void initNative(JNIEnv* env, jobject object) { mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { if ((mCallbacksObj = env->NewGlobalRef(env->GetObjectField(object, sCallbacksField))) == nullptr) { log::error("Failed to allocate Global Ref for Volume control Callbacks"); return; } Loading Loading @@ -779,8 +782,9 @@ static jboolean setExtAudioInDescriptionNative(JNIEnv* env, jobject /* object */ return JNI_TRUE; } static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, jbyteArray address, jint ext_input_id, jint gain_val) { static jboolean setExtAudioInGainSettingNative(JNIEnv* env, jobject /* object */, jbyteArray address, jint ext_input_id, jint gain_setting) { log::info(""); std::shared_lock<std::shared_timed_mutex> lock(interface_mutex); if (!sVolumeControlInterface) { Loading @@ -794,7 +798,7 @@ static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, } RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr); sVolumeControlInterface->SetExtAudioInGainValue(*tmpraw, ext_input_id, gain_val); sVolumeControlInterface->SetExtAudioInGainSetting(*tmpraw, ext_input_id, gain_setting); env->ReleaseByteArrayElements(address, addr, 0); return JNI_TRUE; } Loading Loading @@ -875,8 +879,8 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { reinterpret_cast<void*>(getExtAudioInDescriptionNative)}, {"setExtAudioInDescriptionNative", "([BILjava/lang/String;)Z", reinterpret_cast<void*>(setExtAudioInDescriptionNative)}, {"setExtAudioInGainValueNative", "([BII)Z", reinterpret_cast<void*>(setExtAudioInGainValueNative)}, {"setExtAudioInGainSettingNative", "([BII)Z", reinterpret_cast<void*>(setExtAudioInGainSettingNative)}, {"setExtAudioInGainModeNative", "([BIZ)Z", reinterpret_cast<void*>(setExtAudioInGainModeNative)}, {"setExtAudioInGainMuteNative", "([BIZ)Z", Loading @@ -888,6 +892,12 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { return result; } jclass jniVolumeControlNativeInterfaceClass = env->FindClass("com/android/bluetooth/vc/VolumeControlNativeInterface"); sCallbacksField = env->GetFieldID(jniVolumeControlNativeInterfaceClass, "mNativeCallback", "Lcom/android/bluetooth/vc/VolumeControlNativeCallback;"); env->DeleteLocalRef(jniVolumeControlNativeInterfaceClass); const JNIJavaMethod javaMethods[] = { {"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged}, {"onVolumeStateChanged", "(IZI[BZ)V", &method_onVolumeStateChanged}, Loading @@ -904,7 +914,7 @@ int register_com_android_bluetooth_vc(JNIEnv* env) { {"onExtAudioInDescriptionChanged", "(ILjava/lang/String;[B)V", &method_onExtAudioInDescriptionChanged}, }; GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeInterface", javaMethods); GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeCallback", javaMethods); return 0; } Loading
android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +10 −9 Original line number Diff line number Diff line Loading @@ -43,14 +43,14 @@ class VolumeControlInputDescriptor { int mType = AudioInputType.UNSPECIFIED; int mGainValue = 0; int mGainSetting = 0; int mGainMode = GainMode.MANUAL_ONLY; int mMute = Mute.DISABLED; /* See AICS 1.0 * The Gain_Setting (mGainValue) field is a signed value for which a single increment or * The Gain_Setting (mGainSetting) field is a signed value for which a single increment or * decrement should result in a corresponding increase or decrease of the input amplitude by * the value of the Gain_Setting_Units (mGainSettingsUnits) field of the Gain Setting * Properties characteristic value. Loading Loading @@ -105,9 +105,9 @@ class VolumeControlInputDescriptor { return mVolumeInputs[id].mType; } int getGain(int id) { int getGainSetting(int id) { if (!isValidId(id)) return 0; return mVolumeInputs[id].mGainValue; return mVolumeInputs[id].mGainSetting; } int getMute(int id) { Loading @@ -123,17 +123,18 @@ class VolumeControlInputDescriptor { mVolumeInputs[id].mGainSettingsMaxSetting = gainMax; } void setState(int id, int gainValue, int gainMode, int mute) { void setState(int id, int gainSetting, int mute, int gainMode) { if (!isValidId(id)) return; Descriptor desc = mVolumeInputs[id]; if (gainValue > desc.mGainSettingsMaxSetting || gainValue < desc.mGainSettingsMinSetting) { Log.e(TAG, "Request fail. Illegal gainValue argument: " + gainValue); if (gainSetting > desc.mGainSettingsMaxSetting || gainSetting < desc.mGainSettingsMinSetting) { Log.e(TAG, "Request fail. Illegal gainSetting argument: " + gainSetting); return; } desc.mGainValue = gainValue; desc.mGainSetting = gainSetting; desc.mGainMode = gainMode; desc.mMute = mute; } Loading @@ -145,7 +146,7 @@ class VolumeControlInputDescriptor { ProfileService.println(sb, " description: " + desc.mDescription); ProfileService.println(sb, " type: " + desc.mType); ProfileService.println(sb, " status: " + desc.mStatus); ProfileService.println(sb, " gainValue: " + desc.mGainValue); ProfileService.println(sb, " gainSetting: " + desc.mGainSetting); ProfileService.println(sb, " gainMode: " + desc.mGainMode); ProfileService.println(sb, " mute: " + desc.mMute); ProfileService.println(sb, " units:" + desc.mGainSettingsUnits); Loading
android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java 0 → 100644 +208 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.vc; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED; import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED; import static java.util.Objects.requireNonNull; import android.bluetooth.BluetoothDevice; import android.util.Log; import com.android.bluetooth.btservice.AdapterService; import com.android.internal.annotations.VisibleForTesting; class VolumeControlNativeCallback { private static final String TAG = VolumeControlNativeCallback.class.getSimpleName(); private final AdapterService mAdapterService; private final VolumeControlService mVolumeControlService; VolumeControlNativeCallback( AdapterService adapterService, VolumeControlService volumeControlService) { mAdapterService = requireNonNull(adapterService); mVolumeControlService = requireNonNull(volumeControlService); } private BluetoothDevice getDevice(byte[] address) { return mAdapterService.getDeviceFromByte(address); } @VisibleForTesting void onConnectionStateChanged(int state, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = state; Log.d(TAG, "onConnectionStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onVolumeStateChanged( int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = -1; event.valueInt2 = volume; event.valueInt3 = flags; event.valueBool1 = mute; event.valueBool2 = isAutonomous; Log.d(TAG, "onVolumeStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED); event.device = null; event.valueInt1 = groupId; event.valueInt2 = volume; event.valueBool1 = mute; event.valueBool2 = isAutonomous; Log.d(TAG, "onGroupVolumeStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_DEVICE_AVAILABLE); event.device = getDevice(address); event.valueInt1 = numOfExternalOutputs; event.valueInt2 = numOfExternalInputs; Log.d(TAG, "onDeviceAvailable: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED); event.device = getDevice(address); event.valueInt1 = externalOutputId; event.valueInt2 = offset; Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED); event.device = getDevice(address); event.valueInt1 = externalOutputId; event.valueInt2 = location; Log.d(TAG, "onExtAudioOutLocationChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED); event.device = getDevice(address); event.valueInt1 = externalOutputId; event.valueString1 = descr; Log.d(TAG, "onExtAudioOutLocationChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInStateChanged( int externalInputId, int gainSetting, int mute, int gainMode, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = gainSetting; event.valueInt3 = gainMode; event.valueInt4 = mute; Log.d(TAG, "onExtAudioInStateChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInStatusChanged(int externalInputId, int status, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = status; Log.d(TAG, "onExtAudioInStatusChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInTypeChanged(int externalInputId, int type, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = type; Log.d(TAG, "onExtAudioInTypeChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInDescriptionChanged(int externalInputId, String descr, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueString1 = descr; Log.d(TAG, "onExtAudioInDescriptionChanged: " + event); mVolumeControlService.messageFromNative(event); } @VisibleForTesting void onExtAudioInGainPropsChanged( int externalInputId, int unit, int min, int max, byte[] address) { VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED); event.device = getDevice(address); event.valueInt1 = externalInputId; event.valueInt2 = unit; event.valueInt3 = min; event.valueInt4 = max; Log.d(TAG, "onExtAudioInGainPropsChanged: " + event); mVolumeControlService.messageFromNative(event); } }