Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.hardware.soundtrigger; |
| 18 | |
Nicholas Ambur | 38027cd | 2019-12-16 00:06:19 -0800 | [diff] [blame] | 19 | import android.annotation.Nullable; |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 20 | import android.media.AudioFormat; |
| 21 | import android.media.audio.common.AudioConfig; |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 22 | import android.media.soundtrigger_middleware.AudioCapabilities; |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 23 | import android.media.soundtrigger_middleware.ConfidenceLevel; |
| 24 | import android.media.soundtrigger_middleware.ModelParameterRange; |
| 25 | import android.media.soundtrigger_middleware.Phrase; |
| 26 | import android.media.soundtrigger_middleware.PhraseRecognitionEvent; |
| 27 | import android.media.soundtrigger_middleware.PhraseRecognitionExtra; |
| 28 | import android.media.soundtrigger_middleware.PhraseSoundModel; |
| 29 | import android.media.soundtrigger_middleware.RecognitionConfig; |
| 30 | import android.media.soundtrigger_middleware.RecognitionEvent; |
| 31 | import android.media.soundtrigger_middleware.RecognitionMode; |
| 32 | import android.media.soundtrigger_middleware.SoundModel; |
| 33 | import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor; |
| 34 | import android.media.soundtrigger_middleware.SoundTriggerModuleProperties; |
Ytai Ben-Tsvi | d5065ba | 2020-02-27 15:36:05 -0800 | [diff] [blame] | 35 | import android.os.SharedMemory; |
| 36 | import android.system.ErrnoException; |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 37 | |
Ytai Ben-Tsvi | d5065ba | 2020-02-27 15:36:05 -0800 | [diff] [blame] | 38 | import java.io.FileDescriptor; |
| 39 | import java.nio.ByteBuffer; |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 40 | import java.util.Arrays; |
| 41 | import java.util.UUID; |
| 42 | |
| 43 | /** @hide */ |
| 44 | class ConversionUtil { |
| 45 | public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor( |
| 46 | SoundTriggerModuleDescriptor aidlDesc) { |
| 47 | SoundTriggerModuleProperties properties = aidlDesc.properties; |
| 48 | return new SoundTrigger.ModuleProperties( |
| 49 | aidlDesc.handle, |
| 50 | properties.implementor, |
| 51 | properties.description, |
| 52 | properties.uuid, |
| 53 | properties.version, |
Nicholas Ambur | 38027cd | 2019-12-16 00:06:19 -0800 | [diff] [blame] | 54 | properties.supportedModelArch, |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 55 | properties.maxSoundModels, |
| 56 | properties.maxKeyPhrases, |
| 57 | properties.maxUsers, |
| 58 | aidl2apiRecognitionModes(properties.recognitionModes), |
| 59 | properties.captureTransition, |
| 60 | properties.maxBufferMs, |
| 61 | properties.concurrentCapture, |
| 62 | properties.powerConsumptionMw, |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 63 | properties.triggerInEvent, |
| 64 | aidl2apiAudioCapabilities(properties.audioCapabilities) |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 65 | ); |
| 66 | } |
| 67 | |
| 68 | public static int aidl2apiRecognitionModes(int aidlModes) { |
| 69 | int result = 0; |
| 70 | if ((aidlModes & RecognitionMode.VOICE_TRIGGER) != 0) { |
| 71 | result |= SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER; |
| 72 | } |
| 73 | if ((aidlModes & RecognitionMode.USER_IDENTIFICATION) != 0) { |
| 74 | result |= SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION; |
| 75 | } |
| 76 | if ((aidlModes & RecognitionMode.USER_AUTHENTICATION) != 0) { |
| 77 | result |= SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION; |
| 78 | } |
| 79 | if ((aidlModes & RecognitionMode.GENERIC_TRIGGER) != 0) { |
| 80 | result |= SoundTrigger.RECOGNITION_MODE_GENERIC; |
| 81 | } |
| 82 | return result; |
| 83 | } |
| 84 | |
| 85 | public static int api2aidlRecognitionModes(int apiModes) { |
| 86 | int result = 0; |
| 87 | if ((apiModes & SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER) != 0) { |
| 88 | result |= RecognitionMode.VOICE_TRIGGER; |
| 89 | } |
| 90 | if ((apiModes & SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION) != 0) { |
| 91 | result |= RecognitionMode.USER_IDENTIFICATION; |
| 92 | } |
| 93 | if ((apiModes & SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION) != 0) { |
| 94 | result |= RecognitionMode.USER_AUTHENTICATION; |
| 95 | } |
| 96 | if ((apiModes & SoundTrigger.RECOGNITION_MODE_GENERIC) != 0) { |
| 97 | result |= RecognitionMode.GENERIC_TRIGGER; |
| 98 | } |
| 99 | return result; |
| 100 | } |
| 101 | |
| 102 | |
| 103 | public static SoundModel api2aidlGenericSoundModel(SoundTrigger.GenericSoundModel apiModel) { |
| 104 | return api2aidlSoundModel(apiModel); |
| 105 | } |
| 106 | |
| 107 | public static SoundModel api2aidlSoundModel(SoundTrigger.SoundModel apiModel) { |
| 108 | SoundModel aidlModel = new SoundModel(); |
| 109 | aidlModel.type = apiModel.type; |
| 110 | aidlModel.uuid = api2aidlUuid(apiModel.uuid); |
| 111 | aidlModel.vendorUuid = api2aidlUuid(apiModel.vendorUuid); |
Ytai Ben-Tsvi | d5065ba | 2020-02-27 15:36:05 -0800 | [diff] [blame] | 112 | aidlModel.data = byteArrayToSharedMemory(apiModel.data, "SoundTrigger SoundModel"); |
| 113 | aidlModel.dataSize = apiModel.data.length; |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 114 | return aidlModel; |
| 115 | } |
| 116 | |
| 117 | public static String api2aidlUuid(UUID apiUuid) { |
| 118 | return apiUuid.toString(); |
| 119 | } |
| 120 | |
| 121 | public static PhraseSoundModel api2aidlPhraseSoundModel( |
| 122 | SoundTrigger.KeyphraseSoundModel apiModel) { |
| 123 | PhraseSoundModel aidlModel = new PhraseSoundModel(); |
| 124 | aidlModel.common = api2aidlSoundModel(apiModel); |
| 125 | aidlModel.phrases = new Phrase[apiModel.keyphrases.length]; |
| 126 | for (int i = 0; i < apiModel.keyphrases.length; ++i) { |
| 127 | aidlModel.phrases[i] = api2aidlPhrase(apiModel.keyphrases[i]); |
| 128 | } |
| 129 | return aidlModel; |
| 130 | } |
| 131 | |
| 132 | public static Phrase api2aidlPhrase(SoundTrigger.Keyphrase apiPhrase) { |
| 133 | Phrase aidlPhrase = new Phrase(); |
| 134 | aidlPhrase.id = apiPhrase.id; |
| 135 | aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.recognitionModes); |
| 136 | aidlPhrase.users = Arrays.copyOf(apiPhrase.users, apiPhrase.users.length); |
Nicholas Ambur | ef84fc4 | 2020-01-14 20:28:37 -0800 | [diff] [blame] | 137 | aidlPhrase.locale = apiPhrase.locale.toLanguageTag(); |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 138 | aidlPhrase.text = apiPhrase.text; |
| 139 | return aidlPhrase; |
| 140 | } |
| 141 | |
| 142 | public static RecognitionConfig api2aidlRecognitionConfig( |
| 143 | SoundTrigger.RecognitionConfig apiConfig) { |
| 144 | RecognitionConfig aidlConfig = new RecognitionConfig(); |
| 145 | aidlConfig.captureRequested = apiConfig.captureRequested; |
| 146 | // apiConfig.allowMultipleTriggers is ignored by the lower layers. |
| 147 | aidlConfig.phraseRecognitionExtras = |
| 148 | new PhraseRecognitionExtra[apiConfig.keyphrases.length]; |
| 149 | for (int i = 0; i < apiConfig.keyphrases.length; ++i) { |
| 150 | aidlConfig.phraseRecognitionExtras[i] = api2aidlPhraseRecognitionExtra( |
| 151 | apiConfig.keyphrases[i]); |
| 152 | } |
| 153 | aidlConfig.data = Arrays.copyOf(apiConfig.data, apiConfig.data.length); |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 154 | aidlConfig.audioCapabilities = api2aidlAudioCapabilities(apiConfig.audioCapabilities); |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 155 | return aidlConfig; |
| 156 | } |
| 157 | |
| 158 | public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra( |
| 159 | SoundTrigger.KeyphraseRecognitionExtra apiExtra) { |
| 160 | PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra(); |
| 161 | aidlExtra.id = apiExtra.id; |
| 162 | aidlExtra.recognitionModes = api2aidlRecognitionModes(apiExtra.recognitionModes); |
| 163 | aidlExtra.confidenceLevel = apiExtra.coarseConfidenceLevel; |
| 164 | aidlExtra.levels = new ConfidenceLevel[apiExtra.confidenceLevels.length]; |
| 165 | for (int i = 0; i < apiExtra.confidenceLevels.length; ++i) { |
| 166 | aidlExtra.levels[i] = api2aidlConfidenceLevel(apiExtra.confidenceLevels[i]); |
| 167 | } |
| 168 | return aidlExtra; |
| 169 | } |
| 170 | |
| 171 | public static SoundTrigger.KeyphraseRecognitionExtra aidl2apiPhraseRecognitionExtra( |
| 172 | PhraseRecognitionExtra aidlExtra) { |
| 173 | SoundTrigger.ConfidenceLevel[] apiLevels = |
| 174 | new SoundTrigger.ConfidenceLevel[aidlExtra.levels.length]; |
| 175 | for (int i = 0; i < aidlExtra.levels.length; ++i) { |
| 176 | apiLevels[i] = aidl2apiConfidenceLevel(aidlExtra.levels[i]); |
| 177 | } |
| 178 | return new SoundTrigger.KeyphraseRecognitionExtra(aidlExtra.id, |
| 179 | aidl2apiRecognitionModes(aidlExtra.recognitionModes), |
| 180 | aidlExtra.confidenceLevel, apiLevels); |
| 181 | } |
| 182 | |
| 183 | public static ConfidenceLevel api2aidlConfidenceLevel( |
| 184 | SoundTrigger.ConfidenceLevel apiLevel) { |
| 185 | ConfidenceLevel aidlLevel = new ConfidenceLevel(); |
| 186 | aidlLevel.levelPercent = apiLevel.confidenceLevel; |
| 187 | aidlLevel.userId = apiLevel.userId; |
| 188 | return aidlLevel; |
| 189 | } |
| 190 | |
| 191 | public static SoundTrigger.ConfidenceLevel aidl2apiConfidenceLevel( |
| 192 | ConfidenceLevel apiLevel) { |
| 193 | return new SoundTrigger.ConfidenceLevel(apiLevel.userId, apiLevel.levelPercent); |
| 194 | } |
| 195 | |
| 196 | public static SoundTrigger.RecognitionEvent aidl2apiRecognitionEvent( |
| 197 | int modelHandle, RecognitionEvent aidlEvent) { |
| 198 | return new SoundTrigger.GenericRecognitionEvent( |
| 199 | aidlEvent.status, |
| 200 | modelHandle, aidlEvent.captureAvailable, aidlEvent.captureSession, |
| 201 | aidlEvent.captureDelayMs, aidlEvent.capturePreambleMs, aidlEvent.triggerInData, |
| 202 | aidl2apiAudioFormat(aidlEvent.audioConfig), aidlEvent.data); |
| 203 | } |
| 204 | |
| 205 | public static SoundTrigger.RecognitionEvent aidl2apiPhraseRecognitionEvent( |
| 206 | int modelHandle, |
| 207 | PhraseRecognitionEvent aidlEvent) { |
| 208 | SoundTrigger.KeyphraseRecognitionExtra[] apiExtras = |
| 209 | new SoundTrigger.KeyphraseRecognitionExtra[aidlEvent.phraseExtras.length]; |
| 210 | for (int i = 0; i < aidlEvent.phraseExtras.length; ++i) { |
| 211 | apiExtras[i] = aidl2apiPhraseRecognitionExtra(aidlEvent.phraseExtras[i]); |
| 212 | } |
| 213 | return new SoundTrigger.KeyphraseRecognitionEvent(aidlEvent.common.status, modelHandle, |
| 214 | aidlEvent.common.captureAvailable, |
| 215 | aidlEvent.common.captureSession, aidlEvent.common.captureDelayMs, |
| 216 | aidlEvent.common.capturePreambleMs, aidlEvent.common.triggerInData, |
| 217 | aidl2apiAudioFormat(aidlEvent.common.audioConfig), aidlEvent.common.data, |
| 218 | apiExtras); |
| 219 | } |
| 220 | |
| 221 | public static AudioFormat aidl2apiAudioFormat(AudioConfig audioConfig) { |
| 222 | AudioFormat.Builder apiBuilder = new AudioFormat.Builder(); |
| 223 | apiBuilder.setSampleRate(audioConfig.sampleRateHz); |
| 224 | apiBuilder.setChannelMask(aidl2apiChannelInMask(audioConfig.channelMask)); |
| 225 | apiBuilder.setEncoding(aidl2apiEncoding(audioConfig.format)); |
| 226 | return apiBuilder.build(); |
| 227 | } |
| 228 | |
| 229 | public static int aidl2apiEncoding(int aidlFormat) { |
| 230 | switch (aidlFormat) { |
| 231 | case android.media.audio.common.AudioFormat.PCM |
| 232 | | android.media.audio.common.AudioFormat.PCM_SUB_16_BIT: |
| 233 | return AudioFormat.ENCODING_PCM_16BIT; |
| 234 | |
| 235 | case android.media.audio.common.AudioFormat.PCM |
| 236 | | android.media.audio.common.AudioFormat.PCM_SUB_8_BIT: |
| 237 | return AudioFormat.ENCODING_PCM_8BIT; |
| 238 | |
| 239 | case android.media.audio.common.AudioFormat.PCM |
| 240 | | android.media.audio.common.AudioFormat.PCM_SUB_FLOAT: |
| 241 | case android.media.audio.common.AudioFormat.PCM |
| 242 | | android.media.audio.common.AudioFormat.PCM_SUB_8_24_BIT: |
| 243 | case android.media.audio.common.AudioFormat.PCM |
| 244 | | android.media.audio.common.AudioFormat.PCM_SUB_24_BIT_PACKED: |
| 245 | case android.media.audio.common.AudioFormat.PCM |
| 246 | | android.media.audio.common.AudioFormat.PCM_SUB_32_BIT: |
| 247 | return AudioFormat.ENCODING_PCM_FLOAT; |
| 248 | |
| 249 | case android.media.audio.common.AudioFormat.AC3: |
| 250 | return AudioFormat.ENCODING_AC3; |
| 251 | |
| 252 | case android.media.audio.common.AudioFormat.E_AC3: |
| 253 | return AudioFormat.ENCODING_E_AC3; |
| 254 | |
| 255 | case android.media.audio.common.AudioFormat.DTS: |
| 256 | return AudioFormat.ENCODING_DTS; |
| 257 | |
| 258 | case android.media.audio.common.AudioFormat.DTS_HD: |
| 259 | return AudioFormat.ENCODING_DTS_HD; |
| 260 | |
| 261 | case android.media.audio.common.AudioFormat.MP3: |
| 262 | return AudioFormat.ENCODING_MP3; |
| 263 | |
| 264 | case android.media.audio.common.AudioFormat.AAC |
| 265 | | android.media.audio.common.AudioFormat.AAC_SUB_LC: |
| 266 | return AudioFormat.ENCODING_AAC_LC; |
| 267 | |
| 268 | case android.media.audio.common.AudioFormat.AAC |
| 269 | | android.media.audio.common.AudioFormat.AAC_SUB_HE_V1: |
| 270 | return AudioFormat.ENCODING_AAC_HE_V1; |
| 271 | |
| 272 | case android.media.audio.common.AudioFormat.AAC |
| 273 | | android.media.audio.common.AudioFormat.AAC_SUB_HE_V2: |
| 274 | return AudioFormat.ENCODING_AAC_HE_V2; |
| 275 | |
| 276 | case android.media.audio.common.AudioFormat.IEC61937: |
| 277 | return AudioFormat.ENCODING_IEC61937; |
| 278 | |
| 279 | case android.media.audio.common.AudioFormat.DOLBY_TRUEHD: |
| 280 | return AudioFormat.ENCODING_DOLBY_TRUEHD; |
| 281 | |
| 282 | case android.media.audio.common.AudioFormat.AAC |
| 283 | | android.media.audio.common.AudioFormat.AAC_SUB_ELD: |
| 284 | return AudioFormat.ENCODING_AAC_ELD; |
| 285 | |
| 286 | case android.media.audio.common.AudioFormat.AAC |
| 287 | | android.media.audio.common.AudioFormat.AAC_SUB_XHE: |
| 288 | return AudioFormat.ENCODING_AAC_XHE; |
| 289 | |
| 290 | case android.media.audio.common.AudioFormat.AC4: |
| 291 | return AudioFormat.ENCODING_AC4; |
| 292 | |
| 293 | case android.media.audio.common.AudioFormat.E_AC3 |
| 294 | | android.media.audio.common.AudioFormat.E_AC3_SUB_JOC: |
| 295 | return AudioFormat.ENCODING_E_AC3_JOC; |
| 296 | |
| 297 | case android.media.audio.common.AudioFormat.MAT: |
| 298 | case android.media.audio.common.AudioFormat.MAT |
| 299 | | android.media.audio.common.AudioFormat.MAT_SUB_1_0: |
| 300 | case android.media.audio.common.AudioFormat.MAT |
| 301 | | android.media.audio.common.AudioFormat.MAT_SUB_2_0: |
| 302 | case android.media.audio.common.AudioFormat.MAT |
| 303 | | android.media.audio.common.AudioFormat.MAT_SUB_2_1: |
| 304 | return AudioFormat.ENCODING_DOLBY_MAT; |
| 305 | |
| 306 | case android.media.audio.common.AudioFormat.DEFAULT: |
| 307 | return AudioFormat.ENCODING_DEFAULT; |
| 308 | |
| 309 | default: |
| 310 | return AudioFormat.ENCODING_INVALID; |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | public static int api2aidlModelParameter(int apiParam) { |
| 315 | switch (apiParam) { |
| 316 | case ModelParams.THRESHOLD_FACTOR: |
| 317 | return android.media.soundtrigger_middleware.ModelParameter.THRESHOLD_FACTOR; |
| 318 | default: |
| 319 | return android.media.soundtrigger_middleware.ModelParameter.INVALID; |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | public static int aidl2apiChannelInMask(int aidlMask) { |
| 324 | // We're assuming AudioFormat.CHANNEL_IN_* constants are kept in sync with |
| 325 | // android.media.audio.common.AudioChannelMask. |
| 326 | return aidlMask; |
| 327 | } |
| 328 | |
| 329 | public static SoundTrigger.ModelParamRange aidl2apiModelParameterRange( |
| 330 | @Nullable ModelParameterRange aidlRange) { |
| 331 | if (aidlRange == null) { |
| 332 | return null; |
| 333 | } |
| 334 | return new SoundTrigger.ModelParamRange(aidlRange.minInclusive, aidlRange.maxInclusive); |
| 335 | } |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 336 | |
| 337 | public static int aidl2apiAudioCapabilities(int aidlCapabilities) { |
| 338 | int result = 0; |
| 339 | if ((aidlCapabilities & AudioCapabilities.ECHO_CANCELLATION) != 0) { |
Nicholas Ambur | ce5cd84 | 2020-02-04 13:39:59 -0800 | [diff] [blame] | 340 | result |= SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_ECHO_CANCELLATION; |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 341 | } |
| 342 | if ((aidlCapabilities & AudioCapabilities.NOISE_SUPPRESSION) != 0) { |
Nicholas Ambur | ce5cd84 | 2020-02-04 13:39:59 -0800 | [diff] [blame] | 343 | result |= SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_NOISE_SUPPRESSION; |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 344 | } |
| 345 | return result; |
| 346 | } |
| 347 | |
| 348 | public static int api2aidlAudioCapabilities(int apiCapabilities) { |
| 349 | int result = 0; |
Nicholas Ambur | ce5cd84 | 2020-02-04 13:39:59 -0800 | [diff] [blame] | 350 | if ((apiCapabilities & SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_ECHO_CANCELLATION) |
| 351 | != 0) { |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 352 | result |= AudioCapabilities.ECHO_CANCELLATION; |
| 353 | } |
Nicholas Ambur | ce5cd84 | 2020-02-04 13:39:59 -0800 | [diff] [blame] | 354 | if ((apiCapabilities & SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_NOISE_SUPPRESSION) |
| 355 | != 0) { |
Nicholas Ambur | 7092a56 | 2019-12-16 11:18:55 -0800 | [diff] [blame] | 356 | result |= AudioCapabilities.NOISE_SUPPRESSION; |
| 357 | } |
| 358 | return result; |
| 359 | } |
Ytai Ben-Tsvi | d5065ba | 2020-02-27 15:36:05 -0800 | [diff] [blame] | 360 | |
| 361 | private static @Nullable FileDescriptor byteArrayToSharedMemory(byte[] data, String name) { |
| 362 | if (data.length == 0) { |
| 363 | return null; |
| 364 | } |
| 365 | |
| 366 | try { |
| 367 | SharedMemory shmem = SharedMemory.create(name != null ? name : "", data.length); |
| 368 | ByteBuffer buffer = shmem.mapReadWrite(); |
| 369 | buffer.put(data); |
| 370 | shmem.unmap(buffer); |
| 371 | return shmem.getFileDescriptor(); |
| 372 | } catch (ErrnoException e) { |
| 373 | throw new RuntimeException(e); |
| 374 | } |
| 375 | } |
Ytai Ben-Tsvi | 7d383d1 | 2019-11-25 12:47:40 -0800 | [diff] [blame] | 376 | } |