Merge changes I98336ac6,If48f80a0 into udc-dev
* changes: Add additional conversion to ST for testing Fix ConversionUtil AudioFormat construction
This commit is contained in:
@@ -34,14 +34,16 @@ import android.media.soundtrigger.RecognitionMode;
|
|||||||
import android.media.soundtrigger.SoundModel;
|
import android.media.soundtrigger.SoundModel;
|
||||||
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
|
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.system.ErrnoException;
|
||||||
import android.os.SharedMemory;
|
import android.os.SharedMemory;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
class ConversionUtil {
|
public class ConversionUtil {
|
||||||
public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor(
|
public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor(
|
||||||
SoundTriggerModuleDescriptor aidlDesc) {
|
SoundTriggerModuleDescriptor aidlDesc) {
|
||||||
Properties properties = aidlDesc.properties;
|
Properties properties = aidlDesc.properties;
|
||||||
@@ -140,6 +142,14 @@ class ConversionUtil {
|
|||||||
return aidlPhrase;
|
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(
|
public static RecognitionConfig api2aidlRecognitionConfig(
|
||||||
SoundTrigger.RecognitionConfig apiConfig) {
|
SoundTrigger.RecognitionConfig apiConfig) {
|
||||||
RecognitionConfig aidlConfig = new RecognitionConfig();
|
RecognitionConfig aidlConfig = new RecognitionConfig();
|
||||||
@@ -156,6 +166,21 @@ class ConversionUtil {
|
|||||||
return aidlConfig;
|
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(
|
public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra(
|
||||||
SoundTrigger.KeyphraseRecognitionExtra apiExtra) {
|
SoundTrigger.KeyphraseRecognitionExtra apiExtra) {
|
||||||
PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra();
|
PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra();
|
||||||
@@ -233,7 +258,11 @@ class ConversionUtil {
|
|||||||
if (audioConfig != null) {
|
if (audioConfig != null) {
|
||||||
return AidlConversion.aidl2api_AudioConfig_AudioFormat(audioConfig, isInput);
|
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) {
|
public static int api2aidlModelParameter(int apiParam) {
|
||||||
@@ -277,7 +306,7 @@ class ConversionUtil {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable ParcelFileDescriptor byteArrayToSharedMemory(byte[] data, String name) {
|
public static @Nullable ParcelFileDescriptor byteArrayToSharedMemory(byte[] data, String name) {
|
||||||
if (data.length == 0) {
|
if (data.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -294,4 +323,19 @@ class ConversionUtil {
|
|||||||
throw new RuntimeException(e);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1493,6 +1493,45 @@ public class SoundTrigger {
|
|||||||
+ Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
|
+ Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
|
||||||
+ ", audioCapabilities=" + Integer.toHexString(audioCapabilities) + "]";
|
+ ", 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,15 +16,33 @@
|
|||||||
|
|
||||||
package com.android.server.soundtrigger_middleware;
|
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.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import android.hardware.audio.common.V2_0.Uuid;
|
import android.hardware.audio.common.V2_0.Uuid;
|
||||||
|
import android.hardware.soundtrigger.SoundTrigger;
|
||||||
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class ConversionUtilTest {
|
public class ConversionUtilTest {
|
||||||
private static final String TAG = "ConversionUtilTest";
|
private static final String TAG = "ConversionUtilTest";
|
||||||
@@ -44,4 +62,54 @@ public class ConversionUtilTest {
|
|||||||
Uuid reconstructed = ConversionUtil.aidl2hidlUuid(aidl);
|
Uuid reconstructed = ConversionUtil.aidl2hidlUuid(aidl);
|
||||||
assertEquals(hidl, reconstructed);
|
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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user