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

Commit 3217999c authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Merge changes I98336ac6,If48f80a0 into udc-dev

* changes:
  Add additional conversion to ST for testing
  Fix ConversionUtil AudioFormat construction
parents 9c5c84ff 21c80c8e
Loading
Loading
Loading
Loading
+47 −3
Original line number Diff line number Diff line
@@ -34,14 +34,16 @@ import android.media.soundtrigger.RecognitionMode;
import android.media.soundtrigger.SoundModel;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.os.SharedMemory;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Locale;
import java.util.UUID;

/** @hide */
class ConversionUtil {
public class ConversionUtil {
    public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor(
            SoundTriggerModuleDescriptor aidlDesc) {
        Properties properties = aidlDesc.properties;
@@ -140,6 +142,14 @@ class ConversionUtil {
        return aidlPhrase;
    }

    public static SoundTrigger.Keyphrase aidl2apiPhrase(Phrase aidlPhrase) {
        return new SoundTrigger.Keyphrase(aidlPhrase.id,
                aidl2apiRecognitionModes(aidlPhrase.recognitionModes),
                new Locale.Builder().setLanguageTag(aidlPhrase.locale).build(),
                aidlPhrase.text,
                Arrays.copyOf(aidlPhrase.users, aidlPhrase.users.length));
    }

    public static RecognitionConfig api2aidlRecognitionConfig(
            SoundTrigger.RecognitionConfig apiConfig) {
        RecognitionConfig aidlConfig = new RecognitionConfig();
@@ -156,6 +166,21 @@ class ConversionUtil {
        return aidlConfig;
    }

    public static SoundTrigger.RecognitionConfig aidl2apiRecognitionConfig(
            RecognitionConfig aidlConfig) {
        var keyphrases =
            new SoundTrigger.KeyphraseRecognitionExtra[aidlConfig.phraseRecognitionExtras.length];
        int i = 0;
        for (var extras : aidlConfig.phraseRecognitionExtras) {
            keyphrases[i++] = aidl2apiPhraseRecognitionExtra(extras);
        }
        return new SoundTrigger.RecognitionConfig(aidlConfig.captureRequested,
                false /** allowMultipleTriggers **/,
                keyphrases,
                Arrays.copyOf(aidlConfig.data, aidlConfig.data.length),
                aidl2apiAudioCapabilities(aidlConfig.audioCapabilities));
    }

    public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra(
            SoundTrigger.KeyphraseRecognitionExtra apiExtra) {
        PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra();
@@ -233,7 +258,11 @@ class ConversionUtil {
        if (audioConfig != null) {
            return AidlConversion.aidl2api_AudioConfig_AudioFormat(audioConfig, isInput);
        }
        return new AudioFormat.Builder().build();
        return new AudioFormat.Builder()
            .setSampleRate(48000)
            .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
            .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
            .build();
    }

    public static int api2aidlModelParameter(int apiParam) {
@@ -277,7 +306,7 @@ class ConversionUtil {
        return result;
    }

    private static @Nullable ParcelFileDescriptor byteArrayToSharedMemory(byte[] data, String name) {
    public static @Nullable ParcelFileDescriptor byteArrayToSharedMemory(byte[] data, String name) {
        if (data.length == 0) {
            return null;
        }
@@ -294,4 +323,19 @@ class ConversionUtil {
            throw new RuntimeException(e);
        }
    }

    public static byte[] sharedMemoryToByteArray(@Nullable ParcelFileDescriptor pfd, int size) {
        if (pfd == null || size == 0) {
            return new byte[0];
        }
        try (SharedMemory mem = SharedMemory.fromFileDescriptor(pfd)) {
            ByteBuffer buffer = mem.mapReadOnly();
            byte[] data = new byte[(size > mem.getSize()) ? mem.getSize() : size];
            buffer.get(data);
            mem.unmap(buffer);
            return data;
        } catch (ErrnoException e) {
            throw new RuntimeException(e);
        }
    }
}
+39 −0
Original line number Diff line number Diff line
@@ -1493,6 +1493,45 @@ public class SoundTrigger {
                    + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
                    + ", audioCapabilities=" + Integer.toHexString(audioCapabilities) + "]";
        }

        @Override
        public final boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj instanceof RecognitionConfig))
                return false;
            RecognitionConfig other = (RecognitionConfig) obj;
            if (captureRequested != other.captureRequested) {
                return false;
            }
            if (allowMultipleTriggers != other.allowMultipleTriggers) {
                return false;
            }
            if (!Arrays.equals(keyphrases, other.keyphrases)) {
                return false;
            }
            if (!Arrays.equals(data, other.data)) {
                return false;
            }
            if (audioCapabilities != other.audioCapabilities) {
                return false;
            }
            return true;
        }

        @Override
        public final int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + (captureRequested ? 1 : 0);
            result = prime * result + (allowMultipleTriggers ? 1 : 0);
            result = prime * result + Arrays.hashCode(keyphrases);
            result = prime * result + Arrays.hashCode(data);
            result = prime * result + audioCapabilities;
            return result;
        }
    }

