Merge "Naming consistency: MediaAnalytics to MediaMetrics"
diff --git a/apex/Android.bp b/apex/Android.bp
index 42a620b..73dc264 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -41,6 +41,8 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media-androidManifest",
+
+ legacy_android10_support: true,
}
apex {
@@ -76,6 +78,8 @@
// Use a custom AndroidManifest.xml used for API targeting.
androidManifest: ":com.android.media.swcodec-androidManifest",
+
+ legacy_android10_support: true,
}
prebuilt_etc {
diff --git a/camera/Android.bp b/camera/Android.bp
index b288bcf..ea7259a 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -85,6 +85,7 @@
"aidl/android/hardware/ICameraServiceProxy.aidl",
"aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl",
"aidl/android/hardware/camera2/ICameraDeviceUser.aidl",
+ "aidl/android/hardware/camera2/ICameraOfflineSession.aidl",
],
path: "aidl",
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 93549e0..cdb7ac3 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -17,6 +17,8 @@
package android.hardware.camera2;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.ICameraOfflineSession;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
@@ -177,4 +179,15 @@
* @return the currently applied system-wide audio restriction mode
*/
int getGlobalAudioRestriction();
+
+ /**
+ * Offline processing main entry point
+ *
+ * @param callbacks Object that will receive callbacks from offline session
+ * @param offlineOutputIds The ID of streams that needs to be preserved in offline session
+ *
+ * @return Offline session object.
+ */
+ ICameraOfflineSession switchToOffline(in ICameraDeviceCallbacks callbacks,
+ in Surface[] offlineOutputs);
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraOfflineSession.aidl b/camera/aidl/android/hardware/camera2/ICameraOfflineSession.aidl
new file mode 100644
index 0000000..ab030ab
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/ICameraOfflineSession.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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 android.hardware.camera2;
+
+ /** @hide */
+interface ICameraOfflineSession
+{
+ void disconnect();
+}
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 825f308..0652cbb 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -1311,7 +1311,7 @@
/**
* <p>List of the maximum number of regions that can be used for metering in
* auto-exposure (AE), auto-white balance (AWB), and auto-focus (AF);
- * this corresponds to the the maximum number of elements in
+ * this corresponds to the maximum number of elements in
* ACAMERA_CONTROL_AE_REGIONS, ACAMERA_CONTROL_AWB_REGIONS,
* and ACAMERA_CONTROL_AF_REGIONS.</p>
*
diff --git a/include/soundtrigger/ISoundTrigger.h b/include/soundtrigger/ISoundTrigger.h
deleted file mode 100644
index d628c05..0000000
--- a/include/soundtrigger/ISoundTrigger.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_HARDWARE_ISOUNDTRIGGER_H
-#define ANDROID_HARDWARE_ISOUNDTRIGGER_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class ISoundTrigger : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(SoundTrigger);
-
- virtual void detach() = 0;
-
- virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
- sound_model_handle_t *handle) = 0;
-
- virtual status_t unloadSoundModel(sound_model_handle_t handle) = 0;
-
- virtual status_t startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory) = 0;
- virtual status_t stopRecognition(sound_model_handle_t handle) = 0;
- virtual status_t getModelState(sound_model_handle_t handle) = 0;
- virtual status_t setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t value) = 0;
- virtual status_t getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t* value) = 0;
- virtual status_t queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSoundTrigger: public BnInterface<ISoundTrigger>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_H
diff --git a/include/soundtrigger/ISoundTriggerClient.h b/include/soundtrigger/ISoundTriggerClient.h
deleted file mode 100644
index 480429a..0000000
--- a/include/soundtrigger/ISoundTriggerClient.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
-#define ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class ISoundTriggerClient : public IInterface
-{
-public:
-
- DECLARE_META_INTERFACE(SoundTriggerClient);
-
- virtual void onRecognitionEvent(const sp<IMemory>& eventMemory) = 0;
-
- virtual void onSoundModelEvent(const sp<IMemory>& eventMemory) = 0;
-
- virtual void onServiceStateChange(const sp<IMemory>& eventMemory) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSoundTriggerClient : public BnInterface<ISoundTriggerClient>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
diff --git a/include/soundtrigger/ISoundTriggerHwService.h b/include/soundtrigger/ISoundTriggerHwService.h
deleted file mode 100644
index 1faeb0f..0000000
--- a/include/soundtrigger/ISoundTriggerHwService.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
-#define ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class ISoundTrigger;
-class ISoundTriggerClient;
-
-class ISoundTriggerHwService : public IInterface
-{
-public:
-
- DECLARE_META_INTERFACE(SoundTriggerHwService);
-
- virtual status_t listModules(const String16& opPackageName,
- struct sound_trigger_module_descriptor *modules,
- uint32_t *numModules) = 0;
-
- virtual status_t attach(const String16& opPackageName,
- const sound_trigger_module_handle_t handle,
- const sp<ISoundTriggerClient>& client,
- sp<ISoundTrigger>& module) = 0;
-
- virtual status_t setCaptureState(bool active) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSoundTriggerHwService: public BnInterface<ISoundTriggerHwService>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
diff --git a/include/soundtrigger/OWNERS b/include/soundtrigger/OWNERS
deleted file mode 100644
index e83f6b9..0000000
--- a/include/soundtrigger/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-thorntonc@google.com
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
deleted file mode 100644
index 248620a..0000000
--- a/include/soundtrigger/SoundTrigger.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_H
-
-#include <binder/IBinder.h>
-#include <utils/threads.h>
-#include <soundtrigger/SoundTriggerCallback.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class MemoryDealer;
-
-class SoundTrigger : public BnSoundTriggerClient,
- public IBinder::DeathRecipient
-{
-public:
-
- virtual ~SoundTrigger();
-
- static status_t listModules(const String16& opPackageName,
- struct sound_trigger_module_descriptor *modules,
- uint32_t *numModules);
- static sp<SoundTrigger> attach(const String16& opPackageName,
- const sound_trigger_module_handle_t module,
- const sp<SoundTriggerCallback>& callback);
-
- static status_t setCaptureState(bool active);
-
- void detach();
-
- status_t loadSoundModel(const sp<IMemory>& modelMemory,
- sound_model_handle_t *handle);
-
- status_t unloadSoundModel(sound_model_handle_t handle);
-
- status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory);
- status_t stopRecognition(sound_model_handle_t handle);
- status_t getModelState(sound_model_handle_t handle);
- status_t setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t value);
- status_t getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t* value);
- status_t queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range);
-
- // BpSoundTriggerClient
- virtual void onRecognitionEvent(const sp<IMemory>& eventMemory);
- virtual void onSoundModelEvent(const sp<IMemory>& eventMemory);
- virtual void onServiceStateChange(const sp<IMemory>& eventMemory);
-
- //IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
-
- static status_t stringToGuid(const char *str, sound_trigger_uuid_t *guid);
- static status_t guidToString(const sound_trigger_uuid_t *guid,
- char *str, size_t maxLen);
-
-private:
- SoundTrigger(sound_trigger_module_handle_t module,
- const sp<SoundTriggerCallback>&);
- static const sp<ISoundTriggerHwService> getSoundTriggerHwService();
-
- Mutex mLock;
- sp<ISoundTrigger> mISoundTrigger;
- sp<SoundTriggerCallback> mCallback;
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_SOUNDTRIGGER_H
diff --git a/include/soundtrigger/SoundTriggerCallback.h b/include/soundtrigger/SoundTriggerCallback.h
deleted file mode 100644
index b5277f2..0000000
--- a/include/soundtrigger/SoundTriggerCallback.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
-
-#include <utils/RefBase.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class SoundTriggerCallback : public RefBase
-{
-public:
-
- SoundTriggerCallback() {}
- virtual ~SoundTriggerCallback() {}
-
- virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event) = 0;
-
- virtual void onSoundModelEvent(struct sound_trigger_model_event *event) = 0;
-
- virtual void onServiceStateChange(sound_trigger_service_state_t state) = 0;
-
- virtual void onServiceDied() = 0;
-
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index e33804d..fcf7cb1 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -19,7 +19,6 @@
libmediautils \
libnbaio \
libnblog \
- libsoundtriggerservice \
libutils \
libvibrator
@@ -33,7 +32,6 @@
frameworks/av/services/audiopolicy/service \
frameworks/av/services/medialog \
frameworks/av/services/oboeservice \
- frameworks/av/services/soundtrigger \
frameworks/av/media/libaaudio/include \
frameworks/av/media/libaaudio/src \
frameworks/av/media/libaaudio/src/binding \
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index db57248..4a2ac1d 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -36,7 +36,6 @@
#include "utility/AAudioUtilities.h"
#include "MediaLogService.h"
#include "MediaUtils.h"
-#include "SoundTriggerHwService.h"
using namespace android;
@@ -148,7 +147,6 @@
AAudioService::instantiate();
}
- SoundTriggerHwService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 6f85960..8c0ecf2 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1631,8 +1631,12 @@
{
*offset += chunk_size;
- if (mLastTrack == NULL)
+ // the absolute minimum size of a compliant mett box is 11 bytes:
+ // 6 byte reserved, 2 byte index, null byte, one char mime_format, null byte
+ // The resulting mime_format would be invalid at that size though.
+ if (mLastTrack == NULL || chunk_data_size < 11) {
return ERROR_MALFORMED;
+ }
auto buffer = heapbuffer<uint8_t>(chunk_data_size);
if (buffer.get() == NULL) {
@@ -1644,10 +1648,24 @@
return ERROR_IO;
}
+ // ISO-14496-12:
+ // int8 reserved[6]; // should be all zeroes
+ // int16_t data_reference_index;
+ // char content_encoding[]; // null terminated, optional (= just the null byte)
+ // char mime_format[]; // null terminated, mandatory
+ // optional other boxes
+ //
+ // API < 29:
+ // char mime_format[]; // null terminated
+ //
+ // API >= 29
+ // char mime_format[]; // null terminated
+ // char mime_format[]; // null terminated
+
// Prior to API 29, the metadata track was not compliant with ISO/IEC
// 14496-12-2015. This led to some ISO-compliant parsers failing to read the
// metatrack. As of API 29 and onwards, a change was made to metadata track to
- // make it compliant with the standard. The workaround is to write the
+ // make it somewhat compatible with the standard. The workaround is to write the
// null-terminated mime_format string twice. This allows compliant parsers to
// read the missing reserved, data_reference_index, and content_encoding fields
// from the first mime_type string. The actual mime_format field would then be
@@ -1656,27 +1674,27 @@
// as it would only read the first null-terminated mime_format string. To enable
// reading metadata tracks generated from both the non-compliant and compliant
// formats, a check needs to be done to see which format is used.
- int null_pos = 0;
- const unsigned char *str = buffer.get();
- while (null_pos < chunk_data_size) {
- if (*(str + null_pos) == '\0') {
- break;
- }
- ++null_pos;
- }
+ const char *str = (const char*) buffer.get();
+ size_t string_length = strnlen(str, chunk_data_size);
- if (null_pos == chunk_data_size - 1) {
- // This is not a standard ompliant metadata track.
- String8 mimeFormat((const char *)(buffer.get()), chunk_data_size);
- AMediaFormat_setString(mLastTrack->meta,
- AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+ if (string_length == chunk_data_size - 1) {
+ // This is likely a pre API 29 file, since it's a single null terminated
+ // string filling the entire box.
+ AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, str);
} else {
- // This is a standard compliant metadata track.
- String8 contentEncoding((const char *)(buffer.get() + 8));
- String8 mimeFormat((const char *)(buffer.get() + 8 + contentEncoding.size() + 1),
- chunk_data_size - 8 - contentEncoding.size() - 1);
- AMediaFormat_setString(mLastTrack->meta,
- AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+ // This might be a fully compliant metadata track, a "double mime" compatibility
+ // track, or anything else, including a single non-terminated string, so we need
+ // to determine the length of each string we want to parse out of the box.
+ size_t encoding_length = strnlen(str + 8, chunk_data_size - 8);
+ if (encoding_length + 8 >= chunk_data_size - 2) {
+ // the encoding extends to the end of the box, so there's no mime_format
+ return ERROR_MALFORMED;
+ }
+ String8 contentEncoding(str + 8, encoding_length);
+ String8 mimeFormat(str + 8 + encoding_length + 1,
+ chunk_data_size - 8 - encoding_length - 1);
+ AMediaFormat_setString(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
}
break;
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index ab942df..b9e6e33 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -1371,8 +1371,6 @@
case UNREGISTER_EFFECT:
case SET_EFFECT_ENABLED:
case GET_OUTPUT_FOR_ATTR:
- case ACQUIRE_SOUNDTRIGGER_SESSION:
- case RELEASE_SOUNDTRIGGER_SESSION:
case MOVE_EFFECTS_TO_IO:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
@@ -1410,6 +1408,8 @@
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
+ case ACQUIRE_SOUNDTRIGGER_SESSION:
+ case RELEASE_SOUNDTRIGGER_SESSION:
case SET_RTT_ENABLED:
case IS_CALL_SCREEN_MODE_SUPPORTED:
case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
@@ -2027,8 +2027,6 @@
case ACQUIRE_SOUNDTRIGGER_SESSION: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
- data.readStrongBinder());
audio_session_t session = AUDIO_SESSION_NONE;
audio_io_handle_t ioHandle = AUDIO_IO_HANDLE_NONE;
audio_devices_t device = AUDIO_DEVICE_NONE;
@@ -2044,8 +2042,6 @@
case RELEASE_SOUNDTRIGGER_SESSION: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
- data.readStrongBinder());
audio_session_t session = (audio_session_t)data.readInt32();
status_t status = releaseSoundTriggerSession(session);
reply->writeInt32(status);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index cd3ac1f..342ceb6 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -323,25 +323,45 @@
if (mDevice == 0) return NO_INIT;
if (patch == nullptr) return BAD_VALUE;
+#if MAJOR_VERSION < 6
if (*patch != AUDIO_PATCH_HANDLE_NONE) {
status_t status = releaseAudioPatch(*patch);
ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
__func__, status, *patch);
+ *patch = AUDIO_PATCH_HANDLE_NONE;
}
+#endif
hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
- Result retval;
- Return<void> ret = mDevice->createAudioPatch(
- hidlSources, hidlSinks,
- [&](Result r, AudioPatchHandle hidlPatch) {
- retval = r;
- if (retval == Result::OK) {
- *patch = static_cast<audio_patch_handle_t>(hidlPatch);
- }
- });
- return processReturn("createAudioPatch", ret, retval);
+ Result retval = Result::OK;
+ Return<void> ret;
+ std::string methodName = "createAudioPatch";
+ if (*patch == AUDIO_PATCH_HANDLE_NONE) { // always true for MAJOR_VERSION < 6
+ ret = mDevice->createAudioPatch(
+ hidlSources, hidlSinks,
+ [&](Result r, AudioPatchHandle hidlPatch) {
+ retval = r;
+ if (retval == Result::OK) {
+ *patch = static_cast<audio_patch_handle_t>(hidlPatch);
+ }
+ });
+ } else {
+#if MAJOR_VERSION >= 6
+ ret = mDevice->updateAudioPatch(
+ *patch,
+ hidlSources, hidlSinks,
+ [&](Result r, AudioPatchHandle hidlPatch) {
+ retval = r;
+ if (retval == Result::OK) {
+ *patch = static_cast<audio_patch_handle_t>(hidlPatch);
+ }
+ });
+ methodName = "updateAudioPatch";
+#endif
+ }
+ return processReturn(methodName.c_str(), ret, retval);
}
status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index a49e72e..4657f9e 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -418,7 +418,7 @@
sp<IMediaExtractorService> mediaExService(
interface_cast<IMediaExtractorService>(binder));
sp<IDataSource> source;
- mediaExService->makeIDataSource(mFd, mOffset, mLength, &source);
+ mediaExService->makeIDataSource(base::unique_fd(dup(mFd.get())), mOffset, mLength, &source);
ALOGV("IDataSource(FileSource): %p %d %lld %lld",
source.get(), mFd.get(), (long long)mOffset, (long long)mLength);
if (source.get() != nullptr) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e516477..709bc08 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -101,6 +101,10 @@
static const char *kCodecLatencyHist = "android.media.mediacodec.latency.hist"; /* in us */
static const char *kCodecLatencyUnknown = "android.media.mediacodec.latency.unknown";
+static const char *kCodecNumLowLatencyModeOn = "android.media.mediacodec.low-latency.on"; /* 0..n */
+static const char *kCodecNumLowLatencyModeOff = "android.media.mediacodec.low-latency.off"; /* 0..n */
+static const char *kCodecFirstFrameIndexLowLatencyModeOn = "android.media.mediacodec.low-latency.first-frame"; /* 0..n */
+
// the kCodecRecent* fields appear only in getMetrics() results
static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max"; /* in us */
static const char *kCodecRecentLatencyMin = "android.media.mediacodec.recent.min"; /* in us */
@@ -583,7 +587,12 @@
mHaveInputSurface(false),
mHavePendingInputBuffers(false),
mCpuBoostRequested(false),
- mLatencyUnknown(0) {
+ mLatencyUnknown(0),
+ mNumLowLatencyEnables(0),
+ mNumLowLatencyDisables(0),
+ mIsLowLatencyModeOn(false),
+ mIndexOfFirstFrameWhenLowLatencyOn(-1),
+ mInputBufferCounter(0) {
if (uid == kNoUid) {
mUid = AIBinder_getCallingUid();
} else {
@@ -616,6 +625,16 @@
}
mRecentHead = 0;
}
+
+ {
+ Mutex::Autolock al(mLatencyLock);
+ mBuffersInFlight.clear();
+ mNumLowLatencyEnables = 0;
+ mNumLowLatencyDisables = 0;
+ mIsLowLatencyModeOn = false;
+ mIndexOfFirstFrameWhenLowLatencyOn = -1;
+ mInputBufferCounter = 0;
+ }
}
void MediaCodec::updateMediametrics() {
@@ -641,6 +660,13 @@
mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
}
+ {
+ Mutex::Autolock al(mLatencyLock);
+ mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOn, mNumLowLatencyEnables);
+ mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOff, mNumLowLatencyDisables);
+ mediametrics_setInt64(mMetricsHandle, kCodecFirstFrameIndexLowLatencyModeOn,
+ mIndexOfFirstFrameWhenLowLatencyOn);
+ }
#if 0
// enable for short term, only while debugging
updateEphemeralMediametrics(mMetricsHandle);
@@ -697,6 +723,22 @@
}
}
+void MediaCodec::updateLowLatency(const sp<AMessage> &msg) {
+ int32_t lowLatency = 0;
+ if (msg->findInt32("low-latency", &lowLatency)) {
+ Mutex::Autolock al(mLatencyLock);
+ if (lowLatency > 0) {
+ ++mNumLowLatencyEnables;
+ // This is just an estimate since low latency mode change happens ONLY at key frame
+ mIsLowLatencyModeOn = true;
+ } else if (lowLatency == 0) {
+ ++mNumLowLatencyDisables;
+ // This is just an estimate since low latency mode change happens ONLY at key frame
+ mIsLowLatencyModeOn = false;
+ }
+ }
+}
+
bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor)
{
if (nbuckets <= 0 || width <= 0) {
@@ -813,6 +855,11 @@
// XXX: we *could* make sure that the time is later than the end of queue
// as part of a consistency check...
mBuffersInFlight.push_back(startdata);
+
+ if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
+ mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
+ }
+ ++mInputBufferCounter;
}
}
@@ -1133,6 +1180,8 @@
}
}
+ updateLowLatency(format);
+
msg->setMessage("format", format);
msg->setInt32("flags", flags);
msg->setObject("surface", surface);
@@ -3714,6 +3763,7 @@
}
status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) {
+ updateLowLatency(params);
mCodec->signalSetParameters(params);
return OK;
diff --git a/media/libstagefright/codecs/amrnb/common/Android.bp b/media/libstagefright/codecs/amrnb/common/Android.bp
index 772ebf9..ea8b073 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.bp
+++ b/media/libstagefright/codecs/amrnb/common/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libstagefright_amrnb_common",
vendor_available: true,
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 78cb01c..5c5c23a 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -313,6 +313,7 @@
void updateMediametrics();
void flushMediametrics();
void updateEphemeralMediametrics(mediametrics_handle_t item);
+ void updateLowLatency(const sp<AMessage> &msg);
sp<AMessage> mOutputFormat;
sp<AMessage> mInputFormat;
@@ -440,6 +441,12 @@
std::deque<BufferFlightTiming_t> mBuffersInFlight;
Mutex mLatencyLock;
int64_t mLatencyUnknown; // buffers for which we couldn't calculate latency
+ int64_t mNumLowLatencyEnables; // how many times low latency mode is enabled
+ int64_t mNumLowLatencyDisables; // how many times low latency mode is disabled
+ bool mIsLowLatencyModeOn; // is low latency mode on currently
+ int64_t mIndexOfFirstFrameWhenLowLatencyOn; // index of the first frame queued
+ // when low latency is on
+ int64_t mInputBufferCounter; // number of input buffers queued since last reset/flush
sp<BatteryChecker> mBatteryChecker;
diff --git a/media/mtp/IMtpHandle.h b/media/mtp/IMtpHandle.h
index fd14b18..0435e82 100644
--- a/media/mtp/IMtpHandle.h
+++ b/media/mtp/IMtpHandle.h
@@ -16,7 +16,7 @@
#ifndef _IMTP_HANDLE_H
#define _IMTP_HANDLE_H
-#include <linux/usb/f_mtp.h>
+#include "f_mtp.h"
namespace android {
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index af69a10..fdf51b1 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -84,8 +84,8 @@
// MTP_OPERATION_SET_OBJECT_PROP_LIST,
// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
// MTP_OPERATION_SEND_OBJECT_PROP_LIST,
- MTP_OPERATION_GET_OBJECT_REFERENCES,
- MTP_OPERATION_SET_OBJECT_REFERENCES,
+// MTP_OPERATION_GET_OBJECT_REFERENCES,
+// MTP_OPERATION_SET_OBJECT_REFERENCES,
// MTP_OPERATION_SKIP,
// Android extension for direct file IO
MTP_OPERATION_GET_PARTIAL_OBJECT_64,
diff --git a/media/mtp/f_mtp.h b/media/mtp/f_mtp.h
new file mode 100644
index 0000000..22ec771
--- /dev/null
+++ b/media/mtp/f_mtp.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_USB_F_MTP_H
+#define _UAPI_LINUX_USB_F_MTP_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct mtp_file_range {
+ int fd;
+ loff_t offset;
+ int64_t length;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ uint16_t command;
+ uint32_t transaction_id;
+};
+struct mtp_event {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ size_t length;
+ void * data;
+};
+#define MTP_SEND_FILE _IOW('M', 0, struct mtp_file_range)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MTP_RECEIVE_FILE _IOW('M', 1, struct mtp_file_range)
+#define MTP_SEND_EVENT _IOW('M', 3, struct mtp_event)
+#define MTP_SEND_FILE_WITH_HEADER _IOW('M', 4, struct mtp_file_range)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0911a1f..e953c8e 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2993,7 +2993,7 @@
for (size_t i = 0; i < chains.size(); i++) {
sp<EffectChain> ec = chains[i];
int sessionid = ec->sessionId();
- sp<ThreadBase> t = ec->mThread.promote();
+ sp<ThreadBase> t = ec->thread().promote();
if (t == 0) {
continue;
}
@@ -3016,7 +3016,7 @@
effect->unPin();
t->removeEffect_l(effect, /*release*/ true);
if (effect->purgeHandles()) {
- t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
+ effect->checkSuspendOnEffectEnabled(false, true /*threadLocked*/);
}
removedEffects.push_back(effect);
}
@@ -3639,7 +3639,7 @@
// if the move request is not received from audio policy manager, the effect must be
// re-registered with the new strategy and output
if (dstChain == 0) {
- dstChain = effect->chain().promote();
+ dstChain = effect->callback()->chain().promote();
if (dstChain == 0) {
ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
status = NO_INIT;
@@ -3689,7 +3689,7 @@
goto Exit;
}
- dstChain = effect->chain().promote();
+ dstChain = effect->callback()->chain().promote();
if (dstChain == 0) {
thread->addEffect_l(effect);
status = INVALID_OPERATION;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index f27c6ad..2a83fd3 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -64,14 +64,13 @@
#undef LOG_TAG
#define LOG_TAG "AudioFlinger::EffectModule"
-AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
- const wp<AudioFlinger::EffectChain>& chain,
+AudioFlinger::EffectModule::EffectModule(const sp<AudioFlinger::EffectCallbackInterface>& callback,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
bool pinned)
: mPinned(pinned),
- mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
+ mCallback(callback), mId(id), mSessionId(sessionId),
mDescriptor(*desc),
// clear mConfig to ensure consistent initial value of buffer framecount
// in case buffers are associated by setInBuffer() or setOutBuffer()
@@ -81,8 +80,7 @@
mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
mDisableWaitCnt(0), // set by process() and updateState()
mSuspended(false),
- mOffloaded(false),
- mAudioFlinger(thread->mAudioFlinger)
+ mOffloaded(false)
#ifdef FLOAT_EFFECT_CHAIN
, mSupportsFloat(false)
#endif
@@ -91,16 +89,8 @@
int lStatus;
// create effect engine from effect factory
- mStatus = -ENODEV;
- sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
- if (audioFlinger != 0) {
- sp<EffectsFactoryHalInterface> effectsFactory = audioFlinger->getEffectsFactory();
- if (effectsFactory != 0) {
- mStatus = effectsFactory->createEffect(
- &desc->uuid, sessionId, thread->id(), AUDIO_PORT_HANDLE_NONE, &mEffectInterface);
- }
- }
-
+ mStatus = callback->createEffectHal(
+ &desc->uuid, sessionId, AUDIO_PORT_HANDLE_NONE, &mEffectInterface);
if (mStatus != NO_ERROR) {
return;
}
@@ -110,7 +100,7 @@
goto Error;
}
- setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id());
+ setOffloaded(callback->isOffload(), callback->io());
ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
return;
@@ -188,14 +178,8 @@
doRegister = true;
mPolicyRegistered = mHandles.size() > 0;
if (mPolicyRegistered) {
- sp <EffectChain> chain = mChain.promote();
- sp <ThreadBase> thread = mThread.promote();
-
- if (thread == nullptr || chain == nullptr) {
- return INVALID_OPERATION;
- }
- io = thread->id();
- strategy = chain->strategy();
+ io = mCallback->io();
+ strategy = mCallback->strategy();
}
}
// enable effect when registered according to enable state requested by controlling handle
@@ -292,15 +276,16 @@
ssize_t AudioFlinger::EffectModule::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
{
ALOGV("disconnect() %p handle %p", this, handle);
+ if (mCallback->disconnectEffectHandle(handle, unpinIfLast)) {
+ return mHandles.size();
+ }
+
Mutex::Autolock _l(mLock);
ssize_t numHandles = removeHandle_l(handle);
if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
- sp<AudioFlinger> af = mAudioFlinger.promote();
- if (af != 0) {
- mLock.unlock();
- af->updateOrphanEffectChains(this);
- mLock.lock();
- }
+ mLock.unlock();
+ mCallback->updateOrphanEffectChains(this);
+ mLock.lock();
}
return numHandles;
}
@@ -542,8 +527,7 @@
mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
// If an insert effect is idle and input buffer is different from output buffer,
// accumulate input onto output
- sp<EffectChain> chain = mChain.promote();
- if (chain.get() != nullptr && chain->activeTrackCnt() != 0) {
+ if (mCallback->activeTrackCnt() != 0) {
// similar handling with data_bypass above.
if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
accumulateInputToOutput();
@@ -566,7 +550,6 @@
{
ALOGVV("configure() started");
status_t status;
- sp<ThreadBase> thread;
uint32_t size;
audio_channel_mask_t channelMask;
@@ -575,17 +558,11 @@
goto exit;
}
- thread = mThread.promote();
- if (thread == 0) {
- status = DEAD_OBJECT;
- goto exit;
- }
-
// TODO: handle configuration of effects replacing track process
// TODO: handle configuration of input (record) SW effects above the HAL,
// similar to output EFFECT_FLAG_TYPE_INSERT/REPLACE,
// in which case input channel masks should be used here.
- channelMask = thread->channelMask();
+ channelMask = mCallback->channelMask();
mConfig.inputCfg.channels = channelMask;
mConfig.outputCfg.channels = channelMask;
@@ -622,11 +599,11 @@
mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
// Don't use sample rate for thread if effect isn't offloadable.
- if ((thread->type() == ThreadBase::OFFLOAD) && !isOffloaded()) {
+ if (mCallback->isOffload() && !isOffloaded()) {
mConfig.inputCfg.samplingRate = DEFAULT_OUTPUT_SAMPLE_RATE;
ALOGV("Overriding effect input as 48kHz");
} else {
- mConfig.inputCfg.samplingRate = thread->sampleRate();
+ mConfig.inputCfg.samplingRate = mCallback->sampleRate();
}
mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
mConfig.inputCfg.bufferProvider.cookie = NULL;
@@ -652,11 +629,13 @@
}
mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
- mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+ mConfig.inputCfg.buffer.frameCount = mCallback->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
- ALOGV("configure() %p thread %p buffer %p framecount %zu",
- this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
+ ALOGV("configure() %p chain %p buffer %p framecount %zu",
+ this, mCallback->chain().promote() != nullptr ? mCallback->chain().promote().get() :
+ nullptr,
+ mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
status_t cmdStatus;
size = sizeof(int);
@@ -671,7 +650,7 @@
#ifdef MULTICHANNEL_EFFECT_CHAIN
if (status != NO_ERROR &&
- thread->isOutput() &&
+ mCallback->isOutput() &&
(mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
|| mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
// Older effects may require exact STEREO position mask.
@@ -738,11 +717,7 @@
size = sizeof(int);
*(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
- uint32_t latency = 0;
- PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
- if (pbt != NULL) {
- latency = pbt->latency_l();
- }
+ uint32_t latency = mCallback->latency();
*((int32_t *)p->data + 1)= latency;
mEffectInterface->command(EFFECT_CMD_SET_PARAM,
@@ -789,31 +764,20 @@
{
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- sp<StreamHalInterface> stream = thread->stream();
- if (stream != 0) {
- status_t result = stream->addEffect(mEffectInterface);
- ALOGE_IF(result != OK, "Error when adding effect: %d", result);
- }
- }
+ (void)mCallback->addEffectToHal(mEffectInterface);
}
}
// start() must be called with PlaybackThread::mLock or EffectChain::mLock held
status_t AudioFlinger::EffectModule::start()
{
- sp<EffectChain> chain;
status_t status;
{
Mutex::Autolock _l(mLock);
status = start_l();
- if (status == NO_ERROR) {
- chain = mChain.promote();
- }
}
- if (chain != 0) {
- chain->resetVolume_l();
+ if (status == NO_ERROR) {
+ mCallback->resetVolume();
}
return status;
}
@@ -860,11 +824,10 @@
uint32_t size = sizeof(status_t);
if (isVolumeControl() && isOffloadedOrDirect()) {
- sp<EffectChain>chain = mChain.promote();
// We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
// resetVolume_l --> setVolume_l --> EffectModule::setVolume
mSetVolumeReentrantTid = gettid();
- chain->resetVolume_l();
+ mCallback->resetVolume();
mSetVolumeReentrantTid = INVALID_PID;
}
@@ -877,7 +840,7 @@
status = cmdStatus;
}
if (status == NO_ERROR) {
- status = remove_effect_from_hal_l();
+ status = removeEffectFromHal_l();
}
return status;
}
@@ -886,25 +849,18 @@
void AudioFlinger::EffectModule::release_l()
{
if (mEffectInterface != 0) {
- remove_effect_from_hal_l();
+ removeEffectFromHal_l();
// release effect engine
mEffectInterface->close();
mEffectInterface.clear();
}
}
-status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
+status_t AudioFlinger::EffectModule::removeEffectFromHal_l()
{
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- sp<StreamHalInterface> stream = thread->stream();
- if (stream != 0) {
- status_t result = stream->removeEffect(mEffectInterface);
- ALOGE_IF(result != OK, "Error when removing effect: %d", result);
- }
- }
+ mCallback->removeEffectFromHal(mEffectInterface);
}
return NO_ERROR;
}
@@ -994,10 +950,29 @@
return status;
}
-status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
+void AudioFlinger::EffectModule::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
+ mCallback->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
+}
+
+status_t AudioFlinger::EffectModule::setEnabled(bool enabled, bool fromHandle)
{
- Mutex::Autolock _l(mLock);
- return setEnabled_l(enabled);
+ status_t status;
+ {
+ Mutex::Autolock _l(mLock);
+ status = setEnabled_l(enabled);
+ }
+ if (fromHandle) {
+ if (enabled) {
+ if (status != NO_ERROR) {
+ mCallback->checkSuspendOnEffectEnabled(this, false, false /*threadLocked*/);
+ } else {
+ mCallback->onEffectEnable(this);
+ }
+ } else {
+ mCallback->onEffectDisable(this);
+ }
+ }
+ return status;
}
// must be called with EffectModule::mLock held
@@ -1080,7 +1055,7 @@
bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
{
- return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT);
+ return mCallback->isOffloadOrDirect();
}
bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
@@ -1124,9 +1099,7 @@
|| size > mInConversionBuffer->getSize())) {
mInConversionBuffer.clear();
ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
- sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
- LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
- (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mInConversionBuffer);
+ (void)mCallback->allocateHalBuffer(size, &mInConversionBuffer);
}
if (mInConversionBuffer.get() != nullptr) {
mInConversionBuffer->setFrameCount(inFrameCount);
@@ -1170,9 +1143,7 @@
|| size > mOutConversionBuffer->getSize())) {
mOutConversionBuffer.clear();
ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
- sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
- LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
- (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mOutConversionBuffer);
+ (void)mCallback->allocateHalBuffer(size, &mOutConversionBuffer);
}
if (mOutConversionBuffer.get() != nullptr) {
mOutConversionBuffer->setFrameCount(outFrameCount);
@@ -1220,14 +1191,10 @@
void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
{
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0 &&
- (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT) &&
- !isNonOffloadableEnabled_l()) {
- PlaybackThread *t = (PlaybackThread *)thread.get();
+ if (mEffectCallback->isOffloadOrDirect() && !isNonOffloadableEnabled_l()) {
float vol_l = (float)left / (1 << 24);
float vol_r = (float)right / (1 << 24);
- t->setVolumeForOutput_l(vol_l, vol_r);
+ mEffectCallback->setVolumeForOutput(vol_l, vol_r);
}
}
@@ -1646,38 +1613,16 @@
return status;
}
- sp<ThreadBase> thread = effect->thread().promote();
- if (thread != 0) {
- thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId());
- }
+ effect->checkSuspendOnEffectEnabled(true, false /*threadLocked*/);
// checkSuspendOnEffectEnabled() can suspend this same effect when enabled
if (effect->suspended()) {
return NO_ERROR;
}
- status = effect->setEnabled(true);
+ status = effect->setEnabled(true, true /*fromHandle*/);
if (status != NO_ERROR) {
- if (thread != 0) {
- thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
- }
mEnabled = false;
- } else {
- if (thread != 0) {
- if (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::MMAP) {
- Mutex::Autolock _l(thread->mLock);
- thread->broadcast_l();
- }
- if (!effect->isOffloadable()) {
- if (thread->type() == ThreadBase::OFFLOAD) {
- PlaybackThread *t = (PlaybackThread *)thread.get();
- t->invalidateTracks(AUDIO_STREAM_MUSIC);
- }
- if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
- thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
- }
- }
- }
}
return status;
}
@@ -1705,17 +1650,7 @@
return NO_ERROR;
}
- status_t status = effect->setEnabled(false);
-
- sp<ThreadBase> thread = effect->thread().promote();
- if (thread != 0) {
- thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
- if (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::MMAP) {
- Mutex::Autolock _l(thread->mLock);
- thread->broadcast_l();
- }
- }
-
+ status_t status = effect->setEnabled(false, true /*fromHandle*/);
return status;
}
@@ -1739,10 +1674,7 @@
{
sp<EffectModule> effect = mEffect.promote();
if (effect != 0) {
- sp<ThreadBase> thread = effect->thread().promote();
- if (thread != 0) {
- thread->disconnectEffectHandle(this, unpinIfLast);
- } else if (effect->disconnectHandle(this, unpinIfLast) > 0) {
+ if (effect->disconnectHandle(this, unpinIfLast) > 0) {
ALOGW("%s Effect handle %p disconnected after thread destruction",
__func__, this);
}
@@ -1962,12 +1894,13 @@
AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
audio_session_t sessionId)
- : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
+ : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
- mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
+ mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
+ mEffectCallback(new EffectCallback(this, thread, thread->mAudioFlinger.get()))
{
mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
- if (thread == NULL) {
+ if (thread == nullptr) {
return;
}
mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
@@ -2033,40 +1966,29 @@
void AudioFlinger::EffectChain::clearInputBuffer()
{
Mutex::Autolock _l(mLock);
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- ALOGW("clearInputBuffer(): cannot promote mixer thread");
- return;
- }
- clearInputBuffer_l(thread);
+ clearInputBuffer_l();
}
// Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::clearInputBuffer_l(const sp<ThreadBase>& thread)
+void AudioFlinger::EffectChain::clearInputBuffer_l()
{
if (mInBuffer == NULL) {
return;
}
const size_t frameSize =
- audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * thread->channelCount();
+ audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * mEffectCallback->channelCount();
- memset(mInBuffer->audioBuffer()->raw, 0, thread->frameCount() * frameSize);
+ memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
mInBuffer->commit();
}
// Must be called with EffectChain::mLock locked
void AudioFlinger::EffectChain::process_l()
{
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- ALOGW("process_l(): cannot promote mixer thread");
- return;
- }
// never process effects when:
// - on an OFFLOAD thread
// - no more tracks are on the session and the effect tail has been rendered
- bool doProcess = (thread->type() != ThreadBase::OFFLOAD)
- && (thread->type() != ThreadBase::MMAP);
+ bool doProcess = !mEffectCallback->isOffloadOrMmap();
if (!audio_is_global_session(mSessionId)) {
bool tracksOnSession = (trackCnt() != 0);
@@ -2078,7 +2000,7 @@
// if no track is active and the effect tail has not been rendered,
// the input buffer must be cleared here as the mixer process will not do it
if (tracksOnSession || mTailBufferCount > 0) {
- clearInputBuffer_l(thread);
+ clearInputBuffer_l();
if (mTailBufferCount > 0) {
mTailBufferCount--;
}
@@ -2114,14 +2036,13 @@
// createEffect_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
- ThreadBase *thread,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
bool pinned)
{
Mutex::Autolock _l(mLock);
- effect = new EffectModule(thread, this, desc, id, sessionId, pinned);
+ effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned);
status_t lStatus = effect->status();
if (lStatus == NO_ERROR) {
lStatus = addEffect_ll(effect);
@@ -2144,12 +2065,7 @@
effect_descriptor_t desc = effect->desc();
uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
- effect->setChain(this);
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- return NO_INIT;
- }
- effect->setThread(thread);
+ effect->setCallback(mEffectCallback);
if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
// Auxiliary effects are inserted at the beginning of mEffects vector as
@@ -2160,13 +2076,13 @@
// 32 bit format. This is to avoid saturation in AudoMixer
// accumulation stage. Saturation is done in EffectModule::process() before
// calling the process in effect engine
- size_t numSamples = thread->frameCount();
+ size_t numSamples = mEffectCallback->frameCount();
sp<EffectBufferHalInterface> halBuffer;
#ifdef FLOAT_EFFECT_CHAIN
- status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+ status_t result = mEffectCallback->allocateHalBuffer(
numSamples * sizeof(float), &halBuffer);
#else
- status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+ status_t result = mEffectCallback->allocateHalBuffer(
numSamples * sizeof(int32_t), &halBuffer);
#endif
if (result != OK) return result;
@@ -2484,7 +2400,7 @@
if (effect != 0) {
desc->mEffect = effect;
effect->setSuspended(true);
- effect->setEnabled(false);
+ effect->setEnabled(false, false /*fromHandle*/);
}
}
} else {
@@ -2642,7 +2558,7 @@
// if effect is requested to suspended but was not yet enabled, suspend it now.
if (desc->mEffect == 0) {
desc->mEffect = effect;
- effect->setEnabled(false);
+ effect->setEnabled(false, false /*fromHandle*/);
effect->setSuspended(true);
}
} else {
@@ -2677,10 +2593,7 @@
void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
{
Mutex::Autolock _l(mLock);
- mThread = thread;
- for (size_t i = 0; i < mEffects.size(); i++) {
- mEffects[i]->setThread(thread);
- }
+ mEffectCallback->setThread(thread.get());
}
void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
@@ -2740,4 +2653,224 @@
return true;
}
+// EffectCallbackInterface implementation
+status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
+ const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
+ sp<EffectHalInterface> *effect) {
+ status_t status = NO_INIT;
+ sp<AudioFlinger> af = mAudioFlinger.promote();
+ if (af == nullptr) {
+ return status;
+ }
+ sp<EffectsFactoryHalInterface> effectsFactory = af->getEffectsFactory();
+ if (effectsFactory != 0) {
+ status = effectsFactory->createEffect(pEffectUuid, sessionId, io(), deviceId, effect);
+ }
+ return status;
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
+ const sp<AudioFlinger::EffectModule>& effect) {
+ sp<AudioFlinger> af = mAudioFlinger.promote();
+ if (af == nullptr) {
+ return false;
+ }
+ return af->updateOrphanEffectChains(effect);
+}
+
+status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
+ size_t size, sp<EffectBufferHalInterface>* buffer) {
+ sp<AudioFlinger> af = mAudioFlinger.promote();
+ LOG_ALWAYS_FATAL_IF(af == nullptr, "allocateHalBuffer() could not retrieved audio flinger");
+ return af->mEffectsFactoryHal->allocateBuffer(size, buffer);
+}
+
+status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
+ sp<EffectHalInterface> effect) {
+ status_t result = NO_INIT;
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return result;
+ }
+ sp <StreamHalInterface> st = t->stream();
+ if (st == nullptr) {
+ return result;
+ }
+ result = st->addEffect(effect);
+ ALOGE_IF(result != OK, "Error when adding effect: %d", result);
+ return result;
+}
+
+status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
+ sp<EffectHalInterface> effect) {
+ status_t result = NO_INIT;
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return result;
+ }
+ sp <StreamHalInterface> st = t->stream();
+ if (st == nullptr) {
+ return result;
+ }
+ result = st->removeEffect(effect);
+ ALOGE_IF(result != OK, "Error when removing effect: %d", result);
+ return result;
+}
+
+audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return AUDIO_IO_HANDLE_NONE;
+ }
+ return t->id();
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return true;
+ }
+ return t->isOutput();
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return false;
+ }
+ return t->type() == ThreadBase::OFFLOAD;
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return false;
+ }
+ return t->type() == ThreadBase::OFFLOAD || t->type() == ThreadBase::DIRECT;
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return false;
+ }
+ return t->type() == ThreadBase::OFFLOAD || t->type() == ThreadBase::MMAP;
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return 0;
+ }
+ return t->sampleRate();
+}
+
+audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::channelMask() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return AUDIO_CHANNEL_NONE;
+ }
+ return t->channelMask();
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::channelCount() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return 0;
+ }
+ return t->channelCount();
+}
+
+size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return 0;
+ }
+ return t->frameCount();
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return 0;
+ }
+ return t->latency_l();
+}
+
+void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return;
+ }
+ t->setVolumeForOutput_l(left, right);
+}
+
+void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
+ const sp<EffectModule>& effect, bool enabled, bool threadLocked) {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return;
+ }
+ t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
+
+ sp<EffectChain> c = mChain.promote();
+ if (c == nullptr) {
+ return;
+ }
+ c->checkSuspendOnEffectEnabled(effect, enabled);
+}
+
+void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectModule>& effect) {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return;
+ }
+ t->onEffectEnable(effect);
+}
+
+void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectModule>& effect) {
+ checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
+
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return;
+ }
+ t->onEffectDisable();
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
+ bool unpinIfLast) {
+ sp<ThreadBase> t = mThread.promote();
+ if (t == nullptr) {
+ return false;
+ }
+ t->disconnectEffectHandle(handle, unpinIfLast);
+ return true;
+}
+
+void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
+ sp<EffectChain> c = mChain.promote();
+ if (c == nullptr) {
+ return;
+ }
+ c->resetVolume_l();
+
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
+ sp<EffectChain> c = mChain.promote();
+ if (c == nullptr) {
+ return PRODUCT_STRATEGY_NONE;
+ }
+ return c->strategy();
+}
+
+int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
+ sp<EffectChain> c = mChain.promote();
+ if (c == nullptr) {
+ return 0;
+ }
+ return c->activeTrackCnt();
+}
+
} // namespace android
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index dbf63c8..0b0f9f5 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -21,11 +21,60 @@
//--- Audio Effect Management
+// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
+// interactions between the EffectModule and the reset of the audio framework.
+class EffectCallbackInterface : public RefBase {
+public:
+ ~EffectCallbackInterface() override = default;
+
+ // Trivial methods usually implemented with help from ThreadBase
+ virtual audio_io_handle_t io() const = 0;
+ virtual bool isOutput() const = 0;
+ virtual bool isOffload() const = 0;
+ virtual bool isOffloadOrDirect() const = 0;
+ virtual bool isOffloadOrMmap() const = 0;
+ virtual uint32_t sampleRate() const = 0;
+ virtual audio_channel_mask_t channelMask() const = 0;
+ virtual uint32_t channelCount() const = 0;
+ virtual size_t frameCount() const = 0;
+
+ // Non trivial methods usually implemented with help from ThreadBase:
+ // pay attention to mutex locking order
+ virtual uint32_t latency() const { return 0; }
+ virtual status_t addEffectToHal(sp<EffectHalInterface> effect) = 0;
+ virtual status_t removeEffectFromHal(sp<EffectHalInterface> effect) = 0;
+ virtual void setVolumeForOutput(float left, float right) const = 0;
+ virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
+ virtual void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ bool enabled,
+ bool threadLocked) = 0;
+ virtual void onEffectEnable(const sp<EffectModule>& effect) = 0;
+ virtual void onEffectDisable(const sp<EffectModule>& effect) = 0;
+
+ // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
+ virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+ int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
+ virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+ virtual bool updateOrphanEffectChains(const sp<EffectModule>& effect) = 0;
+
+ // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
+ virtual uint32_t strategy() const = 0;
+ virtual int32_t activeTrackCnt() const = 0;
+ virtual void resetVolume() = 0;
+
+ virtual wp<EffectChain> chain() const = 0;
+};
+
// EffectModule and EffectChain classes both have their own mutex to protect
// state changes or resource modifications. Always respect the following order
// if multiple mutexes must be acquired to avoid cross deadlock:
// AudioFlinger -> ThreadBase -> EffectChain -> EffectModule
// AudioHandle -> ThreadBase -> EffectChain -> EffectModule
+
+// NOTE: When implementing the EffectCallbackInterface, in an EffectChain or other, it is important
+// to pay attention to this locking order as some callback methods can be called from a state where
+// EffectModule and/or EffectChain mutexes are held.
+
// In addition, methods that lock the AudioPolicyService mutex (getOutputForEffect(),
// startOutput(), getInputForAttr(), releaseInput()...) should never be called with AudioFlinger or
// Threadbase mutex locked to avoid cross deadlock with other clients calling AudioPolicyService
@@ -42,8 +91,7 @@
// the attached track(s) to accumulate their auxiliary channel.
class EffectModule : public RefBase {
public:
- EffectModule(ThreadBase *thread,
- const wp<AudioFlinger::EffectChain>& chain,
+ EffectModule(const sp<EffectCallbackInterface>& chain,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
@@ -81,7 +129,7 @@
audio_session_t sessionId() const {
return mSessionId;
}
- status_t setEnabled(bool enabled);
+ status_t setEnabled(bool enabled, bool fromHandle);
status_t setEnabled_l(bool enabled);
bool isEnabled() const;
bool isProcessEnabled() const;
@@ -96,10 +144,7 @@
int16_t *outBuffer() const {
return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
}
- void setChain(const wp<EffectChain>& chain) { mChain = chain; }
- void setThread(const wp<ThreadBase>& thread)
- { mThread = thread; mThreadType = thread.promote()->type(); }
- const wp<ThreadBase>& thread() { return mThread; }
+ void setCallback(const sp<EffectCallbackInterface>& callback) { mCallback = callback; }
status_t addHandle(EffectHandle *handle);
ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
@@ -107,7 +152,7 @@
ssize_t removeHandle_l(EffectHandle *handle);
const effect_descriptor_t& desc() const { return mDescriptor; }
- wp<EffectChain>& chain() { return mChain; }
+ sp<EffectCallbackInterface>& callback() { return mCallback; }
status_t setDevices(const AudioDeviceTypeAddrVector &devices);
status_t setInputDevice(const AudioDeviceTypeAddr &device);
@@ -144,6 +189,7 @@
void release_l();
status_t updatePolicyState();
+ void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked);
void dump(int fd, const Vector<String16>& args);
@@ -158,13 +204,11 @@
status_t start_l();
status_t stop_l();
- status_t remove_effect_from_hal_l();
+ status_t removeEffectFromHal_l();
status_t sendSetAudioDevicesCommand(const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode);
mutable Mutex mLock; // mutex for process, commands and handles list protection
- wp<ThreadBase> mThread; // parent thread
- ThreadBase::type_t mThreadType; // parent thread type
- wp<EffectChain> mChain; // parent effect chain
+ sp<EffectCallbackInterface> mCallback; // parent effect chain
const int mId; // this instance unique ID
const audio_session_t mSessionId; // audio session ID
const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
@@ -181,7 +225,6 @@
uint32_t mDisableWaitCnt; // current process() calls count during disable period.
bool mSuspended; // effect is suspended: temporarily disabled by framework
bool mOffloaded; // effect is currently offloaded to the audio DSP
- wp<AudioFlinger> mAudioFlinger;
#ifdef FLOAT_EFFECT_CHAIN
bool mSupportsFloat; // effect supports float processing
@@ -333,7 +376,6 @@
}
status_t createEffect_l(sp<EffectModule>& effect,
- ThreadBase *thread,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
@@ -389,9 +431,8 @@
bool suspend);
// suspend all eligible effects
void setEffectSuspendedAll_l(bool suspend);
- // check if effects should be suspend or restored when a given effect is enable or disabled
- void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
- bool enabled);
+ // check if effects should be suspended or restored when a given effect is enable or disabled
+ void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, bool enabled);
void clearInputBuffer();
@@ -416,9 +457,60 @@
// isCompatibleWithThread_l() must be called with thread->mLock held
bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
+ sp<EffectCallbackInterface> effectCallback() const { return mEffectCallback; }
+ wp<ThreadBase> thread() const { return mEffectCallback->thread(); }
+
void dump(int fd, const Vector<String16>& args);
private:
+
+ class EffectCallback : public EffectCallbackInterface {
+ public:
+ EffectCallback(EffectChain *chain, ThreadBase *thread, AudioFlinger *audioFlinger)
+ : mChain(chain), mThread(thread), mAudioFlinger(audioFlinger) {}
+
+ status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+ int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
+ status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+ bool updateOrphanEffectChains(const sp<EffectModule>& effect) override;
+
+ audio_io_handle_t io() const override;
+ bool isOutput() const override;
+ bool isOffload() const override;
+ bool isOffloadOrDirect() const override;
+ bool isOffloadOrMmap() const override;
+
+ uint32_t sampleRate() const override;
+ audio_channel_mask_t channelMask() const override;
+ uint32_t channelCount() const override;
+ size_t frameCount() const override;
+ uint32_t latency() const override;
+
+ status_t addEffectToHal(sp<EffectHalInterface> effect) override;
+ status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+ bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+ void setVolumeForOutput(float left, float right) const override;
+
+ // check if effects should be suspended/restored when a given effect is enable/disabled
+ void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ bool enabled, bool threadLocked) override;
+ void resetVolume() override;
+ uint32_t strategy() const override;
+ int32_t activeTrackCnt() const override;
+ void onEffectEnable(const sp<EffectModule>& effect) override;
+ void onEffectDisable(const sp<EffectModule>& effect) override;
+
+ wp<EffectChain> chain() const override { return mChain; }
+
+ wp<ThreadBase> thread() { return mThread; }
+ void setThread(ThreadBase *thread) { mThread = thread; };
+
+ private:
+ wp<EffectChain> mChain;
+ wp<ThreadBase> mThread;
+ wp<AudioFlinger> mAudioFlinger;
+ };
+
friend class AudioFlinger; // for mThread, mEffects
DISALLOW_COPY_AND_ASSIGN(EffectChain);
@@ -444,13 +536,12 @@
static bool isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type);
- void clearInputBuffer_l(const sp<ThreadBase>& thread);
+ void clearInputBuffer_l();
void setThread(const sp<ThreadBase>& thread);
void setVolumeForOutput_l(uint32_t left, uint32_t right);
- wp<ThreadBase> mThread; // parent mixer thread
mutable Mutex mLock; // mutex protecting effect list
Vector< sp<EffectModule> > mEffects; // list of effect modules
audio_session_t mSessionId; // audio session ID
@@ -474,4 +565,6 @@
// timeLow fields among effect type UUIDs.
// Updated by setEffectSuspended_l() and setEffectSuspendedAll_l() only.
KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
+
+ const sp<EffectCallback> mEffectCallback;
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9a16a95..a6d6914 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1146,18 +1146,13 @@
}
}
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
- bool enabled,
- audio_session_t sessionId)
-{
- Mutex::Autolock _l(mLock);
- checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
-}
+void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
+ audio_session_t sessionId,
+ bool threadLocked) {
+ if (!threadLocked) {
+ mLock.lock();
+ }
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
- bool enabled,
- audio_session_t sessionId)
-{
if (mType != RECORD) {
// suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
// another session. This gives the priority to well behaved effect control panels
@@ -1169,9 +1164,8 @@
}
}
- sp<EffectChain> chain = getEffectChain_l(sessionId);
- if (chain != 0) {
- chain->checkSuspendOnEffectEnabled(effect, enabled);
+ if (!threadLocked) {
+ mLock.unlock();
}
}
@@ -1379,7 +1373,7 @@
if (effect == 0) {
effectId = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
// create a new effect module if none present in the chain
- lStatus = chain->createEffect_l(effect, this, desc, effectId, sessionId, pinned);
+ lStatus = chain->createEffect_l(effect, desc, effectId, sessionId, pinned);
if (lStatus != NO_ERROR) {
goto Exit;
}
@@ -1427,7 +1421,7 @@
Mutex::Autolock _l(mLock);
effect = handle->effect().promote();
- if (effect == 0) {
+ if (effect == nullptr) {
return;
}
// restore suspended effects if the disconnected handle was enabled and the last one.
@@ -1439,11 +1433,34 @@
if (remove) {
mAudioFlinger->updateOrphanEffectChains(effect);
if (handle->enabled()) {
- checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
+ effect->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
}
}
}
+void AudioFlinger::ThreadBase::onEffectEnable(const sp<EffectModule>& effect) {
+ if (mType == OFFLOAD || mType == MMAP) {
+ Mutex::Autolock _l(mLock);
+ broadcast_l();
+ }
+ if (!effect->isOffloadable()) {
+ if (mType == ThreadBase::OFFLOAD) {
+ PlaybackThread *t = (PlaybackThread *)this;
+ t->invalidateTracks(AUDIO_STREAM_MUSIC);
+ }
+ if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
+ mAudioFlinger->onNonOffloadableGlobalEffectEnable();
+ }
+ }
+}
+
+void AudioFlinger::ThreadBase::onEffectDisable() {
+ if (mType == OFFLOAD || mType == MMAP) {
+ Mutex::Autolock _l(mLock);
+ broadcast_l();
+ }
+}
+
sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
int effectId)
{
@@ -1519,7 +1536,7 @@
detachAuxEffect_l(effect->id());
}
- sp<EffectChain> chain = effect->chain().promote();
+ sp<EffectChain> chain = effect->callback()->chain().promote();
if (chain != 0) {
// remove effect chain if removing last effect
if (chain->removeEffect_l(effect, release) == 0) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ef7eb6e..f1adc23 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -271,6 +271,8 @@
// Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects,
// and returns the [normal mix] buffer's frame count.
virtual size_t frameCount() const = 0;
+ virtual uint32_t latency_l() const { return 0; }
+ virtual void setVolumeForOutput_l(float left __unused, float right __unused) const {}
// Return's the HAL's frame count i.e. fast mixer buffer size.
size_t frameCountHAL() const { return mFrameCount; }
@@ -424,14 +426,9 @@
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
- void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
- bool enabled,
- audio_session_t sessionId =
- AUDIO_SESSION_OUTPUT_MIX);
- void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
- bool enabled,
- audio_session_t sessionId =
- AUDIO_SESSION_OUTPUT_MIX);
+ void checkSuspendOnEffectEnabled(bool enabled,
+ audio_session_t sessionId,
+ bool threadLocked);
virtual status_t setSyncEvent(const sp<SyncEvent>& event) = 0;
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
@@ -465,6 +462,9 @@
mutable Mutex mLock;
+ void onEffectEnable(const sp<EffectModule>& effect);
+ void onEffectDisable();
+
protected:
// entry describing an effect being suspended in mSuspendedSessions keyed vector
@@ -814,7 +814,7 @@
// return estimated latency in milliseconds, as reported by HAL
uint32_t latency() const;
// same, but lock must already be held
- uint32_t latency_l() const;
+ uint32_t latency_l() const override;
// VolumeInterface
virtual void setMasterVolume(float value);
@@ -824,7 +824,7 @@
virtual void setStreamMute(audio_stream_type_t stream, bool muted);
virtual float streamVolume(audio_stream_type_t stream) const;
- void setVolumeForOutput_l(float left, float right) const;
+ void setVolumeForOutput_l(float left, float right) const override;
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 00f14e1..c5cdc25 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -403,6 +403,12 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source) = 0;
+
+ // Used to notify the sound trigger module that an audio capture is about to
+ // take place. This should typically result in any active recognition
+ // sessions to be preempted on modules that do not support sound trigger
+ // recognition concurrently with audio capture.
+ virtual void setSoundTriggerCaptureState(bool active) = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 1fa0d19..577b42f 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -15,7 +15,6 @@
"libutils",
"liblog",
"libaudiopolicy",
- "libsoundtrigger",
"libmedia_helper",
"libmediametrics",
"libbinder",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 9d80a16..2124646 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -46,7 +46,6 @@
#include <utils/Log.h>
#include <media/AudioParameter.h>
#include <private/android_filesystem_config.h>
-#include <soundtrigger/SoundTrigger.h>
#include <system/audio.h>
#include "AudioPolicyManager.h"
#include <Serializer.h>
@@ -2277,7 +2276,7 @@
DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
if (primaryInputDevices.contains(device) &&
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 1) {
- SoundTrigger::setCaptureState(true);
+ mpClientInterface->setSoundTriggerCaptureState(true);
}
// automatically enable the remote submix output when input is started if not
@@ -2360,7 +2359,7 @@
DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
if (primaryInputDevices.contains(inputDesc->getDevice()) &&
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
- SoundTrigger::setCaptureState(false);
+ mpClientInterface->setSoundTriggerCaptureState(false);
}
inputDesc->clearPreemptedSessions();
}
@@ -5075,7 +5074,7 @@
DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
if (primaryInputDevices.contains(device) &&
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
- SoundTrigger::setCaptureState(false);
+ mpClientInterface->setSoundTriggerCaptureState(false);
}
cleanUpEffectsForIo(input);
diff --git a/services/audiopolicy/service/Android.mk b/services/audiopolicy/service/Android.mk
index fdf3eae..80f4eab 100644
--- a/services/audiopolicy/service/Android.mk
+++ b/services/audiopolicy/service/Android.mk
@@ -31,7 +31,8 @@
libmediametrics \
libmediautils \
libeffectsconfig \
- libsensorprivacy
+ libsensorprivacy \
+ soundtrigger_middleware-aidl-cpp
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
libsensorprivacy
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 6de0c80..5b81b9d 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -17,10 +17,13 @@
#define LOG_TAG "AudioPolicyClientImpl"
//#define LOG_NDEBUG 0
-#include <soundtrigger/SoundTrigger.h>
-#include <utils/Log.h>
#include "AudioPolicyService.h"
+#include <android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.h>
+#include <utils/Log.h>
+
+#include "BinderProxy.h"
+
namespace android {
/* implementation of the client interface from the policy manager */
@@ -239,4 +242,12 @@
return AudioSystem::newAudioUniqueId(use);
}
+void AudioPolicyService::AudioPolicyClient::setSoundTriggerCaptureState(bool active) {
+ using media::soundtrigger_middleware::ISoundTriggerMiddlewareService;
+
+ static BinderProxy<ISoundTriggerMiddlewareService>
+ proxy("soundtrigger_middleware");
+ proxy.waitServiceOrDie()->setExternalCaptureState(active);
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c6fff63..135b3ac 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -717,6 +717,8 @@
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
+ void setSoundTriggerCaptureState(bool active) override;
+
private:
AudioPolicyService *mAudioPolicyService;
};
diff --git a/services/audiopolicy/service/BinderProxy.h b/services/audiopolicy/service/BinderProxy.h
new file mode 100644
index 0000000..516e84d
--- /dev/null
+++ b/services/audiopolicy/service/BinderProxy.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <type_traits>
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// A simple utility that caches a proxy for a service and handles death notification.
+// Typically, intended to be used as a static-lifetime object.
+//
+// Example usage:
+// static BinderProxy<IMyInterface> myInterface("my_interface_svc");
+// ...
+// myInterface.waitServiceOrDie()->doSomething();
+//
+// If the service is unavailable, will wait until it becomes available.
+// Will die if the service doesn't implement the requested interface, or cannot be used for
+// permission reasons.
+template<typename ServiceType>
+class BinderProxy {
+public:
+ static_assert(std::is_base_of_v<IInterface, ServiceType>,
+ "Service type must be a sub-type of IInterface.");
+
+ explicit BinderProxy(std::string_view serviceName)
+ : mServiceName(serviceName), mDeathRecipient(new DeathRecipient(this)) {}
+
+ ~BinderProxy() {
+ if (mDelegate != nullptr) {
+ sp<IBinder> binder = IInterface::asBinder(mDelegate);
+ if (binder != nullptr) {
+ binder->unlinkToDeath(mDeathRecipient);
+ }
+ }
+ }
+
+ sp<ServiceType> waitServiceOrDie() {
+ std::lock_guard<std::mutex> _l(mDelegateMutex);
+ if (mDelegate == nullptr) {
+ mDelegate = waitForService<ServiceType>(String16(mServiceName.c_str()));
+ LOG_ALWAYS_FATAL_IF(mDelegate == nullptr,
+ "Service %s doesn't implement the required interface.",
+ mServiceName.c_str());
+ sp<IBinder> binder = IInterface::asBinder(mDelegate);
+ if (binder != nullptr) {
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+ return mDelegate;
+ }
+
+private:
+ sp<ServiceType> mDelegate;
+ std::mutex mDelegateMutex;
+ const std::string mServiceName;
+ sp<IBinder::DeathRecipient> mDeathRecipient;
+
+ class DeathRecipient : public IBinder::DeathRecipient {
+ public:
+ DeathRecipient(BinderProxy* proxy) : mProxy(proxy) {}
+
+ void binderDied(const wp<IBinder>&) override {
+ mProxy->binderDied();
+ }
+
+ private:
+ BinderProxy* const mProxy;
+ };
+
+ void binderDied() {
+ std::lock_guard<std::mutex> _l(mDelegateMutex);
+ mDelegate.clear();
+ ALOGW("Binder died: %s", mServiceName.c_str());
+ }
+};
+
+} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index b92a2e6..c628e70 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -86,6 +86,7 @@
void setEffectSuspended(int effectId __unused,
audio_session_t sessionId __unused,
bool suspended __unused) {}
+ void setSoundTriggerCaptureState(bool active __unused) override {};
};
} // namespace android
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index c50a3c6..9cc15cd 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -26,6 +26,7 @@
"CameraFlashlight.cpp",
"common/Camera2ClientBase.cpp",
"common/CameraDeviceBase.cpp",
+ "common/CameraOfflineSessionBase.cpp",
"common/CameraProviderManager.cpp",
"common/FrameProcessorBase.cpp",
"api1/CameraClient.cpp",
@@ -45,6 +46,7 @@
"api2/HeicCompositeStream.cpp",
"device1/CameraHardwareInterface.cpp",
"device3/Camera3Device.cpp",
+ "device3/Camera3OfflineSession.cpp",
"device3/Camera3Stream.cpp",
"device3/Camera3IOStreamBase.cpp",
"device3/Camera3InputStream.cpp",
@@ -110,6 +112,7 @@
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.5",
+ "android.hardware.camera.device@3.6"
],
export_shared_lib_headers: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index b704573..18ed3a5 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2776,6 +2776,20 @@
// ----------------------------------------------------------------------------
+sp<CameraService> CameraService::OfflineClient::sCameraService;
+
+status_t CameraService::OfflineClient::startCameraOps() {
+ // TODO
+ return OK;
+}
+
+status_t CameraService::OfflineClient::finishCameraOps() {
+ // TODO
+ return OK;
+}
+
+// ----------------------------------------------------------------------------
+
void CameraService::Client::notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras) {
(void) resultExtras;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1f40fc3..dae9c09 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -71,6 +71,7 @@
public:
class Client;
class BasicClient;
+ class OfflineClient;
// The effective API level. The Camera2 API running in LEGACY mode counts as API_1.
enum apiLevel {
@@ -401,6 +402,87 @@
int mCameraId; // All API1 clients use integer camera IDs
}; // class Client
+
+ // Client for offline session. Note that offline session client does not affect camera service's
+ // client arbitration logic. It is camera HAL's decision to decide whether a normal camera
+ // client is conflicting with existing offline client(s).
+ // The other distinctive difference between offline clients and normal clients is that normal
+ // clients are created through ICameraService binder calls, while the offline session client
+ // is created through ICameraDeviceUser::switchToOffline call.
+ class OfflineClient : public virtual RefBase {
+
+ virtual status_t dump(int fd, const Vector<String16>& args) = 0;
+
+ // Block the client form using the camera
+ virtual void block() = 0;
+
+ // Return the package name for this client
+ virtual String16 getPackageName() const = 0;
+
+ // Notify client about a fatal error
+ // TODO: maybe let impl notify within block?
+ virtual void notifyError(int32_t errorCode,
+ const CaptureResultExtras& resultExtras) = 0;
+
+ // Get the UID of the application client using this
+ virtual uid_t getClientUid() const = 0;
+
+ // Get the PID of the application client using this
+ virtual int getClientPid() const = 0;
+
+ protected:
+ OfflineClient(const sp<CameraService>& cameraService,
+ const String16& clientPackageName,
+ const String8& cameraIdStr,
+ int clientPid,
+ uid_t clientUid,
+ int servicePid): mCameraIdStr(cameraIdStr),
+ mClientPackageName(clientPackageName), mClientPid(clientPid),
+ mClientUid(clientUid), mServicePid(servicePid) {
+ if (sCameraService == nullptr) {
+ sCameraService = cameraService;
+ }
+ }
+
+ virtual ~OfflineClient() { /*TODO*/ }
+
+ // these are initialized in the constructor.
+ static sp<CameraService> sCameraService;
+ const String8 mCameraIdStr;
+ String16 mClientPackageName;
+ pid_t mClientPid;
+ const uid_t mClientUid;
+ const pid_t mServicePid;
+ bool mDisconnected;
+
+ // - The app-side Binder interface to receive callbacks from us
+ sp<IBinder> mRemoteBinder; // immutable after constructor
+
+ // permissions management
+ status_t startCameraOps();
+ status_t finishCameraOps();
+
+ private:
+ std::unique_ptr<AppOpsManager> mAppOpsManager = nullptr;
+
+ class OpsCallback : public BnAppOpsCallback {
+ public:
+ explicit OpsCallback(wp<OfflineClient> client) : mClient(client) {}
+ virtual void opChanged(int32_t /*op*/, const String16& /*packageName*/) {
+ //TODO
+ }
+
+ private:
+ wp<OfflineClient> mClient;
+
+ }; // class OpsCallback
+
+ sp<OpsCallback> mOpsCallback;
+
+ // IAppOpsCallback interface, indirected through opListener
+ // virtual void opChanged(int32_t op, const String16& packageName);
+ }; // class OfflineClient
+
/**
* A listener class that implements the LISTENER interface for use with a ClientManager, and
* implements the following methods:
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 27bebde..28421ba 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1901,6 +1901,80 @@
return binder::Status::ok();
}
+binder::Status CameraDeviceClient::switchToOffline(
+ const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+ const std::vector<view::Surface>& offlineOutputs,
+ /*out*/
+ sp<hardware::camera2::ICameraOfflineSession>* session) {
+ ATRACE_CALL();
+
+ binder::Status res;
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+
+ if (!mDevice.get()) {
+ return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+ }
+
+ if (offlineOutputs.empty()) {
+ String8 msg = String8::format("Offline outputs must not be empty");
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+
+ if (session == nullptr) {
+ String8 msg = String8::format("Invalid offline session");
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+
+ std::vector<int32_t> offlineStreamIds(offlineOutputs.size());
+ for (auto& surface : offlineOutputs) {
+ sp<IBinder> binder = IInterface::asBinder(surface.graphicBufferProducer);
+ ssize_t index = mStreamMap.indexOfKey(binder);
+ if (index == NAME_NOT_FOUND) {
+ String8 msg = String8::format("Offline output is invalid");
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+ // TODO: Also check whether the offline output is supported by Hal for offline mode.
+
+ sp<Surface> s = new Surface(surface.graphicBufferProducer);
+ bool isCompositeStream = camera3::DepthCompositeStream::isDepthCompositeStream(s);
+ isCompositeStream |= camera3::HeicCompositeStream::isHeicCompositeStream(s);
+ if (isCompositeStream) {
+ // TODO: Add composite specific handling
+ } else {
+ offlineStreamIds.push_back(mStreamMap.valueAt(index).streamId());
+ }
+ }
+
+ sp<CameraOfflineSessionBase> offlineSession;
+ auto ret = mDevice->switchToOffline(offlineStreamIds, &offlineSession);
+ if (ret != OK) {
+ return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Camera %s: Error switching to offline mode: %s (%d)",
+ mCameraIdStr.string(), strerror(ret), ret);
+ }
+
+ sp<CameraOfflineSessionClient> offlineClient = new CameraOfflineSessionClient(sCameraService,
+ offlineSession, cameraCb, mClientPackageName, mCameraIdStr, mClientPid, mClientUid,
+ mServicePid);
+ ret = offlineClient->initialize();
+ if (ret == OK) {
+ // TODO: We need to update mStreamMap, mConfiguredOutputs
+ } else {
+ return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Camera %s: Failed to initilize offline session: %s (%d)",
+ mCameraIdStr.string(), strerror(ret), ret);
+ }
+
+ *session = offlineClient;
+
+ return binder::Status::ok();
+}
+
status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
return BasicClient::dump(fd, args);
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 7efc5ab..0a8f377 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -23,6 +23,7 @@
#include <camera/camera2/SessionConfiguration.h>
#include <camera/camera2/SubmitInfo.h>
+#include "CameraOfflineSessionClient.h"
#include "CameraService.h"
#include "common/FrameProcessorBase.h"
#include "common/Camera2ClientBase.h"
@@ -157,6 +158,12 @@
virtual binder::Status getGlobalAudioRestriction(/*out*/int32_t* outMode) override;
+ virtual binder::Status switchToOffline(
+ const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+ const std::vector<view::Surface>& offlineOutputs,
+ /*out*/
+ sp<hardware::camera2::ICameraOfflineSession>* session) override;
+
/**
* Interface used by CameraService
*/
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
new file mode 100644
index 0000000..cb83e29
--- /dev/null
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
+#define ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
+
+#include <android/hardware/camera2/BnCameraOfflineSession.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include "CameraService.h"
+
+namespace android {
+
+using android::hardware::camera2::ICameraDeviceCallbacks;
+
+class CameraOfflineSessionClient :
+ public CameraService::OfflineClient,
+ public hardware::camera2::BnCameraOfflineSession
+ // public camera2::FrameProcessorBase::FilteredListener?
+{
+public:
+ CameraOfflineSessionClient(
+ const sp<CameraService>& cameraService,
+ sp<CameraOfflineSessionBase> session,
+ const sp<ICameraDeviceCallbacks>& remoteCallback,
+ const String16& clientPackageName,
+ const String8& cameraIdStr,
+ int clientPid, uid_t clientUid, int servicePid) :
+ CameraService::OfflineClient(cameraService, clientPackageName,
+ cameraIdStr, clientPid, clientUid, servicePid),
+ mRemoteCallback(remoteCallback), mOfflineSession(session) {}
+
+ ~CameraOfflineSessionClient() {}
+
+ virtual binder::Status disconnect() override { return binder::Status::ok(); }
+
+ virtual status_t dump(int /*fd*/, const Vector<String16>& /*args*/) override {
+ return OK;
+ }
+
+ // Block the client form using the camera
+ virtual void block() override {};
+
+ // Return the package name for this client
+ virtual String16 getPackageName() const override { String16 ret; return ret; };
+
+ // Notify client about a fatal error
+ // TODO: maybe let impl notify within block?
+ virtual void notifyError(int32_t /*errorCode*/,
+ const CaptureResultExtras& /*resultExtras*/) override {}
+
+ // Get the UID of the application client using this
+ virtual uid_t getClientUid() const override { return 0; }
+
+ // Get the PID of the application client using this
+ virtual int getClientPid() const override { return 0; }
+
+ status_t initialize() {
+ // TODO: Talk to camera service to add the offline session client book keeping
+ return OK;
+ }
+private:
+ sp<CameraOfflineSessionBase> mSession;
+
+ sp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
+ // This class is responsible to convert HAL callbacks to AIDL callbacks
+
+ sp<CameraOfflineSessionBase> mOfflineSession;
+};
+
+} // namespace android
+
+#endif // ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 935bc37..1026fdf 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -35,6 +35,8 @@
#include "device3/Camera3StreamInterface.h"
#include "binder/Status.h"
+#include "CameraOfflineSessionBase.h"
+
namespace android {
class CameraProviderManager;
@@ -389,6 +391,13 @@
* requests to complete, based on their settings
*/
virtual nsecs_t getExpectedInFlightDuration() = 0;
+
+ /**
+ * switch to offline session
+ */
+ virtual status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) = 0;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.cpp b/services/camera/libcameraservice/common/CameraOfflineSessionBase.cpp
new file mode 100644
index 0000000..ff673a9
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "CameraOfflineSessionBase.h"
+
+namespace android {
+
+/**
+ * Base class destructors
+ */
+CameraOfflineSessionBase::~CameraOfflineSessionBase() {
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
new file mode 100644
index 0000000..3862521
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERAOFFLINESESSIONBASE_H
+#define ANDROID_SERVERS_CAMERA_CAMERAOFFLINESESSIONBASE_H
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include "camera/CaptureResult.h"
+
+namespace android {
+
+class CameraOfflineSessionBase : public virtual RefBase {
+ public:
+ virtual ~CameraOfflineSessionBase();
+
+ // The session's original camera ID
+ virtual const String8& getId() const = 0;
+
+ virtual status_t disconnect() = 0;
+
+ virtual status_t dump(int fd) = 0;
+
+ virtual status_t abort() = 0;
+
+ /**
+ * Capture result passing
+ */
+ virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
+
+ virtual status_t getNextResult(CaptureResult *frame) = 0;
+
+ // TODO: notification passing path
+}; // class CameraOfflineSessionBase
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2541365..4e5c8d6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -58,6 +58,7 @@
#include "device3/Camera3InputStream.h"
#include "device3/Camera3DummyStream.h"
#include "device3/Camera3SharedOutputStream.h"
+#include "device3/Camera3OfflineSession.h"
#include "CameraService.h"
#include "utils/CameraThreadState.h"
@@ -206,7 +207,15 @@
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
}
- mInterface = new HalInterface(session, queue, mUseHalBufManager);
+ camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ for (size_t i = 0; i < capabilities.count; i++) {
+ uint8_t capability = capabilities.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
+ mSupportOfflineProcessing = true;
+ }
+ }
+
+ mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
std::string providerType;
mVendorTagId = manager->getProviderTagIdLocked(mId.string());
mTagMonitor.initialize(mVendorTagId);
@@ -227,9 +236,8 @@
maxVersion.get_major(), maxVersion.get_minor());
bool isMonochrome = false;
- camera_metadata_entry_t entry = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
- for (size_t i = 0; i < entry.count; i++) {
- uint8_t capability = entry.data.u8[i];
+ for (size_t i = 0; i < capabilities.count; i++) {
+ uint8_t capability = capabilities.data.u8[i];
if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
isMonochrome = true;
}
@@ -4045,13 +4053,18 @@
Camera3Device::HalInterface::HalInterface(
sp<ICameraDeviceSession> &session,
std::shared_ptr<RequestMetadataQueue> queue,
- bool useHalBufManager) :
+ bool useHalBufManager, bool supportOfflineProcessing) :
mHidlSession(session),
mRequestMetadataQueue(queue),
mUseHalBufManager(useHalBufManager),
- mIsReconfigurationQuerySupported(true) {
+ mIsReconfigurationQuerySupported(true),
+ mSupportOfflineProcessing(supportOfflineProcessing) {
// Check with hardware service manager if we can downcast these interfaces
// Somewhat expensive, so cache the results at startup
+ auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_6.isOk()) {
+ mHidlSession_3_6 = castResult_3_6;
+ }
auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
if (castResult_3_5.isOk()) {
mHidlSession_3_5 = castResult_3_5;
@@ -4066,18 +4079,22 @@
}
}
-Camera3Device::HalInterface::HalInterface() : mUseHalBufManager(false) {}
+Camera3Device::HalInterface::HalInterface() :
+ mUseHalBufManager(false),
+ mSupportOfflineProcessing(false) {}
Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
mHidlSession(other.mHidlSession),
mRequestMetadataQueue(other.mRequestMetadataQueue),
- mUseHalBufManager(other.mUseHalBufManager) {}
+ mUseHalBufManager(other.mUseHalBufManager),
+ mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
bool Camera3Device::HalInterface::valid() {
return (mHidlSession != nullptr);
}
void Camera3Device::HalInterface::clear() {
+ mHidlSession_3_6.clear();
mHidlSession_3_5.clear();
mHidlSession_3_4.clear();
mHidlSession_3_3.clear();
@@ -4753,6 +4770,38 @@
}
}
+status_t Camera3Device::HalInterface::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession) {
+ ATRACE_NAME("CameraHal::switchToOffline");
+ if (!valid() || mHidlSession_3_6 == nullptr) {
+ ALOGE("%s called on invalid camera!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ if (offlineSessionInfo == nullptr || offlineSession == nullptr) {
+ ALOGE("%s: offlineSessionInfo and offlineSession must not be null!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
+
+ auto resultCallback =
+ [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
+ status = s;
+ *offlineSessionInfo = info;
+ *offlineSession = session;
+ };
+ auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
+
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ return CameraProviderManager::mapToStatusT(status);
+}
+
void Camera3Device::HalInterface::getInflightBufferKeys(
std::vector<std::pair<int32_t, int32_t>>* out) {
std::lock_guard<std::mutex> lock(mInflightLock);
@@ -5524,6 +5573,7 @@
Mutex::Autolock l(mRequestLock);
mNextRequests.clear();
}
+ mRequestSubmittedSignal.signal();
return submitRequestSuccess;
}
@@ -5903,6 +5953,32 @@
mStreamIdsToBeDrained = streamIds;
}
+status_t Camera3Device::RequestThread::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession) {
+ Mutex::Autolock l(mRequestLock);
+ clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
+
+ // Theoretically we should also check for mRepeatingRequests.empty(), but the API interface
+ // is serialized by mInterfaceLock so skip that check.
+ bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+ while (!queueEmpty) {
+ status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: request thread failed to submit a request within timeout!", __FUNCTION__);
+ return res;
+ } else if (res != OK) {
+ ALOGE("%s: request thread failed to submit a request: %s (%d)!",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+ }
+ return mInterface->switchToOffline(
+ streamsToKeep, offlineSessionInfo, offlineSession);
+}
+
nsecs_t Camera3Device::getExpectedInFlightDuration() {
ATRACE_CALL();
Mutex::Autolock al(mInFlightLock);
@@ -6812,4 +6888,34 @@
return res;
}
+status_t Camera3Device::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) {
+ ATRACE_CALL();
+ if (session == nullptr) {
+ ALOGE("%s: session must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ // 1. Stop repeating request, wait until request thread submitted all requests, then
+ // call HAL switchToOffline
+ hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
+
+ mRequestThread->switchToOffline(streamsToKeep, &offlineSessionInfo, &offlineSession);
+
+
+ // 2. Verify offlineSessionInfo
+ // 3. create Camera3OfflineSession and transfer object ownership
+ // (streams, inflight requests, buffer caches)
+ *session = new Camera3OfflineSession(mId);
+
+ // 4. Delete unneeded streams
+ // 5. Verify Camera3Device is in unconfigured state
+ return OK;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 2573b48..eabc44d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -34,6 +34,7 @@
#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
@@ -196,6 +197,9 @@
nsecs_t getExpectedInFlightDuration() override;
+ status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) override;
+
/**
* Helper functions to map between framework and HIDL values
*/
@@ -282,7 +286,7 @@
public:
HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
std::shared_ptr<RequestMetadataQueue> queue,
- bool useHalBufManager);
+ bool useHalBufManager, bool supportOfflineProcessing);
HalInterface(const HalInterface &other);
HalInterface();
@@ -316,6 +320,11 @@
bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
CameraMetadata& newSessionParams);
+ status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession);
+
// method to extract buffer's unique ID
// return pair of (newlySeenBuffer?, bufferId)
std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
@@ -352,6 +361,8 @@
sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
// Valid if ICameraDeviceSession is @3.5 or newer
sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
+ // Valid if ICameraDeviceSession is @3.6 or newer
+ sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
@@ -424,6 +435,8 @@
const bool mUseHalBufManager;
bool mIsReconfigurationQuerySupported;
+
+ const bool mSupportOfflineProcessing;
};
sp<HalInterface> mInterface;
@@ -842,6 +855,11 @@
void signalPipelineDrain(const std::vector<int>& streamIds);
+ status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession);
+
protected:
virtual bool threadLoop();
@@ -862,6 +880,9 @@
static const nsecs_t kRequestTimeout = 50e6; // 50 ms
+ // TODO: does this need to be adjusted for long exposure requests?
+ static const nsecs_t kRequestSubmitTimeout = 200e6; // 200 ms
+
// Used to prepare a batch of requests.
struct NextRequest {
sp<CaptureRequest> captureRequest;
@@ -936,6 +957,7 @@
Mutex mRequestLock;
Condition mRequestSignal;
+ Condition mRequestSubmittedSignal;
RequestList mRequestQueue;
RequestList mRepeatingRequests;
// The next batch of requests being prepped for submission to the HAL, no longer
@@ -1364,6 +1386,9 @@
// Fix up result metadata for monochrome camera.
bool mNeedFixupMonochromeTags;
status_t fixupMonochromeTags(const CameraMetadata& deviceInfo, CameraMetadata& resultMetadata);
+
+ // Whether HAL supports offline processing capability.
+ bool mSupportOfflineProcessing = false;
}; // class Camera3Device
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
new file mode 100644
index 0000000..dc5cbb3
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#define LOG_TAG "Camera3-OffLnSsn"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0 // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+#include <inttypes.h>
+
+#include <utils/Trace.h>
+
+#include "device3/Camera3OfflineSession.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+
+Camera3OfflineSession::Camera3OfflineSession(const String8 &id):
+ mId(id)
+{
+ ATRACE_CALL();
+ ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.string());
+}
+
+Camera3OfflineSession::~Camera3OfflineSession()
+{
+ ATRACE_CALL();
+ ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
+}
+
+const String8& Camera3OfflineSession::getId() const {
+ return mId;
+}
+
+status_t Camera3OfflineSession::initialize(
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> /*hidlSession*/) {
+ ATRACE_CALL();
+ return OK;
+}
+
+status_t Camera3OfflineSession::dump(int /*fd*/) {
+ ATRACE_CALL();
+ return OK;
+}
+
+status_t Camera3OfflineSession::abort() {
+ ATRACE_CALL();
+ return OK;
+}
+
+status_t Camera3OfflineSession::disconnect() {
+ ATRACE_CALL();
+ return OK;
+}
+
+status_t Camera3OfflineSession::waitForNextFrame(nsecs_t /*timeout*/) {
+ ATRACE_CALL();
+ return OK;
+}
+
+status_t Camera3OfflineSession::getNextResult(CaptureResult* /*frame*/) {
+ ATRACE_CALL();
+ return OK;
+}
+
+hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& /*results*/) {
+ return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& /*results*/) {
+ return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::notify(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& /*msgs*/) {
+ return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& /*bufReqs*/,
+ requestStreamBuffers_cb /*_hidl_cb*/) {
+ return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& /*buffers*/) {
+ return hardware::Void();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
new file mode 100644
index 0000000..30e8c4f
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA3OFFLINESESSION_H
+#define ANDROID_SERVERS_CAMERA3OFFLINESESSION_H
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include <android/hardware/camera/device/3.6/ICameraOfflineSession.h>
+#include <fmq/MessageQueue.h>
+
+#include "common/CameraOfflineSessionBase.h"
+
+#include "device3/Camera3BufferManager.h"
+#include "device3/DistortionMapper.h"
+#include "utils/TagMonitor.h"
+#include "utils/LatencyHistogram.h"
+#include <camera_metadata_hidden.h>
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3Stream;
+class Camera3OutputStreamInterface;
+class Camera3StreamInterface;
+
+} // namespace camera3
+
+/**
+ * Camera3OfflineSession for offline session defined in HIDL ICameraOfflineSession@3.6 or higher
+ */
+class Camera3OfflineSession :
+ public CameraOfflineSessionBase,
+ virtual public hardware::camera::device::V3_5::ICameraDeviceCallback {
+
+ public:
+
+ // initialize by Camera3Device. Camera3Device must send all info in separate argument.
+ // monitored tags
+ // mUseHalBufManager
+ // mUsePartialResult
+ // mNumPartialResults
+ explicit Camera3OfflineSession(const String8& id);
+
+ virtual ~Camera3OfflineSession();
+
+ status_t initialize(
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> hidlSession);
+
+ /**
+ * CameraOfflineSessionBase interface
+ */
+ const String8& getId() const override;
+
+ status_t disconnect() override;
+
+ status_t dump(int fd) override;
+
+ status_t abort() override;
+
+ // methods for capture result passing
+ status_t waitForNextFrame(nsecs_t timeout) override;
+ status_t getNextResult(CaptureResult *frame) override;
+
+ // TODO: methods for notification (error/idle/finished etc) passing
+
+ /**
+ * End of CameraOfflineSessionBase interface
+ */
+
+ /**
+ * HIDL ICameraDeviceCallback interface
+ */
+
+ /**
+ * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
+ */
+
+ hardware::Return<void> processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) override;
+ hardware::Return<void> processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) override;
+ hardware::Return<void> notify(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
+
+ hardware::Return<void> requestStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) override;
+
+ hardware::Return<void> returnStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
+
+ /**
+ * End of CameraOfflineSessionBase interface
+ */
+
+ private:
+
+ // Camera device ID
+ const String8 mId;
+
+}; // class Camera3OfflineSession
+
+}; // namespace android
+
+#endif
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 9e814d1..a6cd224 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -61,13 +61,11 @@
}
::android::binder::Status MediaExtractorService::makeIDataSource(
- const base::unique_fd &fd,
+ base::unique_fd fd,
int64_t offset,
int64_t length,
::android::sp<::android::IDataSource>* _aidl_return) {
- // the caller will close the fd owned by the unique_fd upon return of this function,
- // so we need to dup() it to retain it.
- sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromFd(dup(fd.get()), offset, length);
+ sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromFd(fd.release(), offset, length);
*_aidl_return = CreateIDataSourceFromDataSource(source);
return binder::Status::ok();
}
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 1b61c4b..1b40bf9 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -37,7 +37,7 @@
::android::sp<::android::IMediaExtractor>* _aidl_return);
virtual ::android::binder::Status makeIDataSource(
- const base::unique_fd &fd,
+ base::unique_fd fd,
int64_t offset,
int64_t length,
::android::sp<::android::IDataSource>* _aidl_return);
diff --git a/services/soundtrigger/Android.bp b/services/soundtrigger/Android.bp
deleted file mode 100644
index 600f4a3..0000000
--- a/services/soundtrigger/Android.bp
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 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.
-
-cc_library_shared {
- name: "libsoundtriggerservice",
-
- srcs: [
- "SoundTriggerHwService.cpp",
- "SoundTriggerHalHidl.cpp",
- ],
-
- shared_libs: [
- "liblog",
- "libutils",
- "libbinder",
- "libcutils",
- "libhardware",
- "libsoundtrigger",
- "libaudioclient",
- "libaudioutils",
- "libmediautils",
-
- "libhidlbase",
- "libhidlmemory",
- "libbase",
- "libaudiohal",
- "libaudiohal_deathhandler",
- "android.hardware.soundtrigger@2.0",
- "android.hardware.soundtrigger@2.1",
- "android.hardware.soundtrigger@2.2",
- "android.hardware.soundtrigger@2.3",
- "android.hardware.audio.common@2.0",
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
- ],
-
- include_dirs: ["frameworks/av/services/audioflinger"],
-
- cflags: [
- "-Wall",
- "-Werror",
- ],
-}
diff --git a/services/soundtrigger/OWNERS b/services/soundtrigger/OWNERS
deleted file mode 100644
index e83f6b9..0000000
--- a/services/soundtrigger/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-thorntonc@google.com
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
deleted file mode 100644
index b1d34df..0000000
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ /dev/null
@@ -1,999 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#define LOG_TAG "SoundTriggerHalHidl"
-//#define LOG_NDEBUG 0
-
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <media/audiohal/hidl/HalDeathHandler.h>
-#include <utils/Log.h>
-#include "SoundTriggerHalHidl.h"
-#include <hidlmemory/mapping.h>
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-
-namespace android {
-
-using ::android::hardware::ProcessState;
-using ::android::hardware::Return;
-using ::android::hardware::Status;
-using ::android::hardware::Void;
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::hidl_memory;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-
-namespace {
-
-// Backs up by the vector with the contents of shared memory.
-// It is assumed that the passed hidl_vector is empty, so it's
-// not cleared if the memory is a null object.
-// The caller needs to keep the returned sp<IMemory> as long as
-// the data is needed.
-std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
- sp<IMemory> memory;
- if (m.size() == 0) {
- return std::make_pair(true, memory);
- }
- memory = mapMemory(m);
- if (memory != nullptr) {
- memory->read();
- vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
- memory->getSize());
- return std::make_pair(true, memory);
- }
- ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
- return std::make_pair(false, memory);
-}
-
-// Moves the data from the vector into allocated shared memory,
-// emptying the vector.
-// It is assumed that the passed hidl_memory is a null object, so it's
-// not reset if the vector is empty.
-// The caller needs to keep the returned sp<IMemory> as long as
-// the data is needed.
-std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
- sp<IMemory> memory;
- if (v->size() == 0) {
- return std::make_pair(true, memory);
- }
- sp<IAllocator> ashmem = IAllocator::getService("ashmem");
- if (ashmem == 0) {
- ALOGE("Failed to retrieve ashmem allocator service");
- return std::make_pair(false, memory);
- }
- bool success = false;
- Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
- success = s;
- if (success) *mem = m;
- });
- if (r.isOk() && success) {
- memory = hardware::mapMemory(*mem);
- if (memory != 0) {
- memory->update();
- memcpy(memory->getPointer(), v->data(), v->size());
- memory->commit();
- v->resize(0);
- return std::make_pair(true, memory);
- } else {
- ALOGE("Failed to map allocated ashmem");
- }
- } else {
- ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
- }
- return std::make_pair(false, memory);
-}
-
-} // namespace
-
-/* static */
-sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName)
-{
- return new SoundTriggerHalHidl(moduleName);
-}
-
-int SoundTriggerHalHidl::getProperties(struct sound_trigger_properties *properties)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- ISoundTriggerHw::Properties halProperties;
- Return<void> hidlReturn;
- int ret;
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->getProperties([&](int rc, auto res) {
- ret = rc;
- halProperties = res;
- ALOGI("getProperties res implementor %s", res.implementor.c_str());
- });
- }
-
- if (hidlReturn.isOk()) {
- if (ret == 0) {
- convertPropertiesFromHal(properties, &halProperties);
- }
- } else {
- ALOGE("getProperties error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
- ALOGI("getProperties ret %d", ret);
- return ret;
-}
-
-int SoundTriggerHalHidl::loadSoundModel(struct sound_trigger_sound_model *sound_model,
- sound_model_callback_t callback,
- void *cookie,
- sound_model_handle_t *handle)
-{
- if (handle == NULL) {
- return -EINVAL;
- }
-
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- uint32_t modelId;
- {
- AutoMutex lock(mLock);
- do {
- modelId = nextUniqueId();
- ALOGI("loadSoundModel modelId %u", modelId);
- sp<SoundModel> model = mSoundModels.valueFor(modelId);
- ALOGI("loadSoundModel model %p", model.get());
- } while (mSoundModels.valueFor(modelId) != 0 && modelId != 0);
- }
- LOG_ALWAYS_FATAL_IF(modelId == 0,
- "loadSoundModel(): wrap around in sound model IDs, num loaded models %zd",
- mSoundModels.size());
-
- Return<void> hidlReturn;
- int ret;
- SoundModelHandle halHandle;
- sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
- sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
- if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
- if (soundtrigger_2_2) {
- V2_2_ISoundTriggerHw::PhraseSoundModel halSoundModel;
- auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
- if (result.first) {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_2->loadPhraseSoundModel_2_1(
- halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- } else {
- return NO_MEMORY;
- }
- } else if (soundtrigger_2_1) {
- V2_1_ISoundTriggerHw::PhraseSoundModel halSoundModel;
- auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
- if (result.first) {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_1->loadPhraseSoundModel_2_1(
- halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- } else {
- return NO_MEMORY;
- }
- } else {
- ISoundTriggerHw::PhraseSoundModel halSoundModel;
- convertPhraseSoundModelToHal(&halSoundModel, sound_model);
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->loadPhraseSoundModel(
- halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- }
- } else {
- if (soundtrigger_2_2) {
- V2_2_ISoundTriggerHw::SoundModel halSoundModel;
- auto result = convertSoundModelToHal(&halSoundModel, sound_model);
- if (result.first) {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_2->loadSoundModel_2_1(halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- } else {
- return NO_MEMORY;
- }
- } else if (soundtrigger_2_1) {
- V2_1_ISoundTriggerHw::SoundModel halSoundModel;
- auto result = convertSoundModelToHal(&halSoundModel, sound_model);
- if (result.first) {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_1->loadSoundModel_2_1(halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- } else {
- return NO_MEMORY;
- }
- } else {
- ISoundTriggerHw::SoundModel halSoundModel;
- convertSoundModelToHal(&halSoundModel, sound_model);
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->loadSoundModel(halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- }
- }
-
- if (hidlReturn.isOk()) {
- if (ret == 0) {
- AutoMutex lock(mLock);
- *handle = (sound_model_handle_t)modelId;
- sp<SoundModel> model = new SoundModel(*handle, callback, cookie, halHandle);
- mSoundModels.add(*handle, model);
- }
- } else {
- ALOGE("loadSoundModel error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
-
- return ret;
-}
-
-int SoundTriggerHalHidl::unloadSoundModel(sound_model_handle_t handle)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- sp<SoundModel> model = removeModel(handle);
- if (model == 0) {
- ALOGE("unloadSoundModel model not found for handle %u", handle);
- return -EINVAL;
- }
-
- Return<int32_t> hidlReturn(0);
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle);
- }
-
- if (!hidlReturn.isOk()) {
- ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
-
- return hidlReturn;
-}
-
-int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle,
- const struct sound_trigger_recognition_config *config,
- recognition_callback_t callback,
- void *cookie)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- sp<SoundModel> model = getModel(handle);
- if (model == 0) {
- ALOGE("startRecognition model not found for handle %u", handle);
- return -EINVAL;
- }
-
- model->mRecognitionCallback = callback;
- model->mRecognitionCookie = cookie;
-
- sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
- sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
- Return<int32_t> hidlReturn(0);
-
- if (soundtrigger_2_2) {
- V2_2_ISoundTriggerHw::RecognitionConfig halConfig;
- auto result = convertRecognitionConfigToHal(&halConfig, config);
- if (result.first) {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_2->startRecognition_2_1(
- model->mHalHandle, halConfig, this, handle);
- } else {
- return NO_MEMORY;
- }
- } else if (soundtrigger_2_1) {
- V2_1_ISoundTriggerHw::RecognitionConfig halConfig;
- auto result = convertRecognitionConfigToHal(&halConfig, config);
- if (result.first) {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_1->startRecognition_2_1(
- model->mHalHandle, halConfig, this, handle);
- } else {
- return NO_MEMORY;
- }
- } else {
- ISoundTriggerHw::RecognitionConfig halConfig;
- convertRecognitionConfigToHal(&halConfig, config);
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle);
- }
- }
-
- if (!hidlReturn.isOk()) {
- ALOGE("startRecognition error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
- return hidlReturn;
-}
-
-int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- sp<SoundModel> model = getModel(handle);
- if (model == 0) {
- ALOGE("stopRecognition model not found for handle %u", handle);
- return -EINVAL;
- }
-
- Return<int32_t> hidlReturn(0);
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->stopRecognition(model->mHalHandle);
- }
-
- if (!hidlReturn.isOk()) {
- ALOGE("stopRecognition error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
- return hidlReturn;
-}
-
-int SoundTriggerHalHidl::stopAllRecognitions()
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- Return<int32_t> hidlReturn(0);
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->stopAllRecognitions();
- }
-
- if (!hidlReturn.isOk()) {
- ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
- return hidlReturn;
-}
-
-int SoundTriggerHalHidl::getModelState(sound_model_handle_t handle)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (soundtrigger == 0) {
- return -ENODEV;
- }
-
- sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
- if (soundtrigger_2_2 == 0) {
- ALOGE("getModelState not supported");
- return -ENODEV;
- }
-
- sp<SoundModel> model = getModel(handle);
- if (model == 0) {
- ALOGE("getModelState model not found for handle %u", handle);
- return -EINVAL;
- }
-
- int ret = NO_ERROR;
- Return<int32_t> hidlReturn(0);
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_2->getModelState(model->mHalHandle);
- }
- if (!hidlReturn.isOk()) {
- ALOGE("getModelState error %s", hidlReturn.description().c_str());
- ret = FAILED_TRANSACTION;
- }
- return ret;
-}
-
-int SoundTriggerHalHidl::setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param, int32_t value)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (!soundtrigger) {
- return -ENODEV;
- }
-
- sp<V2_3_ISoundTriggerHw> soundtrigger_2_3 = toService2_3(soundtrigger);
- if (!soundtrigger_2_3) {
- ALOGE("setParameter not supported");
- return -ENOSYS;
- }
-
- sp<SoundModel> model = getModel(handle);
- if (!model) {
- ALOGE("setParameter model not found for handle %u", handle);
- return -EINVAL;
- }
-
- V2_3_ModelParameter halParam;
- convertModelParameterToHal(&halParam, model_param);
-
- Return<int32_t> hidlReturn(0);
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_3->setParameter(model->mHalHandle, halParam, value);
- }
- if (!hidlReturn.isOk()) {
- ALOGE("getModelState error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
-
- return hidlReturn;
-}
-
-int SoundTriggerHalHidl::getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param, int32_t* value)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (!soundtrigger) {
- return -ENODEV;
- }
-
- sp<V2_3_ISoundTriggerHw> soundtrigger_2_3 = toService2_3(soundtrigger);
- if (!soundtrigger_2_3) {
- ALOGE("getParameter not supported");
- return -ENOSYS;
- }
-
- if (value == NULL) {
- ALOGE("getParameter invalid value pointer");
- return -EINVAL;
- }
-
- sp<SoundModel> model = getModel(handle);
- if (!model) {
- ALOGE("getParameter model not found for handle %u", handle);
- return -EINVAL;
- }
-
- V2_3_ModelParameter halParam;
- convertModelParameterToHal(&halParam, model_param);
-
- Return<void> hidlReturn;
- int32_t hidlStatus;
- int32_t hidlValue;
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_3->getParameter(model->mHalHandle, halParam,
- [&](int32_t retStatus, int32_t retValue) {
- hidlStatus = retStatus;
- hidlValue = retValue;
- });
- }
- if (!hidlReturn.isOk()) {
- ALOGE("getModelState error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
-
- *value = hidlValue;
- return hidlStatus;
-}
-
-int SoundTriggerHalHidl::queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param,
- sound_trigger_model_parameter_range_t* param_range)
-{
- sp<ISoundTriggerHw> soundtrigger = getService();
- if (!soundtrigger) {
- return -ENODEV;
- }
-
- sp<V2_3_ISoundTriggerHw> soundtrigger_2_3 = toService2_3(soundtrigger);
- if (!soundtrigger_2_3) {
- ALOGE("queryParameter not supported");
- return -ENOSYS;
- }
-
- sp<SoundModel> model = getModel(handle);
- if (!model) {
- ALOGE("queryParameter model not found for handle %u", handle);
- return -EINVAL;
- }
-
- V2_3_ModelParameter halParam;
- convertModelParameterToHal(&halParam, model_param);
-
- Return<void> hidlReturn;
- int32_t hidlStatus;
- V2_3_OptionalModelParameterRange hidlValue;
- {
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger_2_3->queryParameter(model->mHalHandle, halParam,
- [&](int32_t retStatus, V2_3_OptionalModelParameterRange retValue) {
- hidlStatus = retStatus;
- hidlValue = retValue;
- });
- }
- if (!hidlReturn.isOk()) {
- ALOGE("queryParameter error %s", hidlReturn.description().c_str());
- return FAILED_TRANSACTION;
- }
-
- if (hidlStatus != 0) {
- ALOGE("queryParameter error code: %d", hidlStatus);
- return hidlStatus;
- }
-
- if (hidlValue.getDiscriminator() ==
- V2_3_OptionalModelParameterRange::hidl_discriminator::noinit) {
- return -1;
- }
-
- param_range->start = hidlValue.range().start;
- param_range->end = hidlValue.range().end;
-
- return 0;
-}
-
-SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
- : mModuleName(moduleName), mNextUniqueId(1)
-{
- LOG_ALWAYS_FATAL_IF(strcmp(mModuleName, "primary") != 0,
- "Treble soundtrigger only supports primary module");
-}
-
-SoundTriggerHalHidl::~SoundTriggerHalHidl()
-{
-}
-
-sp<ISoundTriggerHw> SoundTriggerHalHidl::getService()
-{
- AutoMutex lock(mLock);
- if (mISoundTrigger == 0) {
- if (mModuleName == NULL) {
- mModuleName = "primary";
- }
- mISoundTrigger = ISoundTriggerHw::getService();
- if (mISoundTrigger != 0) {
- mISoundTrigger->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
- }
- }
- return mISoundTrigger;
-}
-
-sp<V2_1_ISoundTriggerHw> SoundTriggerHalHidl::toService2_1(const sp<ISoundTriggerHw>& s)
-{
- auto castResult_2_1 = V2_1_ISoundTriggerHw::castFrom(s);
- return castResult_2_1.isOk() ? static_cast<sp<V2_1_ISoundTriggerHw>>(castResult_2_1) : nullptr;
-}
-
-sp<V2_2_ISoundTriggerHw> SoundTriggerHalHidl::toService2_2(const sp<ISoundTriggerHw>& s)
-{
- auto castResult_2_2 = V2_2_ISoundTriggerHw::castFrom(s);
- return castResult_2_2.isOk() ? static_cast<sp<V2_2_ISoundTriggerHw>>(castResult_2_2) : nullptr;
-}
-
-sp<V2_3_ISoundTriggerHw> SoundTriggerHalHidl::toService2_3(const sp<ISoundTriggerHw>& s)
-{
- auto castResult_3_0 = V2_3_ISoundTriggerHw::castFrom(s);
- return castResult_3_0.isOk() ? static_cast<sp<V2_3_ISoundTriggerHw>>(castResult_3_0) : nullptr;
-}
-
-sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
-{
- AutoMutex lock(mLock);
- return mSoundModels.valueFor(handle);
-}
-
-sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::removeModel(sound_model_handle_t handle)
-{
- AutoMutex lock(mLock);
- sp<SoundModel> model = mSoundModels.valueFor(handle);
- mSoundModels.removeItem(handle);
- return model;
-}
-
-uint32_t SoundTriggerHalHidl::nextUniqueId()
-{
- return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId,
- (uint_fast32_t) 1, memory_order_acq_rel);
-}
-
-void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid,
- const sound_trigger_uuid_t *uuid)
-{
- halUuid->timeLow = uuid->timeLow;
- halUuid->timeMid = uuid->timeMid;
- halUuid->versionAndTimeHigh = uuid->timeHiAndVersion;
- halUuid->variantAndClockSeqHigh = uuid->clockSeq;
- memcpy(halUuid->node.data(), &uuid->node[0], sizeof(uuid->node));
-}
-
-void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid,
- const Uuid *halUuid)
-{
- uuid->timeLow = halUuid->timeLow;
- uuid->timeMid = halUuid->timeMid;
- uuid->timeHiAndVersion = halUuid->versionAndTimeHigh;
- uuid->clockSeq = halUuid->variantAndClockSeqHigh;
- memcpy(&uuid->node[0], halUuid->node.data(), sizeof(uuid->node));
-}
-
-void SoundTriggerHalHidl::convertPropertiesFromHal(
- struct sound_trigger_properties *properties,
- const ISoundTriggerHw::Properties *halProperties)
-{
- strlcpy(properties->implementor,
- halProperties->implementor.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
- strlcpy(properties->description,
- halProperties->description.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
- properties->version = halProperties->version;
- convertUuidFromHal(&properties->uuid, &halProperties->uuid);
- properties->max_sound_models = halProperties->maxSoundModels;
- properties->max_key_phrases = halProperties->maxKeyPhrases;
- properties->max_users = halProperties->maxUsers;
- properties->recognition_modes = halProperties->recognitionModes;
- properties->capture_transition = (bool)halProperties->captureTransition;
- properties->max_buffer_ms = halProperties->maxBufferMs;
- properties->concurrent_capture = (bool)halProperties->concurrentCapture;
- properties->trigger_in_event = (bool)halProperties->triggerInEvent;
- properties->power_consumption_mw = halProperties->powerConsumptionMw;
-}
-
-// static
-void SoundTriggerHalHidl::convertModelParameterToHal(V2_3_ModelParameter* halParam,
- sound_trigger_model_parameter_t param)
-{
- switch (param) {
- case MODEL_PARAMETER_THRESHOLD_FACTOR:
- *halParam = V2_3_ModelParameter::THRESHOLD_FACTOR;
- return;
- case MODEL_PARAMETER_INVALID:
- default:
- *halParam = V2_3_ModelParameter::INVALID;
- }
-}
-
-void SoundTriggerHalHidl::convertTriggerPhraseToHal(
- ISoundTriggerHw::Phrase *halTriggerPhrase,
- const struct sound_trigger_phrase *triggerPhrase)
-{
- halTriggerPhrase->id = triggerPhrase->id;
- halTriggerPhrase->recognitionModes = triggerPhrase->recognition_mode;
- halTriggerPhrase->users.setToExternal((uint32_t *)&triggerPhrase->users[0], triggerPhrase->num_users);
- halTriggerPhrase->locale = triggerPhrase->locale;
- halTriggerPhrase->text = triggerPhrase->text;
-}
-
-
-void SoundTriggerHalHidl::convertTriggerPhrasesToHal(
- hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
- struct sound_trigger_phrase_sound_model *keyPhraseModel)
-{
- halTriggerPhrases->resize(keyPhraseModel->num_phrases);
- for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) {
- convertTriggerPhraseToHal(&(*halTriggerPhrases)[i], &keyPhraseModel->phrases[i]);
- }
-}
-
-void SoundTriggerHalHidl::convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
- const struct sound_trigger_sound_model *soundModel)
-{
- halModel->type = (SoundModelType)soundModel->type;
- convertUuidToHal(&halModel->uuid, &soundModel->uuid);
- convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid);
- halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size);
-}
-
-std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertSoundModelToHal(
- V2_1_ISoundTriggerHw::SoundModel *halModel,
- const struct sound_trigger_sound_model *soundModel)
-{
- convertSoundModelToHal(&halModel->header, soundModel);
- return moveVectorToMemory(&halModel->header.data, &halModel->data);
-}
-
-void SoundTriggerHalHidl::convertPhraseSoundModelToHal(
- ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
- const struct sound_trigger_sound_model *soundModel)
-{
- struct sound_trigger_phrase_sound_model *keyPhraseModel =
- (struct sound_trigger_phrase_sound_model *)soundModel;
- convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
- convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
-}
-
-std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertPhraseSoundModelToHal(
- V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
- const struct sound_trigger_sound_model *soundModel)
-{
- struct sound_trigger_phrase_sound_model *keyPhraseModel =
- (struct sound_trigger_phrase_sound_model *)soundModel;
- convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
- return convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
-}
-
-void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal(
- PhraseRecognitionExtra *halExtra,
- const struct sound_trigger_phrase_recognition_extra *extra)
-{
- halExtra->id = extra->id;
- halExtra->recognitionModes = extra->recognition_modes;
- halExtra->confidenceLevel = extra->confidence_level;
- halExtra->levels.resize(extra->num_levels);
- for (unsigned int i = 0; i < extra->num_levels; i++) {
- halExtra->levels[i].userId = extra->levels[i].user_id;
- halExtra->levels[i].levelPercent = extra->levels[i].level;
- }
-}
-
-void SoundTriggerHalHidl::convertRecognitionConfigToHal(
- ISoundTriggerHw::RecognitionConfig *halConfig,
- const struct sound_trigger_recognition_config *config)
-{
- halConfig->captureHandle = config->capture_handle;
- halConfig->captureDevice = (AudioDevice)config->capture_device;
- halConfig->captureRequested = (uint32_t)config->capture_requested;
-
- halConfig->phrases.resize(config->num_phrases);
- for (unsigned int i = 0; i < config->num_phrases; i++) {
- convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
- &config->phrases[i]);
- }
-
- halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size);
-}
-
-std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertRecognitionConfigToHal(
- V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
- const struct sound_trigger_recognition_config *config)
-{
- convertRecognitionConfigToHal(&halConfig->header, config);
- return moveVectorToMemory(&halConfig->header.data, &halConfig->data);
-}
-
-
-// ISoundTriggerHwCallback
-::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback(
- const V2_0_ISoundTriggerHwCallback::RecognitionEvent& halEvent,
- CallbackCookie cookie)
-{
- sp<SoundModel> model;
- {
- AutoMutex lock(mLock);
- model = mSoundModels.valueFor((SoundModelHandle)cookie);
- if (model == 0) {
- return Return<void>();
- }
- }
- struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(&halEvent);
- if (event == NULL) {
- return Return<void>();
- }
- event->model = model->mHandle;
- model->mRecognitionCallback(event, model->mRecognitionCookie);
-
- free(event);
-
- return Return<void>();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback(
- const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent,
- CallbackCookie cookie)
-{
- sp<SoundModel> model;
- {
- AutoMutex lock(mLock);
- model = mSoundModels.valueFor((SoundModelHandle)cookie);
- if (model == 0) {
- return Return<void>();
- }
- }
-
- struct sound_trigger_phrase_recognition_event *event =
- convertPhraseRecognitionEventFromHal(&halEvent);
- if (event == NULL) {
- return Return<void>();
- }
- event->common.model = model->mHandle;
- model->mRecognitionCallback(&event->common, model->mRecognitionCookie);
-
- free(event);
-
- return Return<void>();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback(
- const V2_0_ISoundTriggerHwCallback::ModelEvent& halEvent,
- CallbackCookie cookie)
-{
- sp<SoundModel> model;
- {
- AutoMutex lock(mLock);
- model = mSoundModels.valueFor((SoundModelHandle)cookie);
- if (model == 0) {
- return Return<void>();
- }
- }
-
- struct sound_trigger_model_event *event = convertSoundModelEventFromHal(&halEvent);
- if (event == NULL) {
- return Return<void>();
- }
-
- event->model = model->mHandle;
- model->mSoundModelCallback(event, model->mSoundModelCookie);
-
- free(event);
-
- return Return<void>();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback_2_1(
- const ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie) {
- // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
- V2_0_ISoundTriggerHwCallback::RecognitionEvent event_2_0 = event.header;
- auto result = memoryAsVector(event.data, &event_2_0.data);
- return result.first ? recognitionCallback(event_2_0, cookie) : Void();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback_2_1(
- const ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie) {
- V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
- // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
- event_2_0.common = event.common.header;
- event_2_0.phraseExtras.setToExternal(
- const_cast<PhraseRecognitionExtra*>(event.phraseExtras.data()),
- event.phraseExtras.size());
- auto result = memoryAsVector(event.common.data, &event_2_0.common.data);
- return result.first ? phraseRecognitionCallback(event_2_0, cookie) : Void();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback_2_1(
- const ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie) {
- // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
- V2_0_ISoundTriggerHwCallback::ModelEvent event_2_0 = event.header;
- auto result = memoryAsVector(event.data, &event_2_0.data);
- return result.first ? soundModelCallback(event_2_0, cookie) : Void();
-}
-
-
-struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal(
- const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent)
-{
- struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc(
- sizeof(struct sound_trigger_model_event) +
- halEvent->data.size());
- if (event == NULL) {
- return NULL;
- }
-
- event->status = (int)halEvent->status;
- // event->model to be set by caller
- event->data_offset = sizeof(struct sound_trigger_model_event);
- event->data_size = halEvent->data.size();
- uint8_t *dst = (uint8_t *)event + event->data_offset;
- uint8_t *src = (uint8_t *)&halEvent->data[0];
- memcpy(dst, src, halEvent->data.size());
-
- return event;
-}
-
-void SoundTriggerHalHidl::convertPhraseRecognitionExtraFromHal(
- struct sound_trigger_phrase_recognition_extra *extra,
- const PhraseRecognitionExtra *halExtra)
-{
- extra->id = halExtra->id;
- extra->recognition_modes = halExtra->recognitionModes;
- extra->confidence_level = halExtra->confidenceLevel;
-
- size_t i;
- for (i = 0; i < halExtra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
- extra->levels[i].user_id = halExtra->levels[i].userId;
- extra->levels[i].level = halExtra->levels[i].levelPercent;
- }
- extra->num_levels = (unsigned int)i;
-}
-
-
-struct sound_trigger_phrase_recognition_event* SoundTriggerHalHidl::convertPhraseRecognitionEventFromHal(
- const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent)
-{
- if (halPhraseEvent->common.type != SoundModelType::KEYPHRASE) {
- ALOGE("Received non-keyphrase event type as PhraseRecognitionEvent");
- return NULL;
- }
- struct sound_trigger_phrase_recognition_event *phraseEvent =
- (struct sound_trigger_phrase_recognition_event *)malloc(
- sizeof(struct sound_trigger_phrase_recognition_event) +
- halPhraseEvent->common.data.size());
- if (phraseEvent == NULL) {
- return NULL;
- }
- phraseEvent->common.data_offset = sizeof(sound_trigger_phrase_recognition_event);
-
- for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) {
- convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i],
- &halPhraseEvent->phraseExtras[i]);
- }
- phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size();
-
- fillRecognitionEventFromHal(&phraseEvent->common, &halPhraseEvent->common);
- return phraseEvent;
-}
-
-struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal(
- const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
-{
- if (halEvent->type == SoundModelType::KEYPHRASE) {
- ALOGE("Received keyphrase event type as RecognitionEvent");
- return NULL;
- }
- struct sound_trigger_recognition_event *event;
- event = (struct sound_trigger_recognition_event *)malloc(
- sizeof(struct sound_trigger_recognition_event) + halEvent->data.size());
- if (event == NULL) {
- return NULL;
- }
- event->data_offset = sizeof(sound_trigger_recognition_event);
-
- fillRecognitionEventFromHal(event, halEvent);
- return event;
-}
-
-void SoundTriggerHalHidl::fillRecognitionEventFromHal(
- struct sound_trigger_recognition_event *event,
- const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
-{
- event->status = (int)halEvent->status;
- event->type = (sound_trigger_sound_model_type_t)halEvent->type;
- // event->model to be set by caller
- event->capture_available = (bool)halEvent->captureAvailable;
- event->capture_session = halEvent->captureSession;
- event->capture_delay_ms = halEvent->captureDelayMs;
- event->capture_preamble_ms = halEvent->capturePreambleMs;
- event->trigger_in_data = (bool)halEvent->triggerInData;
- event->audio_config.sample_rate = halEvent->audioConfig.sampleRateHz;
- event->audio_config.channel_mask = (audio_channel_mask_t)halEvent->audioConfig.channelMask;
- event->audio_config.format = (audio_format_t)halEvent->audioConfig.format;
-
- event->data_size = halEvent->data.size();
- uint8_t *dst = (uint8_t *)event + event->data_offset;
- uint8_t *src = (uint8_t *)&halEvent->data[0];
- memcpy(dst, src, halEvent->data.size());
-}
-
-} // namespace android
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
deleted file mode 100644
index 25878d0..0000000
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
-
-#include <utility>
-
-#include <stdatomic.h>
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include "SoundTriggerHalInterface.h"
-#include <android/hardware/soundtrigger/2.0/types.h>
-#include <android/hardware/soundtrigger/2.3/types.h>
-#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
-#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
-#include <android/hardware/soundtrigger/2.3/ISoundTriggerHw.h>
-#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
-#include <android/hardware/soundtrigger/2.1/ISoundTriggerHwCallback.h>
-
-namespace android {
-
-using ::android::hardware::audio::common::V2_0::Uuid;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::soundtrigger::V2_0::ConfidenceLevel;
-using ::android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
-using ::android::hardware::soundtrigger::V2_0::SoundModelType;
-using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
-using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
-using V2_0_ISoundTriggerHwCallback =
- ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
-using V2_1_ISoundTriggerHw =
- ::android::hardware::soundtrigger::V2_1::ISoundTriggerHw;
-using V2_1_ISoundTriggerHwCallback =
- ::android::hardware::soundtrigger::V2_1::ISoundTriggerHwCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using V2_2_ISoundTriggerHw =
- ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw;
-using V2_3_ISoundTriggerHw =
- ::android::hardware::soundtrigger::V2_3::ISoundTriggerHw;
-using V2_3_ModelParameter =
- ::android::hardware::soundtrigger::V2_3::ModelParameter;
-using V2_3_OptionalModelParameterRange =
- ::android::hardware::soundtrigger::V2_3::OptionalModelParameterRange;
-
-class SoundTriggerHalHidl : public SoundTriggerHalInterface,
- public virtual V2_1_ISoundTriggerHwCallback
-
-{
-public:
- virtual int getProperties(struct sound_trigger_properties *properties);
-
- /*
- * Load a sound model. Once loaded, recognition of this model can be started and stopped.
- * Only one active recognition per model at a time. The SoundTrigger service will handle
- * concurrent recognition requests by different users/applications on the same model.
- * The implementation returns a unique handle used by other functions (unload_sound_model(),
- * start_recognition(), etc...
- */
- virtual int loadSoundModel(struct sound_trigger_sound_model *sound_model,
- sound_model_callback_t callback,
- void *cookie,
- sound_model_handle_t *handle);
-
- /*
- * Unload a sound model. A sound model can be unloaded to make room for a new one to overcome
- * implementation limitations.
- */
- virtual int unloadSoundModel(sound_model_handle_t handle);
-
- /* Start recognition on a given model. Only one recognition active at a time per model.
- * Once recognition succeeds of fails, the callback is called.
- * TODO: group recognition configuration parameters into one struct and add key phrase options.
- */
- virtual int startRecognition(sound_model_handle_t handle,
- const struct sound_trigger_recognition_config *config,
- recognition_callback_t callback,
- void *cookie);
-
- /* Stop recognition on a given model.
- * The implementation does not have to call the callback when stopped via this method.
- */
- virtual int stopRecognition(sound_model_handle_t handle);
-
- /* Stop recognition on all models.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_1 or above.
- * If no implementation is provided, stop_recognition will be called for each running model.
- */
- virtual int stopAllRecognitions();
-
- /* Get the current state of a given model.
- * Returns 0 or an error code. If successful the state will be returned asynchronously
- * via a recognition event in the callback method that was registered in the
- * startRecognition() method.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_2 or above.
- */
- virtual int getModelState(sound_model_handle_t handle);
-
- /* Set a model specific ModelParameter with the given value. This parameter
- * will keep its value for the duration the model is loaded regardless of starting and
- * stopping recognition. Once the model is unloaded, the value will be lost.
- * Returns 0 or an error code.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
- */
- int setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param, int32_t value);
-
- /* Get a model specific ModelParameter. This parameter will keep its value
- * for the duration the model is loaded regardless of starting and stopping recognition.
- * Once the model is unloaded, the value will be lost. If the value is not set, a default
- * value is returned. See sound_trigger_model_parameter_t for parameter default values.
- * Returns 0 or an error code. On return 0, value pointer will be set.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
- */
- int getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param, int32_t* value);
-
- /* Get supported parameter attributes with respect to the provided model
- * handle. Along with determining the valid range, this API is also used
- * to determine if a given parameter ID is supported at all by the
- * modelHandle for use with getParameter and setParameter APIs.
- */
- int queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param,
- sound_trigger_model_parameter_range_t* param_range);
-
- // ISoundTriggerHwCallback
- virtual ::android::hardware::Return<void> recognitionCallback(
- const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie);
- virtual ::android::hardware::Return<void> phraseRecognitionCallback(
- const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie);
- virtual ::android::hardware::Return<void> soundModelCallback(
- const V2_0_ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie);
- virtual ::android::hardware::Return<void> recognitionCallback_2_1(
- const RecognitionEvent& event, CallbackCookie cookie);
- virtual ::android::hardware::Return<void> phraseRecognitionCallback_2_1(
- const PhraseRecognitionEvent& event, int32_t cookie);
- virtual ::android::hardware::Return<void> soundModelCallback_2_1(
- const ModelEvent& event, CallbackCookie cookie);
-private:
- class SoundModel : public RefBase {
- public:
- SoundModel(sound_model_handle_t handle, sound_model_callback_t callback,
- void *cookie, android::hardware::soundtrigger::V2_0::SoundModelHandle halHandle)
- : mHandle(handle), mHalHandle(halHandle),
- mSoundModelCallback(callback), mSoundModelCookie(cookie),
- mRecognitionCallback(NULL), mRecognitionCookie(NULL) {}
- ~SoundModel() {}
-
- sound_model_handle_t mHandle;
- android::hardware::soundtrigger::V2_0::SoundModelHandle mHalHandle;
- sound_model_callback_t mSoundModelCallback;
- void * mSoundModelCookie;
- recognition_callback_t mRecognitionCallback;
- void * mRecognitionCookie;
- };
-
- friend class SoundTriggerHalInterface;
-
- explicit SoundTriggerHalHidl(const char *moduleName = NULL);
- virtual ~SoundTriggerHalHidl();
-
- void convertUuidToHal(Uuid *halUuid,
- const sound_trigger_uuid_t *uuid);
- void convertUuidFromHal(sound_trigger_uuid_t *uuid,
- const Uuid *halUuid);
-
- void convertPropertiesFromHal(
- struct sound_trigger_properties *properties,
- const ISoundTriggerHw::Properties *halProperties);
- static void convertModelParameterToHal(V2_3_ModelParameter* halParam,
- sound_trigger_model_parameter_t param);
-
- void convertTriggerPhraseToHal(
- ISoundTriggerHw::Phrase *halTriggerPhrase,
- const struct sound_trigger_phrase *triggerPhrase);
- void convertTriggerPhrasesToHal(
- hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
- struct sound_trigger_phrase_sound_model *keyPhraseModel);
- void convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
- const struct sound_trigger_sound_model *soundModel);
- std::pair<bool, sp<IMemory>> convertSoundModelToHal(
- V2_1_ISoundTriggerHw::SoundModel *halModel,
- const struct sound_trigger_sound_model *soundModel)
- __attribute__((warn_unused_result));
- void convertPhraseSoundModelToHal(ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
- const struct sound_trigger_sound_model *soundModel);
- std::pair<bool, sp<IMemory>> convertPhraseSoundModelToHal(
- V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
- const struct sound_trigger_sound_model *soundModel)
- __attribute__((warn_unused_result));
-
- void convertPhraseRecognitionExtraToHal(
- PhraseRecognitionExtra *halExtra,
- const struct sound_trigger_phrase_recognition_extra *extra);
- void convertRecognitionConfigToHal(ISoundTriggerHw::RecognitionConfig *halConfig,
- const struct sound_trigger_recognition_config *config);
- std::pair<bool, sp<IMemory>> convertRecognitionConfigToHal(
- V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
- const struct sound_trigger_recognition_config *config)
- __attribute__((warn_unused_result));
-
- struct sound_trigger_model_event *convertSoundModelEventFromHal(
- const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent);
- void convertPhraseRecognitionExtraFromHal(
- struct sound_trigger_phrase_recognition_extra *extra,
- const PhraseRecognitionExtra *halExtra);
- struct sound_trigger_phrase_recognition_event* convertPhraseRecognitionEventFromHal(
- const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent);
- struct sound_trigger_recognition_event *convertRecognitionEventFromHal(
- const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent);
- void fillRecognitionEventFromHal(
- struct sound_trigger_recognition_event *event,
- const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent);
-
- uint32_t nextUniqueId();
- sp<ISoundTriggerHw> getService();
- sp<V2_1_ISoundTriggerHw> toService2_1(const sp<ISoundTriggerHw>& s);
- sp<V2_2_ISoundTriggerHw> toService2_2(const sp<ISoundTriggerHw>& s);
- sp<V2_3_ISoundTriggerHw> toService2_3(const sp<ISoundTriggerHw>& s);
- sp<SoundModel> getModel(sound_model_handle_t handle);
- sp<SoundModel> removeModel(sound_model_handle_t handle);
-
- static pthread_once_t sOnceControl;
- static void sOnceInit();
-
- Mutex mLock;
- Mutex mHalLock;
- const char *mModuleName;
- volatile atomic_uint_fast32_t mNextUniqueId;
- // Effect chains without a valid thread
- DefaultKeyedVector< sound_model_handle_t , sp<SoundModel> > mSoundModels;
- sp<::android::hardware::soundtrigger::V2_0::ISoundTriggerHw> mISoundTrigger;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
diff --git a/services/soundtrigger/SoundTriggerHalInterface.h b/services/soundtrigger/SoundTriggerHalInterface.h
deleted file mode 100644
index e1fffff..0000000
--- a/services/soundtrigger/SoundTriggerHalInterface.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_INTERFACE_H
-
-#include <utils/RefBase.h>
-#include <system/sound_trigger.h>
-#include <hardware/sound_trigger.h>
-
-namespace android {
-
-class SoundTriggerHalInterface : public virtual RefBase
-{
-public:
- /* get a sound trigger HAL instance */
- static sp<SoundTriggerHalInterface> connectModule(const char *moduleName);
-
- virtual ~SoundTriggerHalInterface() {}
-
- virtual int getProperties(struct sound_trigger_properties *properties) = 0;
-
- /*
- * Load a sound model. Once loaded, recognition of this model can be started and stopped.
- * Only one active recognition per model at a time. The SoundTrigger service will handle
- * concurrent recognition requests by different users/applications on the same model.
- * The implementation returns a unique handle used by other functions (unload_sound_model(),
- * start_recognition(), etc...
- */
- virtual int loadSoundModel(struct sound_trigger_sound_model *sound_model,
- sound_model_callback_t callback,
- void *cookie,
- sound_model_handle_t *handle) = 0;
-
- /*
- * Unload a sound model. A sound model can be unloaded to make room for a new one to overcome
- * implementation limitations.
- */
- virtual int unloadSoundModel(sound_model_handle_t handle) = 0;
-
- /* Start recognition on a given model. Only one recognition active at a time per model.
- * Once recognition succeeds of fails, the callback is called.
- * TODO: group recognition configuration parameters into one struct and add key phrase options.
- */
- virtual int startRecognition(sound_model_handle_t handle,
- const struct sound_trigger_recognition_config *config,
- recognition_callback_t callback,
- void *cookie) = 0;
-
- /* Stop recognition on a given model.
- * The implementation does not have to call the callback when stopped via this method.
- */
- virtual int stopRecognition(sound_model_handle_t handle) = 0;
-
- /* Stop recognition on all models.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_1 or above.
- * If no implementation is provided, stop_recognition will be called for each running model.
- */
- virtual int stopAllRecognitions() = 0;
-
- /* Get the current state of a given model.
- * Returns 0 or an error code. If successful the state will be returned asynchronously
- * via a recognition event in the callback method that was registered in the
- * startRecognition() method.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_2 or above.
- */
- virtual int getModelState(sound_model_handle_t handle) = 0;
-
- /* Set a model specific ModelParameter with the given value. This parameter
- * will keep its value for the duration the model is loaded regardless of starting and stopping
- * recognition. Once the model is unloaded, the value will be lost.
- * Returns 0 or an error code.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
- */
- virtual int setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t model_param, int32_t value) = 0;
-
- /* Get a model specific ModelParameter. This parameter will keep its value
- * for the duration the model is loaded regardless of starting and stopping recognition.
- * Once the model is unloaded, the value will be lost. If the value is not set, a default
- * value is returned. See sound_trigger_model_parameter_t for parameter default values.
- * Returns 0 or an error code. On return 0, value pointer will be set.
- * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
- */
- virtual int getParameter(sound_model_handle_t sound_model_handle,
- sound_trigger_model_parameter_t model_param, int32_t* value) = 0;
-
- /* Get supported parameter attributes with respect to the provided model
- * handle. Along with determining the valid range, this API is also used
- * to determine if a given parameter ID is supported at all by the
- * modelHandle for use with getParameter and setParameter APIs.
- */
- virtual int queryParameter(sound_model_handle_t sound_model_handle,
- sound_trigger_model_parameter_t model_param,
- sound_trigger_model_parameter_range_t* param_range) = 0;
-
-protected:
- SoundTriggerHalInterface() {}
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_INTERFACE_H
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
deleted file mode 100644
index 4d8b0da..0000000
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ /dev/null
@@ -1,1249 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#define LOG_TAG "SoundTriggerHwService"
-//#define LOG_NDEBUG 0
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <pthread.h>
-
-#include <audio_utils/clock.h>
-#include <system/sound_trigger.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-#include <hardware/hardware.h>
-#include <media/AudioSystem.h>
-#include <mediautils/ServiceUtilities.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <binder/IServiceManager.h>
-#include <binder/MemoryBase.h>
-#include <binder/MemoryHeapBase.h>
-#include <system/sound_trigger.h>
-#include "SoundTriggerHwService.h"
-
-#define HW_MODULE_PREFIX "primary"
-namespace android {
-
-namespace {
-
-// Given an IMemory, returns a copy of its content along with its size.
-// Returns nullptr on failure or if input is nullptr.
-std::pair<std::unique_ptr<uint8_t[]>,
- size_t> CopyToArray(const sp<IMemory>& mem) {
- if (mem == nullptr) {
- return std::make_pair(nullptr, 0);
- }
-
- const size_t size = mem->size();
- if (size == 0) {
- return std::make_pair(nullptr, 0);
- }
-
- std::unique_ptr<uint8_t[]> ar = std::make_unique<uint8_t[]>(size);
- if (ar == nullptr) {
- return std::make_pair(nullptr, 0);
- }
-
- memcpy(ar.get(), mem->unsecurePointer(), size);
- return std::make_pair(std::move(ar), size);
-}
-
-}
-
-SoundTriggerHwService::SoundTriggerHwService()
- : BnSoundTriggerHwService(),
- mNextUniqueId(1),
- mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
- mCaptureState(false)
-{
-}
-
-void SoundTriggerHwService::onFirstRef()
-{
- int rc;
-
- sp<SoundTriggerHalInterface> halInterface =
- SoundTriggerHalInterface::connectModule(HW_MODULE_PREFIX);
-
- if (halInterface == 0) {
- ALOGW("could not connect to HAL");
- return;
- }
- sound_trigger_module_descriptor descriptor;
- rc = halInterface->getProperties(&descriptor.properties);
- if (rc != 0) {
- ALOGE("could not read implementation properties");
- return;
- }
- descriptor.handle =
- (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
- ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
- descriptor.handle);
-
- sp<Module> module = new Module(this, halInterface, descriptor);
- mModules.add(descriptor.handle, module);
- mCallbackThread = new CallbackThread(this);
-}
-
-SoundTriggerHwService::~SoundTriggerHwService()
-{
- if (mCallbackThread != 0) {
- mCallbackThread->exit();
- }
-}
-
-status_t SoundTriggerHwService::listModules(const String16& opPackageName,
- struct sound_trigger_module_descriptor *modules,
- uint32_t *numModules)
-{
- ALOGV("listModules");
- if (!captureHotwordAllowed(opPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- AutoMutex lock(mServiceLock);
- if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
- return BAD_VALUE;
- }
- size_t maxModules = *numModules;
- *numModules = mModules.size();
- for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
- modules[i] = mModules.valueAt(i)->descriptor();
- }
- return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::attach(const String16& opPackageName,
- const sound_trigger_module_handle_t handle,
- const sp<ISoundTriggerClient>& client,
- sp<ISoundTrigger>& moduleInterface)
-{
- ALOGV("attach module %d", handle);
- if (!captureHotwordAllowed(opPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- AutoMutex lock(mServiceLock);
- moduleInterface.clear();
- if (client == 0) {
- return BAD_VALUE;
- }
- ssize_t index = mModules.indexOfKey(handle);
- if (index < 0) {
- return BAD_VALUE;
- }
- sp<Module> module = mModules.valueAt(index);
-
- sp<ModuleClient> moduleClient = module->addClient(client, opPackageName);
- if (moduleClient == 0) {
- return NO_INIT;
- }
-
- moduleClient->setCaptureState_l(mCaptureState);
- moduleInterface = moduleClient;
-
- return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::setCaptureState(bool active)
-{
- ALOGV("setCaptureState %d", active);
- AutoMutex lock(mServiceLock);
- mCaptureState = active;
- for (size_t i = 0; i < mModules.size(); i++) {
- mModules.valueAt(i)->setCaptureState_l(active);
- }
- return NO_ERROR;
-}
-
-
-static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
-
-static bool dumpTryLock(Mutex& mutex)
-{
- status_t err = mutex.timedLock(kDumpLockTimeoutNs);
- return err == NO_ERROR;
-}
-
-status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
- String8 result;
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
- write(fd, result.string(), result.size());
- } else {
- bool locked = dumpTryLock(mServiceLock);
- // failed to lock - SoundTriggerHwService is probably deadlocked
- if (!locked) {
- result.append("SoundTriggerHwService may be deadlocked\n");
- write(fd, result.string(), result.size());
- }
-
- if (locked) mServiceLock.unlock();
- }
- return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
-}
-
-
-// static
-void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
- void *cookie)
-{
- Module *module = (Module *)cookie;
- if (module == NULL) {
- return;
- }
- sp<SoundTriggerHwService> service = module->service().promote();
- if (service == 0) {
- return;
- }
-
- service->sendRecognitionEvent(event, module);
-}
-
-sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent(
- struct sound_trigger_recognition_event *event)
-{
- AutoMutex lock(mMemoryDealerLock);
- sp<IMemory> eventMemory;
-
- //sanitize event
- switch (event->type) {
- case SOUND_MODEL_TYPE_KEYPHRASE:
- ALOGW_IF(event->data_size != 0 && event->data_offset !=
- sizeof(struct sound_trigger_phrase_recognition_event),
- "prepareRecognitionEvent(): invalid data offset %u for keyphrase event type",
- event->data_offset);
- event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
- break;
- case SOUND_MODEL_TYPE_GENERIC:
- ALOGW_IF(event->data_size != 0 && event->data_offset !=
- sizeof(struct sound_trigger_generic_recognition_event),
- "prepareRecognitionEvent(): invalid data offset %u for generic event type",
- event->data_offset);
- event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
- break;
- case SOUND_MODEL_TYPE_UNKNOWN:
- ALOGW_IF(event->data_size != 0 && event->data_offset !=
- sizeof(struct sound_trigger_recognition_event),
- "prepareRecognitionEvent(): invalid data offset %u for unknown event type",
- event->data_offset);
- event->data_offset = sizeof(struct sound_trigger_recognition_event);
- break;
- default:
- return eventMemory;
- }
-
- size_t size = event->data_offset + event->data_size;
- eventMemory = mMemoryDealer->allocate(size);
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- eventMemory.clear();
- return eventMemory;
- }
- memcpy(eventMemory->unsecurePointer(), event, size);
-
- return eventMemory;
-}
-
-void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
- Module *module)
-{
- if (module == NULL) {
- return;
- }
- sp<IMemory> eventMemory = prepareRecognitionEvent(event);
- if (eventMemory == 0) {
- return;
- }
-
- sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
- eventMemory);
- callbackEvent->setModule(module);
- sendCallbackEvent(callbackEvent);
-}
-
-// static
-void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
- void *cookie)
-{
- Module *module = (Module *)cookie;
- if (module == NULL) {
- return;
- }
- sp<SoundTriggerHwService> service = module->service().promote();
- if (service == 0) {
- return;
- }
-
- service->sendSoundModelEvent(event, module);
-}
-
-sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent(struct sound_trigger_model_event *event)
-{
- AutoMutex lock(mMemoryDealerLock);
- sp<IMemory> eventMemory;
-
- size_t size = event->data_offset + event->data_size;
- eventMemory = mMemoryDealer->allocate(size);
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- eventMemory.clear();
- return eventMemory;
- }
- memcpy(eventMemory->unsecurePointer(), event, size);
-
- return eventMemory;
-}
-
-void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
- Module *module)
-{
- sp<IMemory> eventMemory = prepareSoundModelEvent(event);
- if (eventMemory == 0) {
- return;
- }
- sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
- eventMemory);
- callbackEvent->setModule(module);
- sendCallbackEvent(callbackEvent);
-}
-
-
-sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent(sound_trigger_service_state_t state)
-{
- AutoMutex lock(mMemoryDealerLock);
- sp<IMemory> eventMemory;
-
- size_t size = sizeof(sound_trigger_service_state_t);
- eventMemory = mMemoryDealer->allocate(size);
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- eventMemory.clear();
- return eventMemory;
- }
- *((sound_trigger_service_state_t *)eventMemory->unsecurePointer()) = state;
- return eventMemory;
-}
-
-void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
- Module *module)
-{
- sp<IMemory> eventMemory = prepareServiceStateEvent(state);
- if (eventMemory == 0) {
- return;
- }
- sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
- eventMemory);
- callbackEvent->setModule(module);
- sendCallbackEvent(callbackEvent);
-}
-
-void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
- ModuleClient *moduleClient)
-{
- sp<IMemory> eventMemory = prepareServiceStateEvent(state);
- if (eventMemory == 0) {
- return;
- }
- sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
- eventMemory);
- callbackEvent->setModuleClient(moduleClient);
- sendCallbackEvent(callbackEvent);
-}
-
-void SoundTriggerHwService::sendCallbackEvent(const sp<CallbackEvent>& event)
-{
- mCallbackThread->sendCallbackEvent(event);
-}
-
-void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
-{
- ALOGV("onCallbackEvent");
- sp<Module> module;
- sp<ModuleClient> moduleClient;
- {
- AutoMutex lock(mServiceLock);
- //CallbackEvent is either for Module or ModuleClient
- module = event->mModule.promote();
- if (module == 0) {
- moduleClient = event->mModuleClient.promote();
- if (moduleClient == 0) {
- return;
- }
- } else {
- // Sanity check on this being a Module we know about.
- bool foundModule = false;
- for (size_t i = 0; i < mModules.size(); i++) {
- if (mModules.valueAt(i).get() == module.get()) {
- foundModule = true;
- break;
- }
- }
- if (!foundModule) {
- ALOGE("onCallbackEvent for unknown module");
- return;
- }
- }
- }
- if (module != 0) {
- ALOGV("onCallbackEvent for module");
- module->onCallbackEvent(event);
- } else if (moduleClient != 0) {
- ALOGV("onCallbackEvent for moduleClient");
- moduleClient->onCallbackEvent(event);
- }
- {
- AutoMutex lock(mServiceLock);
- // clear now to execute with mServiceLock locked
- event->mMemory.clear();
- }
-}
-
-#undef LOG_TAG
-#define LOG_TAG "SoundTriggerHwService::CallbackThread"
-
-SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
- : mService(service)
-{
-}
-
-SoundTriggerHwService::CallbackThread::~CallbackThread()
-{
- while (!mEventQueue.isEmpty()) {
- mEventQueue[0]->mMemory.clear();
- mEventQueue.removeAt(0);
- }
-}
-
-void SoundTriggerHwService::CallbackThread::onFirstRef()
-{
- run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
-}
-
-bool SoundTriggerHwService::CallbackThread::threadLoop()
-{
- while (!exitPending()) {
- sp<CallbackEvent> event;
- sp<SoundTriggerHwService> service;
- {
- Mutex::Autolock _l(mCallbackLock);
- while (mEventQueue.isEmpty() && !exitPending()) {
- ALOGV("CallbackThread::threadLoop() sleep");
- mCallbackCond.wait(mCallbackLock);
- ALOGV("CallbackThread::threadLoop() wake up");
- }
- if (exitPending()) {
- break;
- }
- event = mEventQueue[0];
- mEventQueue.removeAt(0);
- service = mService.promote();
- }
- if (service != 0) {
- service->onCallbackEvent(event);
- }
- }
- return false;
-}
-
-void SoundTriggerHwService::CallbackThread::exit()
-{
- Mutex::Autolock _l(mCallbackLock);
- requestExit();
- mCallbackCond.broadcast();
-}
-
-void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
- const sp<SoundTriggerHwService::CallbackEvent>& event)
-{
- AutoMutex lock(mCallbackLock);
- mEventQueue.add(event);
- mCallbackCond.signal();
-}
-
-SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
- : mType(type), mMemory(memory)
-{
-}
-
-SoundTriggerHwService::CallbackEvent::~CallbackEvent()
-{
-}
-
-
-#undef LOG_TAG
-#define LOG_TAG "SoundTriggerHwService::Module"
-
-SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
- const sp<SoundTriggerHalInterface>& halInterface,
- sound_trigger_module_descriptor descriptor)
- : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
- mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
-{
-}
-
-SoundTriggerHwService::Module::~Module() {
- mModuleClients.clear();
-}
-
-sp<SoundTriggerHwService::ModuleClient>
-SoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client,
- const String16& opPackageName)
-{
- AutoMutex lock(mLock);
- sp<ModuleClient> moduleClient;
-
- for (size_t i = 0; i < mModuleClients.size(); i++) {
- if (mModuleClients[i]->client() == client) {
- // Client already present, reuse client
- return moduleClient;
- }
- }
- moduleClient = new ModuleClient(this, client, opPackageName);
-
- ALOGV("addClient() client %p", moduleClient.get());
- mModuleClients.add(moduleClient);
-
- return moduleClient;
-}
-
-void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
-{
- ALOGV("Module::detach()");
- Vector<audio_session_t> releasedSessions;
-
- {
- AutoMutex lock(mLock);
- ssize_t index = -1;
-
- for (size_t i = 0; i < mModuleClients.size(); i++) {
- if (mModuleClients[i] == moduleClient) {
- index = i;
- break;
- }
- }
- if (index == -1) {
- return;
- }
-
- ALOGV("remove client %p", moduleClient.get());
- mModuleClients.removeAt(index);
-
- // Iterate in reverse order as models are removed from list inside the loop.
- for (size_t i = mModels.size(); i > 0; i--) {
- sp<Model> model = mModels.valueAt(i - 1);
- if (moduleClient == model->mModuleClient) {
- mModels.removeItemsAt(i - 1);
- ALOGV("detach() unloading model %d", model->mHandle);
- if (mHalInterface != 0) {
- if (model->mState == Model::STATE_ACTIVE) {
- mHalInterface->stopRecognition(model->mHandle);
- }
- mHalInterface->unloadSoundModel(model->mHandle);
- }
- releasedSessions.add(model->mCaptureSession);
- }
- }
- }
-
- for (size_t i = 0; i < releasedSessions.size(); i++) {
- // do not call AudioSystem methods with mLock held
- AudioSystem::releaseSoundTriggerSession(releasedSessions[i]);
- }
-}
-
-status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
- sp<ModuleClient> moduleClient,
- sound_model_handle_t *handle)
-{
- ALOGV("loadSoundModel() handle");
- if (mHalInterface == 0) {
- return NO_INIT;
- }
-
- auto immutableMemory = CopyToArray(modelMemory);
- if (immutableMemory.first == nullptr) {
- return NO_MEMORY;
- }
-
- struct sound_trigger_sound_model* sound_model =
- (struct sound_trigger_sound_model*) immutableMemory.first.get();
-
- size_t structSize;
- if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
- structSize = sizeof(struct sound_trigger_phrase_sound_model);
- } else {
- structSize = sizeof(struct sound_trigger_sound_model);
- }
-
- if (sound_model->data_offset < structSize ||
- sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
- immutableMemory.second < sound_model->data_offset ||
- sound_model->data_size >
- (immutableMemory.second - sound_model->data_offset)) {
- android_errorWriteLog(0x534e4554, "30148546");
- ALOGE("loadSoundModel() data_size is too big");
- return BAD_VALUE;
- }
-
- audio_session_t session;
- audio_io_handle_t ioHandle;
- audio_devices_t device;
- // do not call AudioSystem methods with mLock held
- status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
- if (status != NO_ERROR) {
- return status;
- }
-
- {
- AutoMutex lock(mLock);
-
- if (mModels.size() >= mDescriptor.properties.max_sound_models) {
- ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
- mDescriptor.properties.max_sound_models);
- status = INVALID_OPERATION;
- goto exit;
- }
-
- status = mHalInterface->loadSoundModel(sound_model,
- SoundTriggerHwService::soundModelCallback,
- this, handle);
- if (status != NO_ERROR) {
- goto exit;
- }
-
- sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
- moduleClient);
- mModels.replaceValueFor(*handle, model);
- }
-exit:
- if (status != NO_ERROR) {
- // do not call AudioSystem methods with mLock held
- AudioSystem::releaseSoundTriggerSession(session);
- }
- return status;
-}
-
-status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
-{
- ALOGV("unloadSoundModel() model handle %d", handle);
- status_t status;
- audio_session_t session;
-
- {
- AutoMutex lock(mLock);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
- ssize_t index = mModels.indexOfKey(handle);
- if (index < 0) {
- return BAD_VALUE;
- }
- sp<Model> model = mModels.valueAt(index);
- mModels.removeItem(handle);
- if (model->mState == Model::STATE_ACTIVE) {
- mHalInterface->stopRecognition(model->mHandle);
- model->mState = Model::STATE_IDLE;
- }
- status = mHalInterface->unloadSoundModel(handle);
- session = model->mCaptureSession;
- }
- // do not call AudioSystem methods with mLock held
- AudioSystem::releaseSoundTriggerSession(session);
- return status;
-}
-
-status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory)
-{
- ALOGV("startRecognition() model handle %d", handle);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
-
- auto immutableMemory = CopyToArray(dataMemory);
- if (immutableMemory.first == nullptr) {
- return NO_MEMORY;
- }
-
- struct sound_trigger_recognition_config* config =
- (struct sound_trigger_recognition_config*) immutableMemory.first.get();
-
- if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
- config->data_size > (UINT_MAX - config->data_offset) ||
- immutableMemory.second < config->data_offset ||
- config->data_size >
- (immutableMemory.second - config->data_offset)) {
- ALOGE("startRecognition() data_size is too big");
- return BAD_VALUE;
- }
-
- AutoMutex lock(mLock);
- if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
- return INVALID_OPERATION;
- }
- sp<Model> model = getModel(handle);
- if (model == 0) {
- return BAD_VALUE;
- }
-
- if (model->mState == Model::STATE_ACTIVE) {
- return INVALID_OPERATION;
- }
-
-
- //TODO: get capture handle and device from audio policy service
- config->capture_handle = model->mCaptureIOHandle;
- config->capture_device = model->mCaptureDevice;
- status_t status = mHalInterface->startRecognition(handle, config,
- SoundTriggerHwService::recognitionCallback,
- this);
-
- if (status == NO_ERROR) {
- model->mState = Model::STATE_ACTIVE;
- model->mConfig = *config;
- }
-
- return status;
-}
-
-status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
-{
- ALOGV("stopRecognition() model handle %d", handle);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
- AutoMutex lock(mLock);
- sp<Model> model = getModel(handle);
- if (model == 0) {
- return BAD_VALUE;
- }
-
- if (model->mState != Model::STATE_ACTIVE) {
- return INVALID_OPERATION;
- }
- mHalInterface->stopRecognition(handle);
- model->mState = Model::STATE_IDLE;
- return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::Module::getModelState(sound_model_handle_t handle)
-{
- ALOGV("getModelState() model handle %d", handle);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
- AutoMutex lock(mLock);
- sp<Model> model = getModel(handle);
- if (model == 0) {
- return BAD_VALUE;
- }
-
- if (model->mState != Model::STATE_ACTIVE) {
- return INVALID_OPERATION;
- }
-
- return mHalInterface->getModelState(handle);
-}
-
-status_t SoundTriggerHwService::Module::setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t value)
-{
- ALOGV("setParameter() handle=%d, param=%d, value=%d", handle, param, value);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
-
- AutoMutex lock(mLock);
- return mHalInterface->setParameter(handle, param, value);
-}
-
-status_t SoundTriggerHwService::Module::getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t* value)
-{
- ALOGV("getParameter() handle=%d, param=%d", handle, param);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
-
- AutoMutex lock(mLock);
- return mHalInterface->getParameter(handle, param, value);
-}
-
-status_t SoundTriggerHwService::Module::queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range)
-{
- ALOGV("queryParameter() handle=%d, param=%d", handle, param);
- if (mHalInterface == 0) {
- return NO_INIT;
- }
-
- AutoMutex lock(mLock);
- return mHalInterface->queryParameter(handle, param, param_range);
-}
-
-void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
-{
- ALOGV("onCallbackEvent type %d", event->mType);
-
- // Memory is coming from a trusted process.
- sp<IMemory> eventMemory = event->mMemory;
-
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- return;
- }
- if (mModuleClients.isEmpty()) {
- ALOGI("%s no clients", __func__);
- return;
- }
-
- Vector< sp<ModuleClient> > clients;
-
- switch (event->mType) {
- case CallbackEvent::TYPE_RECOGNITION: {
- struct sound_trigger_recognition_event *recognitionEvent =
- (struct sound_trigger_recognition_event *)eventMemory->unsecurePointer();
- {
- AutoMutex lock(mLock);
- sp<Model> model = getModel(recognitionEvent->model);
- if (model == 0) {
- ALOGW("%s model == 0", __func__);
- return;
- }
- if (model->mState != Model::STATE_ACTIVE) {
- ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
- return;
- }
-
- recognitionEvent->capture_session = model->mCaptureSession;
- model->mState = Model::STATE_IDLE;
- clients.add(model->mModuleClient);
- }
- } break;
- case CallbackEvent::TYPE_SOUNDMODEL: {
- struct sound_trigger_model_event *soundmodelEvent =
- (struct sound_trigger_model_event *)eventMemory->unsecurePointer();
- {
- AutoMutex lock(mLock);
- sp<Model> model = getModel(soundmodelEvent->model);
- if (model == 0) {
- ALOGW("%s model == 0", __func__);
- return;
- }
- clients.add(model->mModuleClient);
- }
- } break;
- case CallbackEvent::TYPE_SERVICE_STATE: {
- {
- AutoMutex lock(mLock);
- for (size_t i = 0; i < mModuleClients.size(); i++) {
- if (mModuleClients[i] != 0) {
- clients.add(mModuleClients[i]);
- }
- }
- }
- } break;
- default:
- LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
- }
-
- for (size_t i = 0; i < clients.size(); i++) {
- clients[i]->onCallbackEvent(event);
- }
-}
-
-sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
- sound_model_handle_t handle)
-{
- sp<Model> model;
- ssize_t index = mModels.indexOfKey(handle);
- if (index >= 0) {
- model = mModels.valueAt(index);
- }
- return model;
-}
-
-// Called with mServiceLock held
-void SoundTriggerHwService::Module::setCaptureState_l(bool active)
-{
- ALOGV("Module::setCaptureState_l %d", active);
- sp<SoundTriggerHwService> service;
- sound_trigger_service_state_t state;
-
- Vector< sp<IMemory> > events;
- {
- AutoMutex lock(mLock);
- state = (active && !mDescriptor.properties.concurrent_capture) ?
- SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
-
- if (state == mServiceState) {
- return;
- }
-
- mServiceState = state;
-
- service = mService.promote();
- if (service == 0) {
- return;
- }
-
- if (state == SOUND_TRIGGER_STATE_ENABLED) {
- goto exit;
- }
-
- const bool supports_stop_all =
- (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() != -ENOSYS);
-
- for (size_t i = 0; i < mModels.size(); i++) {
- sp<Model> model = mModels.valueAt(i);
- if (model->mState == Model::STATE_ACTIVE) {
- if (mHalInterface != 0 && !supports_stop_all) {
- mHalInterface->stopRecognition(model->mHandle);
- }
- // keep model in ACTIVE state so that event is processed by onCallbackEvent()
- if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
- struct sound_trigger_phrase_recognition_event event;
- memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
- event.num_phrases = model->mConfig.num_phrases;
- for (size_t i = 0; i < event.num_phrases; i++) {
- event.phrase_extras[i] = model->mConfig.phrases[i];
- }
- event.common.status = RECOGNITION_STATUS_ABORT;
- event.common.type = model->mType;
- event.common.model = model->mHandle;
- event.common.data_size = 0;
- sp<IMemory> eventMemory = service->prepareRecognitionEvent(&event.common);
- if (eventMemory != 0) {
- events.add(eventMemory);
- }
- } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
- struct sound_trigger_generic_recognition_event event;
- memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
- event.common.status = RECOGNITION_STATUS_ABORT;
- event.common.type = model->mType;
- event.common.model = model->mHandle;
- event.common.data_size = 0;
- sp<IMemory> eventMemory = service->prepareRecognitionEvent(&event.common);
- if (eventMemory != 0) {
- events.add(eventMemory);
- }
- } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
- struct sound_trigger_phrase_recognition_event event;
- memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
- event.common.status = RECOGNITION_STATUS_ABORT;
- event.common.type = model->mType;
- event.common.model = model->mHandle;
- event.common.data_size = 0;
- sp<IMemory> eventMemory = service->prepareRecognitionEvent(&event.common);
- if (eventMemory != 0) {
- events.add(eventMemory);
- }
- } else {
- goto exit;
- }
- }
- }
- }
-
- for (size_t i = 0; i < events.size(); i++) {
- sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
- events[i]);
- callbackEvent->setModule(this);
- service->sendCallbackEvent(callbackEvent);
- }
-
-exit:
- service->sendServiceStateEvent(state, this);
-}
-
-
-SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
- audio_io_handle_t ioHandle, audio_devices_t device,
- sound_trigger_sound_model_type_t type,
- sp<ModuleClient>& moduleClient) :
- mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
- mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
- mModuleClient(moduleClient)
-{
-}
-
-#undef LOG_TAG
-#define LOG_TAG "SoundTriggerHwService::ModuleClient"
-
-SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
- const sp<ISoundTriggerClient>& client,
- const String16& opPackageName)
- : mModule(module), mClient(client), mOpPackageName(opPackageName)
-{
-}
-
-void SoundTriggerHwService::ModuleClient::onFirstRef()
-{
- sp<IBinder> binder = IInterface::asBinder(mClient);
- if (binder != 0) {
- binder->linkToDeath(this);
- }
-}
-
-SoundTriggerHwService::ModuleClient::~ModuleClient()
-{
-}
-
-status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
- const Vector<String16>& args __unused) {
- String8 result;
- return NO_ERROR;
-}
-
-void SoundTriggerHwService::ModuleClient::detach() {
- ALOGV("detach()");
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return;
- }
-
- {
- AutoMutex lock(mLock);
- if (mClient != 0) {
- IInterface::asBinder(mClient)->unlinkToDeath(this);
- mClient.clear();
- }
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return;
- }
- module->detach(this);
-}
-
-status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
- sound_model_handle_t *handle)
-{
- ALOGV("loadSoundModel() handle");
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
- if (checkIMemory(modelMemory) != NO_ERROR) {
- return BAD_VALUE;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->loadSoundModel(modelMemory, this, handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
-{
- ALOGV("unloadSoundModel() model handle %d", handle);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->unloadSoundModel(handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory)
-{
- ALOGV("startRecognition() model handle %d", handle);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
- if (checkIMemory(dataMemory) != NO_ERROR) {
- return BAD_VALUE;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->startRecognition(handle, dataMemory);
-}
-
-status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
-{
- ALOGV("stopRecognition() model handle %d", handle);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->stopRecognition(handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::getModelState(sound_model_handle_t handle)
-{
- ALOGV("getModelState() model handle %d", handle);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->getModelState(handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t value)
-{
- ALOGV("setParameter() handle=%d, param=%d, value=%d", handle, param, value);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->setParameter(handle, param, value);
-}
-
-status_t SoundTriggerHwService::ModuleClient::getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t* value)
-{
- ALOGV("getParameter() handle=%d, param=%d", handle, param);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->getParameter(handle, param, value);
-}
-
-status_t SoundTriggerHwService::ModuleClient::queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range)
-{
- ALOGV("isParameterSupported() handle=%d, param=%d", handle, param);
- if (!captureHotwordAllowed(mOpPackageName,
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid())) {
- return PERMISSION_DENIED;
- }
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return NO_INIT;
- }
- return module->queryParameter(handle, param, param_range);
-}
-
-void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
-{
- ALOGV("ModuleClient::setCaptureState_l %d", active);
- sp<SoundTriggerHwService> service;
- sound_trigger_service_state_t state;
-
- sp<Module> module = mModule.promote();
- if (module == 0) {
- return;
- }
- {
- AutoMutex lock(mLock);
- state = (active && !module->isConcurrentCaptureAllowed()) ?
- SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
-
- service = module->service().promote();
- if (service == 0) {
- return;
- }
- }
- service->sendServiceStateEvent(state, this);
-}
-
-void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
-{
- ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
-
- sp<IMemory> eventMemory = event->mMemory;
-
- // Memory is coming from a trusted process.
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- return;
- }
-
- sp<ISoundTriggerClient> client;
- {
- AutoMutex lock(mLock);
- client = mClient;
- }
-
- if (client != 0) {
- switch (event->mType) {
- case CallbackEvent::TYPE_RECOGNITION: {
- client->onRecognitionEvent(eventMemory);
- } break;
- case CallbackEvent::TYPE_SOUNDMODEL: {
- client->onSoundModelEvent(eventMemory);
- } break;
- case CallbackEvent::TYPE_SERVICE_STATE: {
- client->onServiceStateChange(eventMemory);
- } break;
- default:
- LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
- }
- }
-}
-
-void SoundTriggerHwService::ModuleClient::binderDied(
- const wp<IBinder> &who __unused) {
- ALOGW("client binder died for client %p", this);
- detach();
-}
-
-}; // namespace android
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
deleted file mode 100644
index 4057e14..0000000
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
-
-#include <utils/Vector.h>
-//#include <binder/AppOpsManager.h>
-#include <binder/MemoryDealer.h>
-#include <binder/BinderService.h>
-#include <binder/IAppOpsCallback.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <system/sound_trigger.h>
-#include "SoundTriggerHalInterface.h"
-
-namespace android {
-
-class MemoryHeapBase;
-
-class SoundTriggerHwService :
- public BinderService<SoundTriggerHwService>,
- public BnSoundTriggerHwService
-{
- friend class BinderService<SoundTriggerHwService>;
-public:
- class Module;
- class ModuleClient;
-
- static char const* getServiceName() { return "media.sound_trigger_hw"; }
-
- SoundTriggerHwService();
- virtual ~SoundTriggerHwService();
-
- // ISoundTriggerHwService
- virtual status_t listModules(const String16& opPackageName,
- struct sound_trigger_module_descriptor *modules,
- uint32_t *numModules);
-
- virtual status_t attach(const String16& opPackageName,
- const sound_trigger_module_handle_t handle,
- const sp<ISoundTriggerClient>& client,
- sp<ISoundTrigger>& module);
-
- virtual status_t setCaptureState(bool active);
-
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- class Model : public RefBase {
- public:
-
- enum {
- STATE_IDLE,
- STATE_ACTIVE
- };
-
- Model(sound_model_handle_t handle, audio_session_t session, audio_io_handle_t ioHandle,
- audio_devices_t device, sound_trigger_sound_model_type_t type,
- sp<ModuleClient>& moduleClient);
- ~Model() {}
-
- sound_model_handle_t mHandle;
- int mState;
- audio_session_t mCaptureSession;
- audio_io_handle_t mCaptureIOHandle;
- audio_devices_t mCaptureDevice;
- sound_trigger_sound_model_type_t mType;
- struct sound_trigger_recognition_config mConfig;
- sp<ModuleClient> mModuleClient;
- };
-
- class CallbackEvent : public RefBase {
- public:
- typedef enum {
- TYPE_RECOGNITION,
- TYPE_SOUNDMODEL,
- TYPE_SERVICE_STATE,
- } event_type;
- CallbackEvent(event_type type, sp<IMemory> memory);
-
- virtual ~CallbackEvent();
-
- void setModule(wp<Module> module) { mModule = module; }
- void setModuleClient(wp<ModuleClient> moduleClient) { mModuleClient = moduleClient; }
-
- event_type mType;
- sp<IMemory> mMemory;
- wp<Module> mModule;
- wp<ModuleClient> mModuleClient;
- };
-
- class Module : public RefBase {
- public:
-
- Module(const sp<SoundTriggerHwService>& service,
- const sp<SoundTriggerHalInterface>& halInterface,
- sound_trigger_module_descriptor descriptor);
-
- virtual ~Module();
-
- virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
- sp<ModuleClient> moduleClient,
- sound_model_handle_t *handle);
-
- virtual status_t unloadSoundModel(sound_model_handle_t handle);
-
- virtual status_t startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory);
- virtual status_t stopRecognition(sound_model_handle_t handle);
- virtual status_t getModelState(sound_model_handle_t handle);
- virtual status_t setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t value);
- virtual status_t getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t* value);
- virtual status_t queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range);
-
- sp<SoundTriggerHalInterface> halInterface() const { return mHalInterface; }
- struct sound_trigger_module_descriptor descriptor() { return mDescriptor; }
- wp<SoundTriggerHwService> service() const { return mService; }
- bool isConcurrentCaptureAllowed() const { return mDescriptor.properties.concurrent_capture; }
-
- sp<Model> getModel(sound_model_handle_t handle);
-
- void setCaptureState_l(bool active);
-
- sp<ModuleClient> addClient(const sp<ISoundTriggerClient>& client,
- const String16& opPackageName);
-
- void detach(const sp<ModuleClient>& moduleClient);
-
- void onCallbackEvent(const sp<CallbackEvent>& event);
-
- private:
-
- Mutex mLock;
- wp<SoundTriggerHwService> mService;
- sp<SoundTriggerHalInterface> mHalInterface;
- struct sound_trigger_module_descriptor mDescriptor;
- Vector< sp<ModuleClient> > mModuleClients;
- DefaultKeyedVector< sound_model_handle_t, sp<Model> > mModels;
- sound_trigger_service_state_t mServiceState;
- }; // class Module
-
- class ModuleClient : public virtual RefBase,
- public BnSoundTrigger,
- public IBinder::DeathRecipient {
- public:
-
- ModuleClient(const sp<Module>& module,
- const sp<ISoundTriggerClient>& client,
- const String16& opPackageName);
-
- virtual ~ModuleClient();
-
- virtual void detach();
-
- virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
- sound_model_handle_t *handle);
-
- virtual status_t unloadSoundModel(sound_model_handle_t handle);
-
- virtual status_t startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory);
- virtual status_t stopRecognition(sound_model_handle_t handle);
- virtual status_t getModelState(sound_model_handle_t handle);
- virtual status_t setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t value);
- virtual status_t getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t* value);
- virtual status_t queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range);
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- virtual void onFirstRef();
-
- // IBinder::DeathRecipient implementation
- virtual void binderDied(const wp<IBinder> &who);
-
- void onCallbackEvent(const sp<CallbackEvent>& event);
-
- void setCaptureState_l(bool active);
-
- sp<ISoundTriggerClient> client() const { return mClient; }
-
- private:
-
- mutable Mutex mLock;
- wp<Module> mModule;
- sp<ISoundTriggerClient> mClient;
- const String16 mOpPackageName;
- }; // class ModuleClient
-
- class CallbackThread : public Thread {
- public:
-
- explicit CallbackThread(const wp<SoundTriggerHwService>& service);
-
- virtual ~CallbackThread();
-
- // Thread virtuals
- virtual bool threadLoop();
-
- // RefBase
- virtual void onFirstRef();
-
- void exit();
- void sendCallbackEvent(const sp<CallbackEvent>& event);
-
- private:
- wp<SoundTriggerHwService> mService;
- Condition mCallbackCond;
- Mutex mCallbackLock;
- Vector< sp<CallbackEvent> > mEventQueue;
- };
-
- static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie);
- sp<IMemory> prepareRecognitionEvent(struct sound_trigger_recognition_event *event);
- void sendRecognitionEvent(struct sound_trigger_recognition_event *event, Module *module);
-
- static void soundModelCallback(struct sound_trigger_model_event *event, void *cookie);
- sp<IMemory> prepareSoundModelEvent(struct sound_trigger_model_event *event);
- void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module);
-
- sp<IMemory> prepareServiceStateEvent(sound_trigger_service_state_t state);
- void sendServiceStateEvent(sound_trigger_service_state_t state, Module *module);
- void sendServiceStateEvent(sound_trigger_service_state_t state,
- ModuleClient *moduleClient);
-
- void sendCallbackEvent(const sp<CallbackEvent>& event);
- void onCallbackEvent(const sp<CallbackEvent>& event);
-
-private:
-
- virtual void onFirstRef();
-
- Mutex mServiceLock;
- volatile int32_t mNextUniqueId;
- DefaultKeyedVector< sound_trigger_module_handle_t, sp<Module> > mModules;
- sp<CallbackThread> mCallbackThread;
- sp<MemoryDealer> mMemoryDealer;
- Mutex mMemoryDealerLock;
- bool mCaptureState;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
diff --git a/soundtrigger/Android.bp b/soundtrigger/Android.bp
deleted file mode 100644
index 6178153..0000000
--- a/soundtrigger/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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.
-
-cc_library_shared {
- name: "libsoundtrigger",
-
- srcs: [
- "SoundTrigger.cpp",
- "ISoundTrigger.cpp",
- "ISoundTriggerClient.cpp",
- "ISoundTriggerHwService.cpp",
- ],
-
- shared_libs: [
- "libcutils",
- "libutils",
- "liblog",
- "libbinder",
- ],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
-}
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
deleted file mode 100644
index 9b1da13..0000000
--- a/soundtrigger/ISoundTrigger.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
-**
-** Copyright 2014, 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.
-*/
-
-#define LOG_TAG "ISoundTrigger"
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <binder/IMemory.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-enum {
- DETACH = IBinder::FIRST_CALL_TRANSACTION,
- LOAD_SOUND_MODEL,
- UNLOAD_SOUND_MODEL,
- START_RECOGNITION,
- STOP_RECOGNITION,
- GET_MODEL_STATE,
- SET_PARAMETER,
- GET_PARAMETER,
- QUERY_PARAMETER,
-};
-
-class BpSoundTrigger: public BpInterface<ISoundTrigger>
-{
-public:
- explicit BpSoundTrigger(const sp<IBinder>& impl)
- : BpInterface<ISoundTrigger>(impl)
- {
- }
-
- void detach()
- {
- ALOGV("detach");
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- remote()->transact(DETACH, data, &reply);
- }
-
- status_t loadSoundModel(const sp<IMemory>& modelMemory,
- sound_model_handle_t *handle)
- {
- if (modelMemory == 0 || handle == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(modelMemory));
- status_t status = remote()->transact(LOAD_SOUND_MODEL, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- status = (status_t)reply.readInt32();
- if (status == NO_ERROR) {
- reply.read(handle, sizeof(sound_model_handle_t));
- }
- return status;
- }
-
- virtual status_t unloadSoundModel(sound_model_handle_t handle)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- status_t status = remote()->transact(UNLOAD_SOUND_MODEL, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
-
- virtual status_t startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- if (dataMemory == 0) {
- data.writeInt32(0);
- } else {
- data.writeInt32(dataMemory->size());
- }
- data.writeStrongBinder(IInterface::asBinder(dataMemory));
- status_t status = remote()->transact(START_RECOGNITION, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
-
- virtual status_t stopRecognition(sound_model_handle_t handle)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- status_t status = remote()->transact(STOP_RECOGNITION, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
-
- virtual status_t getModelState(sound_model_handle_t handle)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- status_t status = remote()->transact(GET_MODEL_STATE, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
-
- virtual status_t setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t value)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- data.write(¶m, sizeof(sound_trigger_model_parameter_t));
- data.writeInt32(value);
- status_t status = remote()->transact(SET_PARAMETER, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- }
- return status;
- }
-
- virtual status_t getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- int32_t* value)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- data.write(¶m, sizeof(sound_trigger_model_parameter_t));
- status_t status = remote()->transact(GET_PARAMETER, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- *value = reply.readInt32();
- }
- return status;
- }
-
- virtual status_t queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
- data.write(&handle, sizeof(sound_model_handle_t));
- data.write(¶m, sizeof(sound_trigger_model_parameter_t));
- status_t status = remote()->transact(QUERY_PARAMETER, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- param_range->start = reply.readInt32();
- param_range->end = reply.readInt32();
- }
- return status;
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(SoundTrigger, "android.hardware.ISoundTrigger");
-
-// ----------------------------------------------------------------------
-
-status_t BnSoundTrigger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case DETACH: {
- ALOGV("DETACH");
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- detach();
- return NO_ERROR;
- } break;
- case LOAD_SOUND_MODEL: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sp<IMemory> modelMemory = interface_cast<IMemory>(
- data.readStrongBinder());
- sound_model_handle_t handle;
- status_t status = loadSoundModel(modelMemory, &handle);
- reply->writeInt32(status);
- if (status == NO_ERROR) {
- reply->write(&handle, sizeof(sound_model_handle_t));
- }
- return NO_ERROR;
- }
- case UNLOAD_SOUND_MODEL: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- data.read(&handle, sizeof(sound_model_handle_t));
- status_t status = unloadSoundModel(handle);
- reply->writeInt32(status);
- return NO_ERROR;
- }
- case START_RECOGNITION: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- data.read(&handle, sizeof(sound_model_handle_t));
- sp<IMemory> dataMemory;
- if (data.readInt32() != 0) {
- dataMemory = interface_cast<IMemory>(data.readStrongBinder());
- }
- status_t status = startRecognition(handle, dataMemory);
- reply->writeInt32(status);
- return NO_ERROR;
- }
- case STOP_RECOGNITION: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- data.read(&handle, sizeof(sound_model_handle_t));
- status_t status = stopRecognition(handle);
- reply->writeInt32(status);
- return NO_ERROR;
- }
- case GET_MODEL_STATE: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- status_t status = UNKNOWN_ERROR;
- status_t ret = data.read(&handle, sizeof(sound_model_handle_t));
- if (ret == NO_ERROR) {
- status = getModelState(handle);
- }
- reply->writeInt32(status);
- return ret;
- }
- case SET_PARAMETER: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- sound_trigger_model_parameter_t param;
- int32_t value;
- status_t status = UNKNOWN_ERROR;
- status_t ret;
- ret = data.read(&handle, sizeof(sound_model_handle_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- ret = data.read(¶m, sizeof(sound_trigger_model_parameter_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- ret = data.read(&value, sizeof(int32_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- status = setParameter(handle, param, value);
- reply->writeInt32(status);
- return NO_ERROR;
- }
- case GET_PARAMETER: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- sound_trigger_model_parameter_t param;
- int32_t value;
- status_t status = UNKNOWN_ERROR;
- status_t ret;
- ret = data.read(&handle, sizeof(sound_model_handle_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- ret = data.read(¶m, sizeof(sound_trigger_model_parameter_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- status = getParameter(handle, param, &value);
- reply->writeInt32(status);
- reply->writeInt32(value);
- return NO_ERROR;
- }
- case QUERY_PARAMETER: {
- CHECK_INTERFACE(ISoundTrigger, data, reply);
- sound_model_handle_t handle;
- sound_trigger_model_parameter_t param;
- status_t ret;
- status_t status = UNKNOWN_ERROR;
- sound_trigger_model_parameter_range_t retValue;
- ret = data.read(&handle, sizeof(sound_model_handle_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- ret = data.read(¶m, sizeof(sound_trigger_model_parameter_t));
- if (ret != NO_ERROR) {
- return ret;
- }
- status = queryParameter(handle, param, &retValue);
- reply->writeInt32(status);
- reply->writeInt32(retValue.start);
- reply->writeInt32(retValue.end);
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/soundtrigger/ISoundTriggerClient.cpp b/soundtrigger/ISoundTriggerClient.cpp
deleted file mode 100644
index 1385631..0000000
--- a/soundtrigger/ISoundTriggerClient.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-**
-** Copyright 2014, 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.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-
-namespace android {
-
-enum {
- ON_RECOGNITION_EVENT = IBinder::FIRST_CALL_TRANSACTION,
- ON_SOUNDMODEL_EVENT,
- ON_SERVICE_STATE_CHANGE
-};
-
-class BpSoundTriggerClient: public BpInterface<ISoundTriggerClient>
-{
-
-public:
- explicit BpSoundTriggerClient(const sp<IBinder>& impl)
- : BpInterface<ISoundTriggerClient>(impl)
- {
- }
-
- virtual void onRecognitionEvent(const sp<IMemory>& eventMemory)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(eventMemory));
- remote()->transact(ON_RECOGNITION_EVENT,
- data,
- &reply);
- }
-
- virtual void onSoundModelEvent(const sp<IMemory>& eventMemory)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(eventMemory));
- remote()->transact(ON_SOUNDMODEL_EVENT,
- data,
- &reply);
- }
- virtual void onServiceStateChange(const sp<IMemory>& eventMemory)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(eventMemory));
- remote()->transact(ON_SERVICE_STATE_CHANGE,
- data,
- &reply);
- }
-};
-
-IMPLEMENT_META_INTERFACE(SoundTriggerClient,
- "android.hardware.ISoundTriggerClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnSoundTriggerClient::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case ON_RECOGNITION_EVENT: {
- CHECK_INTERFACE(ISoundTriggerClient, data, reply);
- sp<IMemory> eventMemory = interface_cast<IMemory>(
- data.readStrongBinder());
- onRecognitionEvent(eventMemory);
- return NO_ERROR;
- } break;
- case ON_SOUNDMODEL_EVENT: {
- CHECK_INTERFACE(ISoundTriggerClient, data, reply);
- sp<IMemory> eventMemory = interface_cast<IMemory>(
- data.readStrongBinder());
- onSoundModelEvent(eventMemory);
- return NO_ERROR;
- } break;
- case ON_SERVICE_STATE_CHANGE: {
- CHECK_INTERFACE(ISoundTriggerClient, data, reply);
- sp<IMemory> eventMemory = interface_cast<IMemory>(
- data.readStrongBinder());
- onServiceStateChange(eventMemory);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
deleted file mode 100644
index bd107b4..0000000
--- a/soundtrigger/ISoundTriggerHwService.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-**
-** Copyright 2014, 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.
-*/
-
-#define LOG_TAG "BpSoundTriggerHwService"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/Errors.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-
-namespace android {
-
-enum {
- LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
- ATTACH,
- SET_CAPTURE_STATE,
-};
-
-#define MAX_ITEMS_PER_LIST 1024
-
-class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
-{
-public:
- explicit BpSoundTriggerHwService(const sp<IBinder>& impl)
- : BpInterface<ISoundTriggerHwService>(impl)
- {
- }
-
- virtual status_t listModules(const String16& opPackageName,
- struct sound_trigger_module_descriptor *modules,
- uint32_t *numModules)
- {
- if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
- data.writeString16(opPackageName);
- unsigned int numModulesReq = (modules == NULL) ? 0 : *numModules;
- data.writeInt32(numModulesReq);
- status_t status = remote()->transact(LIST_MODULES, data, &reply);
- if (status == NO_ERROR) {
- status = (status_t)reply.readInt32();
- *numModules = (unsigned int)reply.readInt32();
- }
- ALOGV("listModules() status %d got *numModules %d", status, *numModules);
- if (status == NO_ERROR) {
- if (numModulesReq > *numModules) {
- numModulesReq = *numModules;
- }
- if (numModulesReq > 0) {
- reply.read(modules, numModulesReq * sizeof(struct sound_trigger_module_descriptor));
- }
- }
- return status;
- }
-
- virtual status_t attach(const String16& opPackageName,
- const sound_trigger_module_handle_t handle,
- const sp<ISoundTriggerClient>& client,
- sp<ISoundTrigger>& module)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
- data.writeString16(opPackageName);
- data.write(&handle, sizeof(sound_trigger_module_handle_t));
- data.writeStrongBinder(IInterface::asBinder(client));
- status_t status = remote()->transact(ATTACH, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- status = reply.readInt32();
- if (reply.readInt32() != 0) {
- module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
- }
- return status;
- }
-
- virtual status_t setCaptureState(bool active)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
- data.writeInt32(active);
- status_t status = remote()->transact(SET_CAPTURE_STATE, data, &reply);
- if (status == NO_ERROR) {
- status = reply.readInt32();
- }
- return status;
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
-
-// ----------------------------------------------------------------------
-
-status_t BnSoundTriggerHwService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case LIST_MODULES: {
- CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
- String16 opPackageName;
- status_t status = data.readString16(&opPackageName);
- if (status != NO_ERROR) {
- return status;
- }
- unsigned int numModulesReq = data.readInt32();
- if (numModulesReq > MAX_ITEMS_PER_LIST) {
- numModulesReq = MAX_ITEMS_PER_LIST;
- }
- unsigned int numModules = numModulesReq;
- struct sound_trigger_module_descriptor *modules =
- (struct sound_trigger_module_descriptor *)calloc(numModulesReq,
- sizeof(struct sound_trigger_module_descriptor));
- if (modules == NULL) {
- reply->writeInt32(NO_MEMORY);
- reply->writeInt32(0);
- return NO_ERROR;
- }
- status = listModules(opPackageName, modules, &numModules);
- reply->writeInt32(status);
- reply->writeInt32(numModules);
- ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
-
- if (status == NO_ERROR) {
- if (numModulesReq > numModules) {
- numModulesReq = numModules;
- }
- reply->write(modules,
- numModulesReq * sizeof(struct sound_trigger_module_descriptor));
- }
- free(modules);
- return NO_ERROR;
- }
-
- case ATTACH: {
- CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
- String16 opPackageName;
- status_t status = data.readString16(&opPackageName);
- if (status != NO_ERROR) {
- return status;
- }
- sound_trigger_module_handle_t handle;
- data.read(&handle, sizeof(sound_trigger_module_handle_t));
- sp<ISoundTriggerClient> client =
- interface_cast<ISoundTriggerClient>(data.readStrongBinder());
- sp<ISoundTrigger> module;
- status = attach(opPackageName, handle, client, module);
- reply->writeInt32(status);
- if (module != 0) {
- reply->writeInt32(1);
- reply->writeStrongBinder(IInterface::asBinder(module));
- } else {
- reply->writeInt32(0);
- }
- return NO_ERROR;
- } break;
-
- case SET_CAPTURE_STATE: {
- CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
- reply->writeInt32(setCaptureState((bool)data.readInt32()));
- return NO_ERROR;
- } break;
-
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/soundtrigger/OWNERS b/soundtrigger/OWNERS
deleted file mode 100644
index e83f6b9..0000000
--- a/soundtrigger/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-thorntonc@google.com
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
deleted file mode 100644
index 021697b..0000000
--- a/soundtrigger/SoundTrigger.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
-**
-** Copyright (C) 2014, 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.
-*/
-
-#define LOG_TAG "SoundTrigger"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/IMemory.h>
-
-#include <soundtrigger/SoundTrigger.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <soundtrigger/SoundTriggerCallback.h>
-
-namespace android {
-
-namespace {
- sp<ISoundTriggerHwService> gSoundTriggerHwService;
- const int kSoundTriggerHwServicePollDelay = 500000; // 0.5s
- const char* kSoundTriggerHwServiceName = "media.sound_trigger_hw";
- Mutex gLock;
-
- class DeathNotifier : public IBinder::DeathRecipient
- {
- public:
- DeathNotifier() {
- }
-
- virtual void binderDied(const wp<IBinder>& who __unused) {
- ALOGV("binderDied");
- Mutex::Autolock _l(gLock);
- gSoundTriggerHwService.clear();
- ALOGW("Sound trigger service died!");
- }
- };
-
- sp<DeathNotifier> gDeathNotifier;
-}; // namespace anonymous
-
-const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
-{
- Mutex::Autolock _l(gLock);
- if (gSoundTriggerHwService.get() == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16(kSoundTriggerHwServiceName));
- if (binder != 0) {
- break;
- }
- ALOGW("SoundTriggerHwService not published, waiting...");
- usleep(kSoundTriggerHwServicePollDelay);
- } while(true);
- if (gDeathNotifier == NULL) {
- gDeathNotifier = new DeathNotifier();
- }
- binder->linkToDeath(gDeathNotifier);
- gSoundTriggerHwService = interface_cast<ISoundTriggerHwService>(binder);
- }
- ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?");
- return gSoundTriggerHwService;
-}
-
-// Static methods
-status_t SoundTrigger::listModules(const String16& opPackageName,
- struct sound_trigger_module_descriptor *modules,
- uint32_t *numModules)
-{
- ALOGV("listModules()");
- const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
- if (service == 0) {
- return NO_INIT;
- }
- return service->listModules(opPackageName, modules, numModules);
-}
-
-sp<SoundTrigger> SoundTrigger::attach(const String16& opPackageName,
- const sound_trigger_module_handle_t module,
- const sp<SoundTriggerCallback>& callback)
-{
- ALOGV("attach()");
- sp<SoundTrigger> soundTrigger;
- const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
- if (service == 0) {
- return soundTrigger;
- }
- soundTrigger = new SoundTrigger(module, callback);
- status_t status = service->attach(opPackageName, module, soundTrigger,
- soundTrigger->mISoundTrigger);
-
- if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
- IInterface::asBinder(soundTrigger->mISoundTrigger)->linkToDeath(soundTrigger);
- } else {
- ALOGW("Error %d connecting to sound trigger service", status);
- soundTrigger.clear();
- }
- return soundTrigger;
-}
-
-
-status_t SoundTrigger::setCaptureState(bool active)
-{
- ALOGV("setCaptureState(%d)", active);
- const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
- if (service == 0) {
- return NO_INIT;
- }
- return service->setCaptureState(active);
-}
-
-// SoundTrigger
-SoundTrigger::SoundTrigger(sound_trigger_module_handle_t /*module*/,
- const sp<SoundTriggerCallback>& callback)
- : mCallback(callback)
-{
-}
-
-SoundTrigger::~SoundTrigger()
-{
- if (mISoundTrigger != 0) {
- mISoundTrigger->detach();
- }
-}
-
-
-void SoundTrigger::detach() {
- ALOGV("detach()");
- Mutex::Autolock _l(mLock);
- mCallback.clear();
- if (mISoundTrigger != 0) {
- mISoundTrigger->detach();
- IInterface::asBinder(mISoundTrigger)->unlinkToDeath(this);
- mISoundTrigger = 0;
- }
-}
-
-status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
- sound_model_handle_t *handle)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
-
- return mISoundTrigger->loadSoundModel(modelMemory, handle);
-}
-
-status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->unloadSoundModel(handle);
-}
-
-status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
- const sp<IMemory>& dataMemory)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->startRecognition(handle, dataMemory);
-}
-
-status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->stopRecognition(handle);
-}
-
-status_t SoundTrigger::getModelState(sound_model_handle_t handle)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->getModelState(handle);
-}
-
-status_t SoundTrigger::setParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t value)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->setParameter(handle, param, value);
-}
-
-status_t SoundTrigger::getParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param, int32_t* value)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->getParameter(handle, param, value);
-}
-
-status_t SoundTrigger::queryParameter(sound_model_handle_t handle,
- sound_trigger_model_parameter_t param,
- sound_trigger_model_parameter_range_t* param_range)
-{
- Mutex::Autolock _l(mLock);
- if (mISoundTrigger == 0) {
- return NO_INIT;
- }
- return mISoundTrigger->queryParameter(handle, param, param_range);
-}
-
-// BpSoundTriggerClient
-void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
-{
- Mutex::Autolock _l(mLock);
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- return;
- }
-
- if (mCallback != 0) {
- // Memory is coming from a trusted process.
- mCallback->onRecognitionEvent(
- (struct sound_trigger_recognition_event *)eventMemory->unsecurePointer());
- }
-}
-
-void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
-{
- Mutex::Autolock _l(mLock);
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- return;
- }
-
- if (mCallback != 0) {
- // Memory is coming from a trusted process.
- mCallback->onSoundModelEvent(
- (struct sound_trigger_model_event *)eventMemory->unsecurePointer());
- }
-}
-
-void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
-{
- Mutex::Autolock _l(mLock);
- if (eventMemory == 0 || eventMemory->unsecurePointer() == NULL) {
- return;
- }
-
- if (mCallback != 0) {
- // Memory is coming from a trusted process.
- mCallback->onServiceStateChange(
- *((sound_trigger_service_state_t *)eventMemory->unsecurePointer()));
- }
-}
-
-//IBinder::DeathRecipient
-void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
- Mutex::Autolock _l(mLock);
- ALOGW("SoundTrigger server binder Died ");
- mISoundTrigger = 0;
- if (mCallback != 0) {
- mCallback->onServiceDied();
- }
-}
-
-status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
-{
- if (str == NULL || guid == NULL) {
- return BAD_VALUE;
- }
-
- int tmp[10];
-
- if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
- return BAD_VALUE;
- }
- guid->timeLow = (uint32_t)tmp[0];
- guid->timeMid = (uint16_t)tmp[1];
- guid->timeHiAndVersion = (uint16_t)tmp[2];
- guid->clockSeq = (uint16_t)tmp[3];
- guid->node[0] = (uint8_t)tmp[4];
- guid->node[1] = (uint8_t)tmp[5];
- guid->node[2] = (uint8_t)tmp[6];
- guid->node[3] = (uint8_t)tmp[7];
- guid->node[4] = (uint8_t)tmp[8];
- guid->node[5] = (uint8_t)tmp[9];
-
- return NO_ERROR;
-}
-
-status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
-{
- if (guid == NULL || str == NULL) {
- return BAD_VALUE;
- }
-
- snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- guid->timeLow,
- guid->timeMid,
- guid->timeHiAndVersion,
- guid->clockSeq,
- guid->node[0],
- guid->node[1],
- guid->node[2],
- guid->node[3],
- guid->node[4],
- guid->node[5]);
-
- return NO_ERROR;
-}
-
-}; // namespace android