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

Commit 47a96400 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I7b0a2840,Id5ddfa65,I97e34389,I0decbb7f into main

* changes:
  AICS: Check mute value and update to int type
  AICS: Simplify VolumeControlInputDescriptor usage
  Aics: shift ids to start at 0
  VCP: silence gmock warning in test
parents 8bb04d1d ffb0d7f0
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -218,7 +218,7 @@ public:
  }

  void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val,
                                uint8_t gain_mode, bool mute) override {
                                uint8_t gain_mode, uint8_t mute) override {
    log::info("");

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -237,7 +237,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, (jboolean)mute, addr.get());
                                 (jint)gain_val, (jint)gain_mode, (jint)mute, addr.get());
  }

  void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
@@ -893,7 +893,7 @@ int register_com_android_bluetooth_vc(JNIEnv* env) {
          {"onExtAudioOutLocationChanged", "(II[B)V", &method_onExtAudioOutLocationChanged},
          {"onExtAudioOutDescriptionChanged", "(ILjava/lang/String;[B)V",
           &method_onExtAudioOutDescriptionChanged},
          {"onExtAudioInStateChanged", "(IIIZ[B)V", &method_onExtAudioInStateChanged},
          {"onExtAudioInStateChanged", "(IIII[B)V", &method_onExtAudioInStateChanged},
          {"onExtAudioInStatusChanged", "(II[B)V", &method_onExtAudioInStatusChanged},
          {"onExtAudioInTypeChanged", "(II[B)V", &method_onExtAudioInTypeChanged},
          {"onExtAudioInGainPropsChanged", "(IIII[B)V", &method_onExtAudioInGainPropsChanged},
+69 −138
Original line number Diff line number Diff line
@@ -16,56 +16,47 @@

package com.android.bluetooth.vc;

import android.bluetooth.BluetoothVolumeControl;
import android.util.Log;

import com.android.bluetooth.btservice.ProfileService;

import java.util.HashMap;
import java.util.Map;

class VolumeControlInputDescriptor {
    private static final String TAG = "VolumeControlInputDescriptor";
    final Map<Integer, Descriptor> mVolumeInputs = new HashMap<>();

    public static final int AUDIO_INPUT_TYPE_UNSPECIFIED = 0x00;
    public static final int AUDIO_INPUT_TYPE_BLUETOOTH = 0x01;
    public static final int AUDIO_INPUT_TYPE_MICROPHONE = 0x02;
    public static final int AUDIO_INPUT_TYPE_ANALOG = 0x03;
    public static final int AUDIO_INPUT_TYPE_DIGITAL = 0x04;
    public static final int AUDIO_INPUT_TYPE_RADIO = 0x05;
    public static final int AUDIO_INPUT_TYPE_STREAMING = 0x06;
    public static final int AUDIO_INPUT_TYPE_AMBIENT = 0x07;
    private static final String TAG = VolumeControlInputDescriptor.class.getSimpleName();

    final Descriptor[] mVolumeInputs;

    VolumeControlInputDescriptor(int numberOfExternalInputs) {
        mVolumeInputs = new Descriptor[numberOfExternalInputs];
        // Stack delivers us number of audio inputs. ids are countinous from [0;n[
        for (int i = 0; i < numberOfExternalInputs; i++) {
            mVolumeInputs[i] = new Descriptor();
        }
    }

    private static class Descriptor {
        /* True when input is active, false otherwise */
        boolean mIsActive = false;
        int mStatus = 0; // AudioInputStatus.INACTIVE;

        /* Defined as in Assigned Numbers in the BluetoothVolumeControl.AUDIO_INPUT_TYPE_ */
        int mType = AUDIO_INPUT_TYPE_UNSPECIFIED;
        int mType = 0; // AudioInputType.UNSPECIFIED;

        int mGainValue = 0;

        /* As per AICS 1.0
         * 3.1.3. Gain_Mode field
         * The Gain_Mode field shall be set to a value that reflects whether gain modes are
         *  manual or automatic.
        /* See AICS 1.0 - 3.1.3. Gain_Mode field
         * The Gain_Mode field shall be set to a value that reflects whether gain modes are manual
         * or automatic.
         * - Manual Only, the server allows only manual gain.
         * - Automatic Only, the server allows only automatic gain.
         *
         * If the Gain_Mode field value is Manual Only, the server allows only manual gain.
         * If the Gain_Mode field is Automatic Only, the server allows only automatic gain.
         *
         * For all other Gain_Mode field values, the server allows switchable
         * automatic/manual gain.
         * For all other Gain_Mode field values, the server allows switchable automatic/manual gain.
         */
        int mGainMode = 0;

        boolean mIsMute = false;
        int mMute = 2; // DISABLED

        /* As per AICS 1.0
         * The Gain_Setting (mGainValue) 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.
        /* See AICS 1.0
         * The Gain_Setting (mGainValue) 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.
         */
        int mGainSettingsUnits = 0;

@@ -76,150 +67,90 @@ class VolumeControlInputDescriptor {
    }

    int size() {
        return mVolumeInputs.size();
        return mVolumeInputs.length;
    }

    void add(int id) {
        if (!mVolumeInputs.containsKey(id)) {
            mVolumeInputs.put(id, new Descriptor());
        }
    }

    boolean setActive(int id, boolean active) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "setActive, Id " + id + " is unknown");
    private boolean isValidId(int id) {
        if (id >= size() || id < 0) {
            Log.e(TAG, "Request fail. Illegal id argument: " + id);
            return false;
        }
        desc.mIsActive = active;
        return true;
    }

    boolean isActive(int id) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "isActive, Id " + id + " is unknown");
            return false;
        }
        return desc.mIsActive;
    }

    boolean setDescription(int id, String description) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "setDescription, Id " + id + " is unknown");
            return false;
        }
        desc.mDescription = description;
        return true;
    void setStatus(int id, int status) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].mStatus = status;
    }

    String getDescription(int id) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "getDescription, Id " + id + " is unknown");
            return null;
        }
        return desc.mDescription;
    int getStatus(int id) {
        if (!isValidId(id)) return 0; // AudioInputStatus.INACTIVE;
        return mVolumeInputs[id].mStatus;
    }

    boolean setType(int id, int type) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "setType, Id " + id + " is unknown");
            return false;
    void setDescription(int id, String description) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].mDescription = description;
    }

        if (type > AUDIO_INPUT_TYPE_AMBIENT) {
            Log.e(TAG, "setType, Type " + type + "for id " + id + " is invalid");
            return false;
    String getDescription(int id) {
        if (!isValidId(id)) return null;
        return mVolumeInputs[id].mDescription;
    }

        desc.mType = type;
        return true;
    void setType(int id, int type) {
        if (!isValidId(id)) return;
        mVolumeInputs[id].mType = type;
    }

    int getType(int id) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "getType, Id " + id + " is unknown");
            return AUDIO_INPUT_TYPE_UNSPECIFIED;
        }
        return desc.mType;
        if (!isValidId(id)) return 0; // AudioInputType.UNSPECIFIED;
        return mVolumeInputs[id].mType;
    }

    int getGain(int id) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "getGain, Id " + id + " is unknown");
            return 0;
        }
        return desc.mGainValue;
    }

    boolean isMuted(int id) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "isMuted, Id " + id + " is unknown");
            return false;
        }
        return desc.mIsMute;
        if (!isValidId(id)) return 0;
        return mVolumeInputs[id].mGainValue;
    }

    boolean setPropSettings(int id, int gainUnit, int gainMin, int gainMax) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "setPropSettings, Id " + id + " is unknown");
            return false;
    int getMute(int id) {
        if (!isValidId(id)) return 2; // MuteField.DISABLED
        return mVolumeInputs[id].mMute;
    }

        desc.mGainSettingsUnits = gainUnit;
        desc.mGainSettingsMinSetting = gainMin;
        desc.mGainSettingsMaxSetting = gainMax;
    void setPropSettings(int id, int gainUnit, int gainMin, int gainMax) {
        if (!isValidId(id)) return;

        return true;
        mVolumeInputs[id].mGainSettingsUnits = gainUnit;
        mVolumeInputs[id].mGainSettingsMinSetting = gainMin;
        mVolumeInputs[id].mGainSettingsMaxSetting = gainMax;
    }

    boolean setState(int id, int gainValue, int gainMode, boolean mute) {
        Descriptor desc = mVolumeInputs.get(id);
        if (desc == null) {
            Log.e(TAG, "Id " + id + " is unknown");
            return false;
        }
    void setState(int id, int gainValue, int gainMode, int mute) {
        if (!isValidId(id)) return;

        Descriptor desc = mVolumeInputs[id];

        if (gainValue > desc.mGainSettingsMaxSetting || gainValue < desc.mGainSettingsMinSetting) {
            Log.e(TAG, "Invalid gainValue " + gainValue);
            return false;
            Log.e(TAG, "Request fail. Illegal gainValue argument: " + gainValue);
            return;
        }

        desc.mGainValue = gainValue;
        desc.mGainMode = gainMode;
        desc.mIsMute = mute;

        return true;
    }

    void remove(int id) {
        Log.d(TAG, "remove, id: " + id);
        mVolumeInputs.remove(id);
    }

    void clear() {
        Log.d(TAG, "clear all inputs");
        mVolumeInputs.clear();
        desc.mMute = mute;
    }

    void dump(StringBuilder sb) {
        for (Map.Entry<Integer, Descriptor> entry : mVolumeInputs.entrySet()) {
            Descriptor desc = entry.getValue();
            Integer id = entry.getKey();
            ProfileService.println(sb, "        id: " + id);
        for (int i = 0; i < mVolumeInputs.length; i++) {
            Descriptor desc = mVolumeInputs[i];
            ProfileService.println(sb, "      id: " + i);
            ProfileService.println(sb, "        description: " + desc.mDescription);
            ProfileService.println(sb, "        type: " + desc.mType);
            ProfileService.println(sb, "        isActive: " + desc.mIsActive);
            ProfileService.println(sb, "        status: " + desc.mStatus);
            ProfileService.println(sb, "        gainValue: " + desc.mGainValue);
            ProfileService.println(sb, "        gainMode: " + desc.mGainMode);
            ProfileService.println(sb, "        mute: " + desc.mIsMute);
            ProfileService.println(sb, "        mute: " + desc.mMute);
            ProfileService.println(sb, "        units:" + desc.mGainSettingsUnits);
            ProfileService.println(sb, "        minGain:" + desc.mGainSettingsMinSetting);
            ProfileService.println(sb, "        maxGain:" + desc.mGainSettingsMaxSetting);
+2 −2
Original line number Diff line number Diff line
@@ -454,7 +454,7 @@ public class VolumeControlNativeInterface {

    @VisibleForTesting
    void onExtAudioInStateChanged(
            int externalInputId, int gainValue, int gainMode, boolean mute, byte[] address) {
            int externalInputId, int gainValue, int gainMode, int mute, byte[] address) {
        VolumeControlStackEvent event =
                new VolumeControlStackEvent(
                        VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED);
@@ -462,7 +462,7 @@ public class VolumeControlNativeInterface {
        event.valueInt1 = externalInputId;
        event.valueInt2 = gainValue;
        event.valueInt3 = gainMode;
        event.valueBool1 = mute;
        event.valueInt4 = mute;

        Log.d(TAG, "onExtAudioInStateChanged: " + event);
        sendMessageToService(event);
+60 −93
Original line number Diff line number Diff line
@@ -935,23 +935,11 @@ public class VolumeControlService extends ProfileService {
    void handleExternalInputs(BluetoothDevice device, int numberOfExternalInputs) {
        if (numberOfExternalInputs == 0) {
            Log.i(TAG, "Volume offset not available");
            mAudioInputs.remove(device);
            return;
        }

        VolumeControlInputDescriptor inputs = mAudioInputs.get(device);
        if (inputs == null) {
            inputs = new VolumeControlInputDescriptor();
            mAudioInputs.put(device, inputs);
        } else if (inputs.size() != numberOfExternalInputs) {
            Log.i(TAG, "Number of inputs changed: ");
            inputs.clear();
        }

        /* Stack delivers us number of audio inputs.
         * Offset ids a countinous from 1 to numberOfExternalInputs*/
        for (int i = 1; i <= numberOfExternalInputs; i++) {
            inputs.add(i);
        }
        mAudioInputs.put(device, new VolumeControlInputDescriptor(numberOfExternalInputs));
    }

    void handleDeviceAvailable(
@@ -1034,134 +1022,113 @@ public class VolumeControlService extends ProfileService {
    }

    void handleDeviceExtInputStateChanged(
            BluetoothDevice device, int id, int gainValue, int gainMode, boolean mute) {
        Log.d(
                TAG,
                ("handleDeviceExtInputStateChanged, device: " + device)
                        + (" inputId: " + id)
            BluetoothDevice device, int id, int gainValue, int gainMode, int mute) {
        String logInfo =
                "handleDeviceExtInputStateChanged("
                        + ("device:" + device)
                        + (", id" + id)
                        + (" gainValue: " + gainValue)
                        + (" gainMode: " + gainMode)
                        + (" mute: " + mute));
                        + (" mute: " + mute)
                        + ")";

        VolumeControlInputDescriptor input = mAudioInputs.get(device);
        if (input == null) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputStateChanged, inputId: " + id)
                            + (" not found for device: " + device));
            Log.e(TAG, logInfo + " This device has no audio input control");
            return;
        }
        if (!input.setState(id, gainValue, gainMode, mute)) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputStateChanged, error while setting inputId: " + id)
                            + ("for: " + device));
        }

        Log.d(TAG, logInfo);
        input.setState(id, gainValue, gainMode, mute);
    }

    void handleDeviceExtInputStatusChanged(BluetoothDevice device, int id, int status) {
        Log.d(TAG, " device: " + device + " inputId: " + id + " status: " + status);
        String logInfo =
                "handleDeviceExtInputStatusChanged("
                        + ("device:" + device)
                        + (", id" + id)
                        + (", status" + status)
                        + ")";

        VolumeControlInputDescriptor input = mAudioInputs.get(device);
        if (input == null) {
            Log.e(TAG, " inputId: " + id + " not found for device: " + device);
            Log.e(TAG, logInfo + " This device has no audio input control");
            return;
        }

        /*
         * As per ACIS 1.0. Status
         * Inactive: 0x00
         * Active: 0x01
         */
        if (status > 1 || status < 0) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputStatusChanged, invalid status: " + status)
                            + (" for: " + device));
        if (status != 0 && status != 1) {
            Log.e(TAG, logInfo + ": Invalid status argument");
            return;
        }

        boolean active = (status == 0x01);
        if (!input.setActive(id, active)) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputStatusChanged, error while setting inputId: " + id)
                            + ("for: " + device));
        }
        Log.d(TAG, logInfo);
        input.setStatus(id, status);
    }

    void handleDeviceExtInputTypeChanged(BluetoothDevice device, int id, int type) {
        Log.d(
                TAG,
                ("handleDeviceExtInputTypeChanged, device: " + device)
                        + (" inputId: " + id)
                        + (" type: " + type));
        String logInfo =
                "handleDeviceExtInputTypeChanged("
                        + ("device:" + device)
                        + (", id" + id)
                        + (", type" + type)
                        + ")";

        VolumeControlInputDescriptor input = mAudioInputs.get(device);
        if (input == null) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputTypeChanged, inputId: " + id)
                            + (" not found for device: " + device));
            Log.e(TAG, logInfo + ": This device has no audio input control");
            return;
        }

        if (!input.setType(id, type)) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputTypeChanged, error while setting inputId: " + id)
                            + ("for: " + device));
        if (type > 7) { // AudioInputType.AMBIENT) {
            Log.e(TAG, logInfo + ": Invalid type argument");
            return;
        }

        Log.d(TAG, logInfo);
        input.setType(id, type);
    }

    void handleDeviceExtInputDescriptionChanged(
            BluetoothDevice device, int id, String description) {
        Log.d(
                TAG,
                ("handleDeviceExtInputDescriptionChanged, device: " + device)
                        + (" inputId: " + id)
                        + (" description: " + description));
        String logInfo =
                "handleDeviceExtInputDescriptionChanged("
                        + ("device:" + device)
                        + (", id" + id)
                        + (", description" + description)
                        + ")";

        VolumeControlInputDescriptor input = mAudioInputs.get(device);
        if (input == null) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputDescriptionChanged, inputId: " + id)
                            + (" not found for device: " + device));
            Log.e(TAG, logInfo + ": This device has no audio input control");
            return;
        }

        if (!input.setDescription(id, description)) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputDescriptionChanged, error while setting inputId: " + id)
                            + ("for: " + device));
        if (description == null) {
            Log.e(TAG, logInfo + ": Invalid description argument");
            return;
        }

        Log.d(TAG, logInfo);
        input.setDescription(id, description);
    }

    void handleDeviceExtInputGainPropsChanged(
            BluetoothDevice device, int id, int unit, int min, int max) {
        Log.d(
                TAG,
                ("handleDeviceExtInputGainPropsChanged, device: " + device)
                        + (" inputId: " + id)
                        + (" unit: " + unit + " min" + min + " max:" + max));
        String logInfo =
                "handleDeviceExtInputGainPropsChanged("
                        + ("device:" + device)
                        + (", id" + id)
                        + (" unit: " + unit + " min" + min + " max:" + max)
                        + ")";

        VolumeControlInputDescriptor input = mAudioInputs.get(device);
        if (input == null) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputGainPropsChanged, inputId: " + id)
                            + (" not found for device: " + device));
            Log.e(TAG, logInfo + ": This device has no audio input control");
            return;
        }

        if (!input.setPropSettings(id, unit, min, max)) {
            Log.e(
                    TAG,
                    ("handleDeviceExtInputGainPropsChanged, error while setting inputId: " + id)
                            + ("for: " + device));
        }
        Log.d(TAG, logInfo);
        input.setPropSettings(id, unit, min, max);
    }

    void messageFromNative(VolumeControlStackEvent stackEvent) {
@@ -1210,7 +1177,7 @@ public class VolumeControlService extends ProfileService {
                    stackEvent.valueInt1,
                    stackEvent.valueInt2,
                    stackEvent.valueInt3,
                    stackEvent.valueBool1);
                    stackEvent.valueInt4);
            return;
        }

+2 −1
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ public class VolumeControlStackEvent {
        switch (type) {
            case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED:
                return "{gain set max:" + value + "}";
            case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
                return "{mute:" + value + "}";
            default:
                break;
        }
@@ -168,7 +170,6 @@ public class VolumeControlStackEvent {
    private static String eventTypeValueBool1ToString(int type, boolean value) {
        switch (type) {
            case EVENT_TYPE_VOLUME_STATE_CHANGED:
            case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
                return "{muted:" + value + "}";
            default:
                break;
Loading