    /**
+68 −0
Original line number Diff line number Diff line
@@ -16,15 +16,33 @@

package com.android.server.soundtrigger_middleware;

import static android.hardware.soundtrigger.ConversionUtil.aidl2apiAudioFormatWithDefault;
import static android.hardware.soundtrigger.ConversionUtil.aidl2apiPhrase;
import static android.hardware.soundtrigger.ConversionUtil.aidl2apiRecognitionConfig;
import static android.hardware.soundtrigger.ConversionUtil.api2aidlPhrase;
import static android.hardware.soundtrigger.ConversionUtil.api2aidlRecognitionConfig;
import static android.hardware.soundtrigger.ConversionUtil.byteArrayToSharedMemory;
import static android.hardware.soundtrigger.ConversionUtil.sharedMemoryToByteArray;
import static android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel;
import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_GENERIC;
import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION;
import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import android.hardware.audio.common.V2_0.Uuid;
import android.hardware.soundtrigger.SoundTrigger;

import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Locale;

@RunWith(AndroidJUnit4.class)
public class ConversionUtilTest {
    private static final String TAG = "ConversionUtilTest";
@@ -44,4 +62,54 @@ public class ConversionUtilTest {
        Uuid reconstructed = ConversionUtil.aidl2hidlUuid(aidl);
        assertEquals(hidl, reconstructed);
    }

    @Test
    public void testDefaultAudioFormatConstruction() {
        // This method should generate a real format when passed null
        final var format = aidl2apiAudioFormatWithDefault(
                null /** exercise default **/,
                true /** isInput **/
                );
        assertNotNull(format);
    }

    @Test
    public void testRecognitionConfigRoundTrip() {
        final int flags = SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_ECHO_CANCELLATION
                | SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_NOISE_SUPPRESSION;
        final var data = new byte[] {0x11, 0x22};
        final var keyphrases = new SoundTrigger.KeyphraseRecognitionExtra[2];
        keyphrases[0] = new SoundTrigger.KeyphraseRecognitionExtra(99,
                RECOGNITION_MODE_VOICE_TRIGGER | RECOGNITION_MODE_USER_IDENTIFICATION, 13,
                    new ConfidenceLevel[] {new ConfidenceLevel(9999, 50),
                                           new ConfidenceLevel(5000, 80)});
        keyphrases[1] = new SoundTrigger.KeyphraseRecognitionExtra(101,
                RECOGNITION_MODE_GENERIC, 8, new ConfidenceLevel[] {
                    new ConfidenceLevel(7777, 30),
                    new ConfidenceLevel(2222, 60)});

        var apiconfig = new SoundTrigger.RecognitionConfig(true, false /** must be false **/,
                keyphrases, data, flags);
        assertEquals(apiconfig, aidl2apiRecognitionConfig(api2aidlRecognitionConfig(apiconfig)));
    }

    @Test
    public void testByteArraySharedMemRoundTrip() {
        final var data = new byte[] { 0x11, 0x22, 0x33, 0x44,
                (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef };
        assertArrayEquals(data, sharedMemoryToByteArray(byteArrayToSharedMemory(data, "name"),
                    10000000));

    }

    @Test
    public void testPhraseRoundTrip() {
        final var users = new int[] {10001, 10002};
        final var apiphrase = new SoundTrigger.Keyphrase(17 /** id **/,
                RECOGNITION_MODE_VOICE_TRIGGER | RECOGNITION_MODE_USER_AUTHENTICATION,
                Locale.forLanguageTag("no_NO"),
                "Hello Android", /** keyphrase **/
                users);
        assertEquals(apiphrase, aidl2apiPhrase(api2aidlPhrase(apiphrase)));
    }
}