Merge changes from topic 'fix omxnode fd leak'
* changes:
Fix Omx emptyBuffer fd leak in GraphicBufferSource
Revert "Revert "Refactor GraphicBufferSource wrappers for OMX HAL""
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 3512730..0771fc8 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -54,6 +54,22 @@
void beginConfigure();
/**
+ * The standard operating mode for a camera device; all API guarantees are in force
+ */
+ const int NORMAL_MODE = 0;
+
+ /**
+ * High-speed recording mode; only two outputs targeting preview and video recording may be
+ * used, and requests must be batched.
+ */
+ const int CONSTRAINED_HIGH_SPEED_MODE = 1;
+
+ /**
+ * Start of custom vendor modes
+ */
+ const int VENDOR_MODE_START = 0x8000;
+
+ /**
* End the device configuration.
*
* <p>
@@ -61,8 +77,10 @@
* a call to beginConfigure and subsequent createStream/deleteStream calls). This
* must be called before any requests can be submitted.
* <p>
+ * @param operatingMode The kind of session to create; either NORMAL_MODE or
+ * CONSTRAINED_HIGH_SPEED_MODE. Must be a non-negative value.
*/
- void endConfigure(boolean isConstrainedHighSpeed);
+ void endConfigure(int operatingMode);
void deleteStream(int streamId);
diff --git a/cmds/screenrecord/EglWindow.cpp b/cmds/screenrecord/EglWindow.cpp
index c16f2ad..5ea0706 100644
--- a/cmds/screenrecord/EglWindow.cpp
+++ b/cmds/screenrecord/EglWindow.cpp
@@ -21,7 +21,6 @@
#define EGL_EGLEXT_PROTOTYPES
#include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
#include <gui/Surface.h>
#include "EglWindow.h"
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index be993e0..aa800d8 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -23,7 +23,6 @@
#include <utils/Log.h>
#include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
#include <gui/Surface.h>
#include <cutils/properties.h>
#include <utils/misc.h>
diff --git a/drm/libmediadrm/Android.mk b/drm/libmediadrm/Android.mk
index a57fafa..590622e 100644
--- a/drm/libmediadrm/Android.mk
+++ b/drm/libmediadrm/Android.mk
@@ -48,7 +48,8 @@
android.hidl.base@1.0 \
android.hardware.drm@1.0 \
libhidlbase \
- libhidlmemory
+ libhidlmemory \
+ libhidltransport
endif
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 5732613..e77a8ea 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -17,10 +17,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "CryptoHal"
#include <utils/Log.h>
-#include <dirent.h>
-#include <dlfcn.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
#include <binder/IMemory.h>
#include <cutils/native_handle.h>
@@ -47,6 +46,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
+using ::android::hidl::manager::V1_0::IServiceManager;
using ::android::sp;
@@ -101,31 +101,52 @@
CryptoHal::CryptoHal()
- : mFactory(makeCryptoFactory()),
- mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT),
+ : mFactories(makeCryptoFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
mNextBufferId(0) {
}
CryptoHal::~CryptoHal() {
}
+Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
+ Vector<sp<ICryptoFactory>> factories;
-sp<ICryptoFactory> CryptoHal::makeCryptoFactory() {
- sp<ICryptoFactory> factory = ICryptoFactory::getService("crypto");
- if (factory == NULL) {
- ALOGE("Failed to make crypto factory");
+ auto manager = ::IServiceManager::getService();
+ if (manager != NULL) {
+ manager->listByInterface(ICryptoFactory::descriptor,
+ [&factories](const hidl_vec<hidl_string> ®istered) {
+ for (const auto &instance : registered) {
+ auto factory = ICryptoFactory::getService(instance);
+ if (factory != NULL) {
+ factories.push_back(factory);
+ ALOGI("makeCryptoFactories: factory instance %s is %s",
+ instance.c_str(),
+ factory->isRemote() ? "Remote" : "Not Remote");
+ }
+ }
+ }
+ );
}
- return factory;
+
+ if (factories.size() == 0) {
+ // must be in passthrough mode, load the default passthrough service
+ auto passthrough = ICryptoFactory::getService("crypto");
+ if (passthrough != NULL) {
+ ALOGI("makeCryptoFactories: using default crypto instance");
+ factories.push_back(passthrough);
+ } else {
+ ALOGE("Failed to find any crypto factories");
+ }
+ }
+ return factories;
}
-sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const uint8_t uuid[16],
- const void *initData, size_t initDataSize) {
- if (mFactory == NULL){
- return NULL;
- }
+sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void *initData, size_t initDataSize) {
sp<ICryptoPlugin> plugin;
- Return<void> hResult = mFactory->createPlugin(toHidlArray16(uuid),
+ Return<void> hResult = factory->createPlugin(toHidlArray16(uuid),
toHidlVec(initData, initDataSize),
[&](Status status, const sp<ICryptoPlugin>& hPlugin) {
if (status != Status::OK) {
@@ -146,17 +167,24 @@
bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
Mutex::Autolock autoLock(mLock);
- if (mFactory != NULL) {
- return mFactory->isCryptoSchemeSupported(uuid);
+
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ return true;
+ }
}
return false;
}
-status_t CryptoHal::createPlugin(
- const uint8_t uuid[16], const void *data, size_t size) {
+status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data,
+ size_t size) {
Mutex::Autolock autoLock(mLock);
- mPlugin = makeCryptoPlugin(uuid, data, size);
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
+ }
+ }
if (mPlugin == NULL) {
mInitCheck = ERROR_UNSUPPORTED;
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 8200d55..16035c0 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,12 +20,11 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
-#include <dirent.h>
-#include <dlfcn.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
#include <media/DrmHal.h>
#include <media/DrmSessionClientInterface.h>
@@ -52,6 +51,7 @@
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
+using ::android::hidl::manager::V1_0::IServiceManager;
using ::android::sp;
namespace android {
@@ -110,9 +110,9 @@
return keyedVector;
}
-static List<Vector<uint8_t> > toSecureStops(const hidl_vec<SecureStop>&
+static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
hSecureStops) {
- List<Vector<uint8_t> > secureStops;
+ List<Vector<uint8_t>> secureStops;
for (size_t i = 0; i < hSecureStops.size(); i++) {
secureStops.push_back(toVector(hSecureStops[i].opaqueData));
}
@@ -189,43 +189,61 @@
DrmHal::DrmHal()
: mDrmSessionClient(new DrmSessionClient(this)),
- mFactory(makeDrmFactory()),
- mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT) {
+ mFactories(makeDrmFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
}
DrmHal::~DrmHal() {
DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
}
-sp<IDrmFactory> DrmHal::makeDrmFactory() {
- sp<IDrmFactory> factory = IDrmFactory::getService("drm");
- if (factory == NULL) {
- ALOGE("Failed to make drm factory");
- return NULL;
+Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
+ Vector<sp<IDrmFactory>> factories;
+
+ auto manager = ::IServiceManager::getService();
+
+ if (manager != NULL) {
+ manager->listByInterface(IDrmFactory::descriptor,
+ [&factories](const hidl_vec<hidl_string> ®istered) {
+ for (const auto &instance : registered) {
+ auto factory = IDrmFactory::getService(instance);
+ if (factory != NULL) {
+ factories.push_back(factory);
+ ALOGI("makeDrmFactories: factory instance %s is %s",
+ instance.c_str(),
+ factory->isRemote() ? "Remote" : "Not Remote");
+ }
+ }
+ }
+ );
}
- ALOGD("makeDrmFactory: service is %s",
- factory->isRemote() ? "Remote" : "Not Remote");
-
- return factory;
+ if (factories.size() == 0) {
+ // must be in passthrough mode, load the default passthrough service
+ auto passthrough = IDrmFactory::getService("drm");
+ if (passthrough != NULL) {
+ ALOGI("makeDrmFactories: using default drm instance");
+ factories.push_back(passthrough);
+ } else {
+ ALOGE("Failed to find any drm factories");
+ }
+ }
+ return factories;
}
-sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16],
- const String8& appPackageName) {
- if (mFactory == NULL){
- return NULL;
- }
+sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& appPackageName) {
sp<IDrmPlugin> plugin;
- Return<void> hResult = mFactory->createPlugin(uuid, appPackageName.string(),
+ Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
[&](Status status, const sp<IDrmPlugin>& hPlugin) {
- if (status != Status::OK) {
- ALOGD("Failed to make drm plugin");
- return;
- }
- plugin = hPlugin;
- }
- );
+ if (status != Status::OK) {
+ ALOGE("Failed to make drm plugin");
+ return;
+ }
+ plugin = hPlugin;
+ }
+ );
return plugin;
}
@@ -346,22 +364,30 @@
bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
Mutex::Autolock autoLock(mLock);
- bool result = false;
- if (mFactory != NULL && mFactory->isCryptoSchemeSupported(uuid)) {
- result = true;
- if (mimeType != "") {
- result = mFactory->isContentTypeSupported(mimeType.string());
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ if (mimeType != "") {
+ if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
+ return true;
+ }
+ } else {
+ return true;
+ }
}
}
- return result;
+ return false;
}
status_t DrmHal::createPlugin(const uint8_t uuid[16],
const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
- mPlugin = makeDrmPlugin(uuid, appPackageName);
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+ }
+ }
if (mPlugin == NULL) {
mInitCheck = ERROR_UNSUPPORTED;
@@ -628,7 +654,7 @@
return hResult.isOk() ? err : DEAD_OBJECT;
}
-status_t DrmHal::getSecureStops(List<Vector<uint8_t> > &secureStops) {
+status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
deleted file mode 120000
index 310fd0d..0000000
--- a/include/media/IAudioFlinger.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/IAudioFlinger.h
\ No newline at end of file
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
new file mode 100644
index 0000000..0ad4231
--- /dev/null
+++ b/include/media/IAudioFlinger.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2007 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_IAUDIOFLINGER_H
+#define ANDROID_IAUDIOFLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+#include <media/IAudioFlingerClient.h>
+#include <system/audio.h>
+#include <system/audio_effect.h>
+#include <system/audio_policy.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioFlinger : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioFlinger);
+
+
+ // invariant on exit for all APIs that return an sp<>:
+ // (return value != 0) == (*status == NO_ERROR)
+
+ /* create an audio track and registers it with AudioFlinger.
+ * return null if the track cannot be created.
+ */
+ virtual sp<IAudioTrack> createTrack(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ size_t *pFrameCount,
+ audio_output_flags_t *flags,
+ const sp<IMemory>& sharedBuffer,
+ // On successful return, AudioFlinger takes over the handle
+ // reference and will release it when the track is destroyed.
+ // However on failure, the client is responsible for release.
+ audio_io_handle_t output,
+ pid_t pid,
+ pid_t tid, // -1 means unused, otherwise must be valid non-0
+ audio_session_t *sessionId,
+ int clientUid,
+ status_t *status,
+ audio_port_handle_t portId) = 0;
+
+ virtual sp<IAudioRecord> openRecord(
+ // On successful return, AudioFlinger takes over the handle
+ // reference and will release it when the track is destroyed.
+ // However on failure, the client is responsible for release.
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ const String16& callingPackage,
+ size_t *pFrameCount,
+ audio_input_flags_t *flags,
+ pid_t pid,
+ pid_t tid, // -1 means unused, otherwise must be valid non-0
+ int clientUid,
+ audio_session_t *sessionId,
+ size_t *notificationFrames,
+ sp<IMemory>& cblk,
+ sp<IMemory>& buffers, // return value 0 means it follows cblk
+ status_t *status,
+ audio_port_handle_t portId) = 0;
+
+ // FIXME Surprisingly, format/latency don't work for input handles
+
+ /* query the audio hardware state. This state never changes,
+ * and therefore can be cached.
+ */
+ virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const = 0;
+
+ // reserved; formerly channelCount()
+
+ virtual audio_format_t format(audio_io_handle_t output) const = 0;
+ virtual size_t frameCount(audio_io_handle_t ioHandle) const = 0;
+
+ // return estimated latency in milliseconds
+ virtual uint32_t latency(audio_io_handle_t output) const = 0;
+
+ /* set/get the audio hardware state. This will probably be used by
+ * the preference panel, mostly.
+ */
+ virtual status_t setMasterVolume(float value) = 0;
+ virtual status_t setMasterMute(bool muted) = 0;
+
+ virtual float masterVolume() const = 0;
+ virtual bool masterMute() const = 0;
+
+ /* set/get stream type state. This will probably be used by
+ * the preference panel, mostly.
+ */
+ virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output) = 0;
+ virtual status_t setStreamMute(audio_stream_type_t stream, bool muted) = 0;
+
+ virtual float streamVolume(audio_stream_type_t stream,
+ audio_io_handle_t output) const = 0;
+ virtual bool streamMute(audio_stream_type_t stream) const = 0;
+
+ // set audio mode
+ virtual status_t setMode(audio_mode_t mode) = 0;
+
+ // mic mute/state
+ virtual status_t setMicMute(bool state) = 0;
+ virtual bool getMicMute() const = 0;
+
+ virtual status_t setParameters(audio_io_handle_t ioHandle,
+ const String8& keyValuePairs) = 0;
+ virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys)
+ const = 0;
+
+ // Register an object to receive audio input/output change and track notifications.
+ // For a given calling pid, AudioFlinger disregards any registrations after the first.
+ // Thus the IAudioFlingerClient must be a singleton per process.
+ virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
+
+ // retrieve the audio recording buffer size
+ // FIXME This API assumes a route, and so should be deprecated.
+ virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+ audio_channel_mask_t channelMask) const = 0;
+
+ virtual status_t openOutput(audio_module_handle_t module,
+ audio_io_handle_t *output,
+ audio_config_t *config,
+ audio_devices_t *devices,
+ const String8& address,
+ uint32_t *latencyMs,
+ audio_output_flags_t flags) = 0;
+ virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2) = 0;
+ virtual status_t closeOutput(audio_io_handle_t output) = 0;
+ virtual status_t suspendOutput(audio_io_handle_t output) = 0;
+ virtual status_t restoreOutput(audio_io_handle_t output) = 0;
+
+ virtual status_t openInput(audio_module_handle_t module,
+ audio_io_handle_t *input,
+ audio_config_t *config,
+ audio_devices_t *device,
+ const String8& address,
+ audio_source_t source,
+ audio_input_flags_t flags) = 0;
+ virtual status_t closeInput(audio_io_handle_t input) = 0;
+
+ virtual status_t invalidateStream(audio_stream_type_t stream) = 0;
+
+ virtual status_t setVoiceVolume(float volume) = 0;
+
+ virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
+ audio_io_handle_t output) const = 0;
+
+ virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const = 0;
+
+ virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
+
+ virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
+ virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects) const = 0;
+
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) const = 0;
+
+ virtual status_t getEffectDescriptor(const effect_uuid_t *pEffectUUID,
+ effect_descriptor_t *pDescriptor) const = 0;
+
+ virtual sp<IEffect> createEffect(
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& client,
+ int32_t priority,
+ // AudioFlinger doesn't take over handle reference from client
+ audio_io_handle_t output,
+ audio_session_t sessionId,
+ const String16& callingPackage,
+ pid_t pid,
+ status_t *status,
+ int *id,
+ int *enabled) = 0;
+
+ virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput) = 0;
+
+ virtual audio_module_handle_t loadHwModule(const char *name) = 0;
+
+ // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+ // FIXME move these APIs to AudioPolicy to permit a more accurate implementation
+ // that looks on primary device for a stream with fast flag, primary flag, or first one.
+ virtual uint32_t getPrimaryOutputSamplingRate() = 0;
+ virtual size_t getPrimaryOutputFrameCount() = 0;
+
+ // Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
+ // and should be called at most once. For a definition of what "low RAM" means, see
+ // android.app.ActivityManager.isLowRamDevice().
+ virtual status_t setLowRamDevice(bool isLowRamDevice) = 0;
+
+ /* List available audio ports and their attributes */
+ virtual status_t listAudioPorts(unsigned int *num_ports,
+ struct audio_port *ports) = 0;
+
+ /* Get attributes for a given audio port */
+ virtual status_t getAudioPort(struct audio_port *port) = 0;
+
+ /* Create an audio patch between several source and sink ports */
+ virtual status_t createAudioPatch(const struct audio_patch *patch,
+ audio_patch_handle_t *handle) = 0;
+
+ /* Release an audio patch */
+ virtual status_t releaseAudioPatch(audio_patch_handle_t handle) = 0;
+
+ /* List existing audio patches */
+ virtual status_t listAudioPatches(unsigned int *num_patches,
+ struct audio_patch *patches) = 0;
+ /* Set audio port configuration */
+ virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
+
+ /* Get the HW synchronization source used for an audio session */
+ virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) = 0;
+
+ /* Indicate JAVA services are ready (scheduling, power management ...) */
+ virtual status_t systemReady() = 0;
+
+ // Returns the number of frames per audio HAL buffer.
+ virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioFlinger : public BnInterface<IAudioFlinger>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ // Requests media.log to start merging log buffers
+ virtual void requestLogMerge() = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOFLINGER_H
diff --git a/include/media/IMediaLogService.h b/include/media/IMediaLogService.h
deleted file mode 120000
index 7a822dd..0000000
--- a/include/media/IMediaLogService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/IMediaLogService.h
\ No newline at end of file
diff --git a/include/media/IMediaLogService.h b/include/media/IMediaLogService.h
new file mode 100644
index 0000000..0f09e0d
--- /dev/null
+++ b/include/media/IMediaLogService.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 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_IMEDIALOGSERVICE_H
+#define ANDROID_IMEDIALOGSERVICE_H
+
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMediaLogService: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaLogService);
+
+ virtual void registerWriter(const sp<IMemory>& shared, size_t size, const char *name) = 0;
+ virtual void unregisterWriter(const sp<IMemory>& shared) = 0;
+ virtual void requestMergeWakeup() = 0;
+
+};
+
+class BnMediaLogService: public BnInterface<IMediaLogService>
+{
+public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // ANDROID_IMEDIALOGSERVICE_H
diff --git a/include/media/MmapStreamInterface.h b/include/media/MmapStreamInterface.h
index 9f3731e..7dbc19e 100644
--- a/include/media/MmapStreamInterface.h
+++ b/include/media/MmapStreamInterface.h
@@ -75,6 +75,7 @@
/**
* Retrieve information on the mmap buffer used for audio samples transfer.
+ * Must be called before any other method after opening the stream or entering standby.
*
* \param[in] min_size_frames minimum buffer size requested. The actual buffer
* size returned in struct audio_mmap_buffer_info can be larger.
@@ -94,6 +95,7 @@
* \param[out] position address at which the mmap read/write position should be returned.
*
* \return OK if the position is successfully returned.
+ * NO_INIT in case of initialization error
* NOT_ENOUGH_DATA if the position cannot be retrieved
* INVALID_OPERATION if called before createMmapBuffer()
*/
@@ -106,6 +108,7 @@
* \param[in] client a Client struct describing the client starting on this stream.
* \param[out] handle unique handle for this instance. Used with stop().
* \return OK in case of success.
+ * NO_INIT in case of initialization error
* INVALID_OPERATION if called out of sequence
*/
virtual status_t start(const Client& client, audio_port_handle_t *handle) = 0;
@@ -116,10 +119,23 @@
*
* \param[in] handle unique handle allocated by start().
* \return OK in case of success.
+ * NO_INIT in case of initialization error
* INVALID_OPERATION if called out of sequence
*/
virtual status_t stop(audio_port_handle_t handle) = 0;
+ /**
+ * Put a stream operating in mmap mode into standby.
+ * Must be called after createMmapBuffer(). Cannot be called if any client is active.
+ * It is recommended to place a mmap stream into standby as often as possible when no client is
+ * active to save power.
+ *
+ * \return OK in case of success.
+ * NO_INIT in case of initialization error
+ * INVALID_OPERATION if called out of sequence
+ */
+ virtual status_t standby() = 0;
+
protected:
// Subclasses can not be constructed directly by clients.
MmapStreamInterface() {}
diff --git a/include/ndk/NdkImage.h b/include/ndk/NdkImage.h
index 9a99287..15eae40 100644
--- a/include/ndk/NdkImage.h
+++ b/include/ndk/NdkImage.h
@@ -54,6 +54,97 @@
// Formats not listed here will not be supported by AImageReader
enum AIMAGE_FORMATS {
/**
+ * 32 bits RGBA format, 8 bits for each of the four channels.
+ *
+ * <p>
+ * Corresponding formats:
+ * <ul>
+ * <li>AHardwareBuffer: AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM</li>
+ * <li>Vulkan: VK_FORMAT_R8G8B8A8_UNORM</li>
+ * <li>OpenGL ES: GL_RGBA8</li>
+ * </ul>
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see AHardwareBuffer
+ */
+ AIMAGE_FORMAT_RGBA_8888 = 0x1,
+
+ /**
+ * 32 bits RGBX format, 8 bits for each of the four channels.
+ *
+ * <p>
+ * Corresponding formats:
+ * <ul>
+ * <li>AHardwareBuffer: AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM</li>
+ * <li>Vulkan: VK_FORMAT_R8G8B8A8_UNORM</li>
+ * <li>OpenGL ES: GL_RGBA8</li>
+ * </ul>
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see AHardwareBuffer
+ */
+ AIMAGE_FORMAT_RGBX_8888 = 0x2,
+
+ /**
+ * 24 bits RGB format, 8 bits for each of the three channels.
+ *
+ * <p>
+ * Corresponding formats:
+ * <ul>
+ * <li>AHardwareBuffer: AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM</li>
+ * <li>Vulkan: VK_FORMAT_R8G8B8_UNORM</li>
+ * <li>OpenGL ES: GL_RGB8</li>
+ * </ul>
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see AHardwareBuffer
+ */
+ AIMAGE_FORMAT_RGB_888 = 0x3,
+
+ /**
+ * 16 bits RGB format, 5 bits for Red channel, 6 bits for Green channel,
+ * and 5 bits for Blue channel.
+ *
+ * <p>
+ * Corresponding formats:
+ * <ul>
+ * <li>AHardwareBuffer: AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM</li>
+ * <li>Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16</li>
+ * <li>OpenGL ES: GL_RGB565</li>
+ * </ul>
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see AHardwareBuffer
+ */
+ AIMAGE_FORMAT_RGB_565 = 0x4,
+
+ /**
+ * 64 bits RGBA format, 16 bits for each of the four channels.
+ *
+ * <p>
+ * Corresponding formats:
+ * <ul>
+ * <li>AHardwareBuffer: AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT</li>
+ * <li>Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT</li>
+ * <li>OpenGL ES: GL_RGBA16F</li>
+ * </ul>
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see AHardwareBuffer
+ */
+ AIMAGE_FORMAT_RGBA_FP16 = 0x16,
+
+ /**
* Multi-plane Android YUV 420 format.
*
* <p>This format is a generic YCbCr format, capable of describing any 4:2:0
diff --git a/media/libaaudio/include/aaudio/AAudioDefinitions.h b/media/libaaudio/include/aaudio/AAudioDefinitions.h
index 5b7b819..e5b7d7a 100644
--- a/media/libaaudio/include/aaudio/AAudioDefinitions.h
+++ b/media/libaaudio/include/aaudio/AAudioDefinitions.h
@@ -23,8 +23,6 @@
extern "C" {
#endif
-typedef int32_t aaudio_result_t;
-
/**
* This is used to represent a value that has not been specified.
* For example, an application could use AAUDIO_UNSPECIFIED to indicate
@@ -34,12 +32,13 @@
#define AAUDIO_UNSPECIFIED 0
#define AAUDIO_DEVICE_UNSPECIFIED ((int32_t) -1)
-enum aaudio_direction_t {
+enum {
AAUDIO_DIRECTION_OUTPUT,
AAUDIO_DIRECTION_INPUT
};
+typedef int32_t aaudio_direction_t;
-enum aaudio_audio_format_t {
+enum {
AAUDIO_FORMAT_INVALID = -1,
AAUDIO_FORMAT_UNSPECIFIED = 0,
AAUDIO_FORMAT_PCM_I16,
@@ -47,6 +46,7 @@
AAUDIO_FORMAT_PCM_I8_24,
AAUDIO_FORMAT_PCM_I32
};
+typedef int32_t aaudio_audio_format_t;
enum {
AAUDIO_OK,
@@ -71,8 +71,9 @@
AAUDIO_ERROR_OUT_OF_RANGE,
AAUDIO_ERROR_NO_SERVICE
};
+typedef int32_t aaudio_result_t;
-typedef enum
+enum
{
AAUDIO_STREAM_STATE_UNINITIALIZED = 0,
AAUDIO_STREAM_STATE_UNKNOWN,
@@ -87,9 +88,10 @@
AAUDIO_STREAM_STATE_STOPPED,
AAUDIO_STREAM_STATE_CLOSING,
AAUDIO_STREAM_STATE_CLOSED,
-} aaudio_stream_state_t;
+};
+typedef int32_t aaudio_stream_state_t;
-typedef enum {
+enum {
/**
* This will be the only stream using a particular source or sink.
* This mode will provide the lowest possible latency.
@@ -101,7 +103,8 @@
* This will have higher latency than the EXCLUSIVE mode.
*/
AAUDIO_SHARING_MODE_SHARED
-} aaudio_sharing_mode_t;
+};
+typedef int32_t aaudio_sharing_mode_t;
#ifdef __cplusplus
}
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 255e350..4e2a0d5 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -935,7 +935,6 @@
}
return reply.readInt64();
}
-
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -945,6 +944,29 @@
status_t BnAudioFlinger::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
+ // Whitelist of relevant events to trigger log merging.
+ // Log merging should activate during audio activity of any kind. This are considered the
+ // most relevant events.
+ // TODO should select more wisely the items from the list
+ switch (code) {
+ case CREATE_TRACK:
+ case OPEN_RECORD:
+ case SET_MASTER_VOLUME:
+ case SET_MASTER_MUTE:
+ case SET_STREAM_VOLUME:
+ case SET_STREAM_MUTE:
+ case SET_MIC_MUTE:
+ case SET_PARAMETERS:
+ case OPEN_INPUT:
+ case SET_VOICE_VOLUME:
+ case CREATE_EFFECT:
+ case SYSTEM_READY: {
+ requestLogMerge();
+ break;
+ }
+ default:
+ break;
+ }
switch (code) {
case CREATE_TRACK: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index db115ef..539558d 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -194,8 +194,8 @@
}
return analyzeResult(retval);
}
- if (ret == -EAGAIN) {
- // This normally retries no more than once.
+ if (ret == -EAGAIN || ret == -EINTR) {
+ // Spurious wakeup. This normally retries no more than once.
goto retry;
}
return ret;
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/StreamHalHidl.cpp
index 77ba716..5b06b73 100644
--- a/media/libaudiohal/StreamHalHidl.cpp
+++ b/media/libaudiohal/StreamHalHidl.cpp
@@ -360,8 +360,8 @@
}
return ret;
}
- if (ret == -EAGAIN) {
- // This normally retries no more than once.
+ if (ret == -EAGAIN || ret == -EINTR) {
+ // Spurious wakeup. This normally retries no more than once.
goto retry;
}
return ret;
@@ -620,8 +620,8 @@
}
return ret;
}
- if (ret == -EAGAIN) {
- // This normally retries no more than once.
+ if (ret == -EAGAIN || ret == -EINTR) {
+ // Spurious wakeup. This normally retries no more than once.
goto retry;
}
return ret;
diff --git a/media/libmedia/include/CryptoHal.h b/media/libmedia/include/CryptoHal.h
index 9d0c3e4..28ade20 100644
--- a/media/libmedia/include/CryptoHal.h
+++ b/media/libmedia/include/CryptoHal.h
@@ -20,11 +20,14 @@
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+
#include <media/ICrypto.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
-#include "SharedLibrary.h"
+using ::android::hardware::drm::V1_0::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::SharedBuffer;
class IMemoryHeap;
@@ -60,9 +63,8 @@
private:
mutable Mutex mLock;
- sp<SharedLibrary> mLibrary;
- sp<::android::hardware::drm::V1_0::ICryptoFactory> mFactory;
- sp<::android::hardware::drm::V1_0::ICryptoPlugin> mPlugin;
+ const Vector<sp<ICryptoFactory>> mFactories;
+ sp<ICryptoPlugin> mPlugin;
/**
* mInitCheck is:
@@ -75,16 +77,13 @@
KeyedVector<void *, uint32_t> mHeapBases;
uint32_t mNextBufferId;
- sp<::android::hardware::drm::V1_0::ICryptoFactory>
- makeCryptoFactory();
- sp<::android::hardware::drm::V1_0::ICryptoPlugin>
- makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
- size_t size);
+ Vector<sp<ICryptoFactory>> makeCryptoFactories();
+ sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void *initData, size_t size);
void setHeapBase(const sp<IMemoryHeap>& heap);
- status_t toSharedBuffer(const sp<IMemory>& memory,
- ::android::hardware::drm::V1_0::SharedBuffer* buffer);
+ status_t toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer);
DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
};
diff --git a/media/libmedia/include/DrmHal.h b/media/libmedia/include/DrmHal.h
index 82d2555..e031765 100644
--- a/media/libmedia/include/DrmHal.h
+++ b/media/libmedia/include/DrmHal.h
@@ -87,7 +87,7 @@
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey);
- virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
+ virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
@@ -158,7 +158,7 @@
mutable Mutex mEventLock;
mutable Mutex mNotifyLock;
- sp<IDrmFactory> mFactory;
+ const Vector<sp<IDrmFactory>> mFactories;
sp<IDrmPlugin> mPlugin;
/**
@@ -169,9 +169,9 @@
*/
status_t mInitCheck;
- sp<IDrmFactory> makeDrmFactory();
- sp<IDrmPlugin> makeDrmPlugin(const uint8_t uuid[16],
- const String8 &appPackageName);
+ Vector<sp<IDrmFactory>> makeDrmFactories();
+ sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& appPackageName);
void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 3b2a8a1..19c4d85 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -49,6 +49,7 @@
mSeekInProgress(false),
mPlayingTimeUs(0),
mLooper(new ALooper),
+ mPlayer(new NuPlayer(pid)),
mPlayerFlags(0),
mAnalyticsItem(NULL),
mAtEOS(false),
@@ -66,7 +67,6 @@
true, /* canCallJava */
PRIORITY_AUDIO);
- mPlayer = new NuPlayer(pid);
mLooper->registerHandler(mPlayer);
mPlayer->setDriver(this);
@@ -998,8 +998,6 @@
{
ALOGV("prepareDrm(%p) state: %d", this, mState);
- Mutex::Autolock autoLock(mLock);
-
// leaving the state verification for mediaplayer.cpp
status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
@@ -1012,8 +1010,6 @@
{
ALOGV("releaseDrm(%p) state: %d", this, mState);
- Mutex::Autolock autoLock(mLock);
-
// leaving the state verification for mediaplayer.cpp
status_t ret = mPlayer->releaseDrm();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 972a348..082f71a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -127,7 +127,7 @@
// <<<
sp<ALooper> mLooper;
- sp<NuPlayer> mPlayer;
+ const sp<NuPlayer> mPlayer;
sp<AudioSink> mAudioSink;
uint32_t mPlayerFlags;
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index f480c16..7936ad2 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "NBLog"
//#define LOG_NDEBUG 0
+#include <climits>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -90,8 +91,9 @@
return -1;
}
-size_t NBLog::FormatEntry::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const {
- auto it = this->begin();
+NBLog::FormatEntry::iterator NBLog::FormatEntry::copyWithAuthor(
+ std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const {
+ auto it = begin();
// copy fmt start entry
it.copyTo(dst);
// insert author entry
@@ -109,7 +111,7 @@
}
it.copyTo(dst);
++it;
- return it - this->begin();
+ return it;
}
void NBLog::FormatEntry::iterator::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const {
@@ -125,6 +127,9 @@
return iterator(mEntry);
}
+NBLog::FormatEntry::iterator::iterator()
+ : ptr(nullptr) {}
+
NBLog::FormatEntry::iterator::iterator(const uint8_t *entry)
: ptr(entry) {}
@@ -149,6 +154,16 @@
return *this;
}
+NBLog::FormatEntry::iterator NBLog::FormatEntry::iterator::next() const {
+ iterator aux(*this);
+ return ++aux;
+}
+
+NBLog::FormatEntry::iterator NBLog::FormatEntry::iterator::prev() const {
+ iterator aux(*this);
+ return --aux;
+}
+
int NBLog::FormatEntry::iterator::operator-(const NBLog::FormatEntry::iterator &other) const {
return ptr - other.ptr;
}
@@ -579,6 +594,23 @@
delete mFifo;
}
+uint8_t *NBLog::Reader::findLastEntryOfType(uint8_t *front, uint8_t *back, uint8_t type) {
+ while (back + Entry::kPreviousLengthOffset >= front) {
+ uint8_t *prev = back - back[Entry::kPreviousLengthOffset] - Entry::kOverhead;
+ if (prev < front || prev + prev[offsetof(FormatEntry::entry, length)] +
+ Entry::kOverhead != back) {
+
+ // prev points to an out of limits or inconsistent entry
+ return nullptr;
+ }
+ if (prev[offsetof(FormatEntry::entry, type)] == type) {
+ return prev;
+ }
+ back = prev;
+ }
+ return nullptr; // no entry found
+}
+
std::unique_ptr<NBLog::Reader::Snapshot> NBLog::Reader::getSnapshot()
{
if (mFifoReader == NULL) {
@@ -587,22 +619,66 @@
// make a copy to avoid race condition with writer
size_t capacity = mFifo->capacity();
- std::unique_ptr<Snapshot> snapshot(new Snapshot(capacity));
+ // This emulates the behaviour of audio_utils_fifo_reader::read, but without incrementing the
+ // reader index. The index is incremented after handling corruption, to after the last complete
+ // entry of the buffer
+ size_t lost;
+ audio_utils_iovec iovec[2];
+ ssize_t availToRead = mFifoReader->obtain(iovec, capacity, NULL /*timeout*/, &lost);
+ if (availToRead <= 0) {
+ return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot());
+ }
- ssize_t actual = mFifoReader->read((void*) snapshot->mData, capacity, NULL /*timeout*/,
- &(snapshot->mLost));
- ALOG_ASSERT(actual <= capacity);
- snapshot->mAvail = actual > 0 ? (size_t) actual : 0;
+ std::unique_ptr<Snapshot> snapshot(new Snapshot(availToRead));
+ memcpy(snapshot->mData, (const char *) mFifo->buffer() + iovec[0].mOffset, iovec[0].mLength);
+ if (iovec[1].mLength > 0) {
+ memcpy(snapshot->mData + (iovec[0].mLength),
+ (const char *) mFifo->buffer() + iovec[1].mOffset, iovec[1].mLength);
+ }
+
+ // Handle corrupted buffer
+ // Potentially, a buffer has corrupted data on both beginning (due to overflow) and end
+ // (due to incomplete format entry). But even if the end format entry is incomplete,
+ // it ends in a complete entry (which is not an END_FMT). So is safe to traverse backwards.
+ // TODO: handle client corruption (in the middle of a buffer)
+
+ uint8_t *back = snapshot->mData + availToRead;
+ uint8_t *front = snapshot->mData;
+
+ // Find last END_FMT. <back> is sitting on an entry which might be the middle of a FormatEntry.
+ // We go backwards until we find an EVENT_END_FMT.
+ uint8_t *lastEnd = findLastEntryOfType(front, back, EVENT_END_FMT);
+ if (lastEnd == nullptr) {
+ snapshot->mEnd = snapshot->mBegin = FormatEntry::iterator(front);
+ } else {
+ // end of snapshot points to after last END_FMT entry
+ snapshot->mEnd = FormatEntry::iterator(lastEnd + Entry::kOverhead);
+ // find first START_FMT
+ uint8_t *firstStart = nullptr;
+ uint8_t *firstStartTmp = lastEnd;
+ while ((firstStartTmp = findLastEntryOfType(front, firstStartTmp, EVENT_START_FMT))
+ != nullptr) {
+ firstStart = firstStartTmp;
+ }
+ // firstStart is null if no START_FMT entry was found before lastEnd
+ if (firstStart == nullptr) {
+ snapshot->mBegin = snapshot->mEnd;
+ } else {
+ snapshot->mBegin = FormatEntry::iterator(firstStart);
+ }
+ }
+
+ // advance fifo reader index to after last entry read.
+ mFifoReader->release(snapshot->mEnd - front);
+
+ snapshot->mLost = lost;
return snapshot;
+
}
void NBLog::Reader::dump(int fd, size_t indent, NBLog::Reader::Snapshot &snapshot)
{
- NBLog::FormatEntry::iterator entry(snapshot.data() + snapshot.available());
- NBLog::FormatEntry::iterator prevEntry = entry;
- --prevEntry;
- NBLog::FormatEntry::iterator start(snapshot.data());
-
+#if 0
struct timespec ts;
time_t maxSec = -1;
while (entry - start >= (int) Entry::kOverhead) {
@@ -622,16 +698,18 @@
--entry;
--prevEntry;
}
+#endif
mFd = fd;
mIndent = indent;
String8 timestamp, body;
- size_t lost = snapshot.lost() + (entry - start);
+ size_t lost = snapshot.lost() + (snapshot.begin() - FormatEntry::iterator(snapshot.data()));
if (lost > 0) {
body.appendFormat("warning: lost %zu bytes worth of events", lost);
// TODO timestamp empty here, only other choice to wait for the first timestamp event in the
// log to push it out. Consider keeping the timestamp/body between calls to readAt().
dumpLine(timestamp, body);
}
+#if 0
size_t width = 1;
while (maxSec >= 10) {
++width;
@@ -641,9 +719,8 @@
timestamp.appendFormat("[%*s]", (int) width + 4, "");
}
bool deferredTimestamp = false;
- NBLog::FormatEntry::iterator end(snapshot.data() + snapshot.available());
-
- while (entry != end) {
+#endif
+ for (auto entry = snapshot.begin(); entry != snapshot.end();) {
switch (entry->type) {
#if 0
case EVENT_STRING:
@@ -716,21 +793,23 @@
break;
case EVENT_END_FMT:
body.appendFormat("warning: got to end format event");
+ ++entry;
break;
case EVENT_RESERVED:
default:
- body.appendFormat("warning: unknown event %d", entry->type);
+ body.appendFormat("warning: unexpected event %d", entry->type);
+ ++entry;
break;
}
if (!body.isEmpty()) {
dumpLine(timestamp, body);
- deferredTimestamp = false;
+ // deferredTimestamp = false;
}
}
- if (deferredTimestamp) {
- dumpLine(timestamp, body);
- }
+ // if (deferredTimestamp) {
+ // dumpLine(timestamp, body);
+ // }
}
void NBLog::Reader::dump(int fd, size_t indent)
@@ -816,12 +895,6 @@
size_t length = arg->length;
// TODO check length for event type is correct
- if (!arg.hasConsistentLength()) {
- // TODO: corrupt, resync buffer
- body->append("<invalid entry>");
- ++fmt_offset;
- continue;
- }
if (event == EVENT_END_FMT) {
break;
@@ -909,37 +982,33 @@
void NBLog::Merger::merge() {
int nLogs = mNamedReaders.size();
std::vector<std::unique_ptr<NBLog::Reader::Snapshot>> snapshots(nLogs);
+ std::vector<NBLog::FormatEntry::iterator> offsets(nLogs);
for (int i = 0; i < nLogs; ++i) {
snapshots[i] = mNamedReaders[i].reader()->getSnapshot();
+ offsets[i] = snapshots[i]->begin();
}
// initialize offsets
- std::vector<size_t> offsets(nLogs, 0);
// TODO custom heap implementation could allow to update top, improving performance
// for bursty buffers
std::priority_queue<MergeItem, std::vector<MergeItem>, std::greater<MergeItem>> timestamps;
for (int i = 0; i < nLogs; ++i)
{
- if (snapshots[i]->available() > 0) {
- timespec ts = FormatEntry(snapshots[i]->data()).timestamp();
- MergeItem item(ts, i);
- timestamps.push(item);
+ if (offsets[i] != snapshots[i]->end()) {
+ timespec ts = FormatEntry(offsets[i]).timestamp();
+ timestamps.emplace(ts, i);
}
}
while (!timestamps.empty()) {
// find minimum timestamp
int index = timestamps.top().index;
- // copy it to the log
- size_t length = FormatEntry(snapshots[index]->data() + offsets[index]).copyTo(
- mFifoWriter, index);
+ // copy it to the log, increasing offset
+ offsets[index] = FormatEntry(offsets[index]).copyWithAuthor(mFifoWriter, index);
// update data structures
- offsets[index] += length;
- ALOGW_IF(offsets[index] > snapshots[index]->available(), "Overflown snapshot capacity");
timestamps.pop();
- if (offsets[index] != snapshots[index]->available()) {
- timespec ts = FormatEntry(snapshots[index]->data() + offsets[index]).timestamp();
- MergeItem item(ts, index);
- timestamps.emplace(item);
+ if (offsets[index] != snapshots[index]->end()) {
+ timespec ts = FormatEntry(offsets[index]).timestamp();
+ timestamps.emplace(ts, index);
}
}
}
@@ -958,4 +1027,42 @@
return NBLog::Entry::kOverhead + sizeof(author);
}
+NBLog::MergeThread::MergeThread(NBLog::Merger &merger)
+ : mMerger(merger),
+ mTimeoutUs(0) {}
+
+NBLog::MergeThread::~MergeThread() {
+ // set exit flag, set timeout to 0 to force threadLoop to exit and wait for the thread to join
+ requestExit();
+ setTimeoutUs(0);
+ join();
+}
+
+bool NBLog::MergeThread::threadLoop() {
+ bool doMerge;
+ {
+ AutoMutex _l(mMutex);
+ // If mTimeoutUs is negative, wait on the condition variable until it's positive.
+ // If it's positive, wait kThreadSleepPeriodUs and then merge
+ nsecs_t waitTime = mTimeoutUs > 0 ? kThreadSleepPeriodUs * 1000 : LLONG_MAX;
+ mCond.waitRelative(mMutex, waitTime);
+ doMerge = mTimeoutUs > 0;
+ mTimeoutUs -= kThreadSleepPeriodUs;
+ }
+ if (doMerge) {
+ mMerger.merge();
+ }
+ return true;
+}
+
+void NBLog::MergeThread::wakeup() {
+ setTimeoutUs(kThreadWakeupPeriodUs);
+}
+
+void NBLog::MergeThread::setTimeoutUs(int time) {
+ AutoMutex _l(mMutex);
+ mTimeoutUs = time;
+ mCond.signal();
+}
+
} // namespace android
diff --git a/media/libnbaio/PipeReader.cpp b/media/libnbaio/PipeReader.cpp
index bd468a6..be5c0c1 100644
--- a/media/libnbaio/PipeReader.cpp
+++ b/media/libnbaio/PipeReader.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <cutils/compiler.h>
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <media/nbaio/PipeReader.h>
diff --git a/media/libnbaio/include/NBLog.h b/media/libnbaio/include/NBLog.h
index 043f15e..7aaf298 100644
--- a/media/libnbaio/include/NBLog.h
+++ b/media/libnbaio/include/NBLog.h
@@ -20,8 +20,9 @@
#define ANDROID_MEDIA_NBLOG_H
#include <binder/IMemory.h>
-#include <utils/Mutex.h>
#include <audio_utils/fifo.h>
+#include <utils/Mutex.h>
+#include <utils/threads.h>
#include <vector>
@@ -41,6 +42,7 @@
enum Event {
EVENT_RESERVED,
EVENT_STRING, // ASCII string, not NUL-terminated
+ // TODO: make timestamp optional
EVENT_TIMESTAMP, // clock_gettime(CLOCK_MONOTONIC)
EVENT_INTEGER, // integer value entry
EVENT_FLOAT, // floating point value entry
@@ -87,6 +89,7 @@
// entry iterator
class iterator {
public:
+ iterator();
iterator(const uint8_t *entry);
iterator(const iterator &other);
@@ -97,6 +100,8 @@
iterator& operator++(); // ++i
// back to previous entry
iterator& operator--(); // --i
+ iterator next() const;
+ iterator prev() const;
bool operator!=(const iterator &other) const;
int operator-(const iterator &other) const;
@@ -106,7 +111,7 @@
template<typename T>
inline const T& payload() {
- return *reinterpret_cast<const T *>(ptr + 2);
+ return *reinterpret_cast<const T *>(ptr + offsetof(entry, data));
}
private:
@@ -132,7 +137,7 @@
int author() const;
// copy entry, adding author before timestamp, returns size of original entry
- size_t copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
+ iterator copyWithAuthor(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
iterator begin() const;
@@ -315,26 +320,32 @@
// A snapshot of a readers buffer
class Snapshot {
public:
- Snapshot() : mData(NULL), mAvail(0), mLost(0) {}
+ Snapshot() : mData(NULL), mLost(0) {}
Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
~Snapshot() { delete[] mData; }
// copy of the buffer
- const uint8_t *data() const { return mData; }
-
- // amount of data available (given by audio_utils_fifo_reader)
- size_t available() const { return mAvail; }
+ uint8_t *data() const { return mData; }
// amount of data lost (given by audio_utils_fifo_reader)
size_t lost() const { return mLost; }
+ // iterator to beginning of readable segment of snapshot
+ // data between begin and end has valid entries
+ FormatEntry::iterator begin() { return mBegin; }
+
+ // iterator to end of readable segment of snapshot
+ FormatEntry::iterator end() { return mEnd; }
+
+
private:
friend class Reader;
- const uint8_t *mData;
- size_t mAvail;
- size_t mLost;
+ uint8_t *mData;
+ size_t mLost;
+ FormatEntry::iterator mBegin;
+ FormatEntry::iterator mEnd;
};
// Input parameter 'size' is the desired size of the timeline in byte units.
@@ -371,6 +382,10 @@
// dummy method for handling absent author entry
virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; }
+ // Searches for the last entry of type <type> in the range [front, back)
+ // back has to be entry-aligned. Returns nullptr if none enconuntered.
+ static uint8_t *findLastEntryOfType(uint8_t *front, uint8_t *back, uint8_t type);
+
static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
};
@@ -425,6 +440,43 @@
size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body);
};
+// MergeThread is a thread that contains a Merger. It works as a retriggerable one-shot:
+// when triggered, it awakes for a lapse of time, during which it periodically merges; if
+// retriggered, the timeout is reset.
+// The thread is triggered on AudioFlinger binder activity.
+class MergeThread : public Thread {
+public:
+ MergeThread(Merger &merger);
+ virtual ~MergeThread() override;
+
+ // Reset timeout and activate thread to merge periodically if it's idle
+ void wakeup();
+
+ // Set timeout period until the merging thread goes idle again
+ void setTimeoutUs(int time);
+
+private:
+ virtual bool threadLoop() override;
+
+ // the merger who actually does the work of merging the logs
+ Merger& mMerger;
+
+ // mutex for the condition variable
+ Mutex mMutex;
+
+ // condition variable to activate merging on timeout >= 0
+ Condition mCond;
+
+ // time left until the thread blocks again (in microseconds)
+ int mTimeoutUs;
+
+ // merging period when the thread is awake
+ static const int kThreadSleepPeriodUs = 1000000 /*1s*/;
+
+ // initial timeout value when triggered
+ static const int kThreadWakeupPeriodUs = 3000000 /*3s*/;
+};
+
}; // class NBLog
} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index d46ef3c..cafedba 100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3669,11 +3669,19 @@
mOwner->beginBox("ctts");
mOwner->writeInt32(0); // version=0, flags=0
- uint32_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
+ int64_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
// entries are <count, ctts> pairs; adjust only ctts
uint32_t duration = htonl(value[1]); // back to host byte order
- value[1] = htonl(duration - delta);
+ // Prevent overflow and underflow
+ if (delta > duration) {
+ duration = 0;
+ } else if (delta < 0 && UINT32_MAX + delta < duration) {
+ duration = UINT32_MAX;
+ } else {
+ duration -= delta;
+ }
+ value[1] = htonl(duration);
});
mCttsTableEntries->write(mOwner);
mOwner->endBox(); // ctts
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index de5ea9c..1d2a931 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -701,7 +701,13 @@
}
++sampleIndex;
- sampleTime += delta;
+ if (sampleTime > UINT32_MAX - delta) {
+ ALOGE("%u + %u would overflow, clamping",
+ sampleTime, delta);
+ sampleTime = UINT32_MAX;
+ } else {
+ sampleTime += delta;
+ }
}
}
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 4f1ef30..d0d82b3 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -29,7 +29,6 @@
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
#include <gui/ISurfaceComposer.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <OMX_Component.h>
#include <utils/Log.h>
diff --git a/media/libstagefright/include/SurfaceMediaSource.h b/media/libstagefright/include/SurfaceMediaSource.h
index ca3a3bf..ae19a75 100644
--- a/media/libstagefright/include/SurfaceMediaSource.h
+++ b/media/libstagefright/include/SurfaceMediaSource.h
@@ -32,7 +32,6 @@
namespace android {
// ----------------------------------------------------------------------------
-class IGraphicBufferAlloc;
class String8;
class GraphicBuffer;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 5a1d6dc..88dabff 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -54,7 +54,7 @@
MTP_OPERATION_SEND_OBJECT,
// MTP_OPERATION_INITIATE_CAPTURE,
// MTP_OPERATION_FORMAT_STORE,
-// MTP_OPERATION_RESET_DEVICE,
+ MTP_OPERATION_RESET_DEVICE,
// MTP_OPERATION_SELF_TEST,
// MTP_OPERATION_SET_OBJECT_PROTECTION,
// MTP_OPERATION_POWER_DOWN,
@@ -362,6 +362,7 @@
case MTP_OPERATION_OPEN_SESSION:
response = doOpenSession();
break;
+ case MTP_OPERATION_RESET_DEVICE:
case MTP_OPERATION_CLOSE_SESSION:
response = doCloseSession();
break;
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 30aa7fb..ab3829e 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -22,6 +22,7 @@
#include "NdkImagePriv.h"
#include "NdkImageReaderPriv.h"
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <android_runtime/android_view_Surface.h>
@@ -41,6 +42,11 @@
bool
AImageReader::isSupportedFormat(int32_t format) {
switch (format) {
+ case AIMAGE_FORMAT_RGBA_8888:
+ case AIMAGE_FORMAT_RGBX_8888:
+ case AIMAGE_FORMAT_RGB_888:
+ case AIMAGE_FORMAT_RGB_565:
+ case AIMAGE_FORMAT_RGBA_FP16:
case AIMAGE_FORMAT_YUV_420_888:
case AIMAGE_FORMAT_JPEG:
case AIMAGE_FORMAT_RAW16:
@@ -60,6 +66,11 @@
switch (format) {
case AIMAGE_FORMAT_YUV_420_888:
return 3;
+ case AIMAGE_FORMAT_RGBA_8888:
+ case AIMAGE_FORMAT_RGBX_8888:
+ case AIMAGE_FORMAT_RGB_888:
+ case AIMAGE_FORMAT_RGB_565:
+ case AIMAGE_FORMAT_RGBA_FP16:
case AIMAGE_FORMAT_JPEG:
case AIMAGE_FORMAT_RAW16:
case AIMAGE_FORMAT_RAW_PRIVATE:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3d1f268..c0918d4 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -129,6 +129,7 @@
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
+ mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
mPrimaryHardwareDev(NULL),
mAudioHwDevs(NULL),
mHardwareStatus(AUDIO_HW_IDLE),
@@ -163,6 +164,8 @@
mDevicesFactoryHal = DevicesFactoryHalInterface::create();
mEffectsFactoryHal = EffectsFactoryHalInterface::create();
+ mMediaLogNotifier->run("MediaLogNotifier");
+
#ifdef TEE_SINK
char value[PROPERTY_VALUE_MAX];
(void) property_get("ro.debuggable", value, "0");
@@ -1528,6 +1531,41 @@
mAudioFlinger->removeNotificationClient(mPid);
}
+// ----------------------------------------------------------------------------
+AudioFlinger::MediaLogNotifier::MediaLogNotifier()
+ : mPendingRequests(false) {}
+
+
+void AudioFlinger::MediaLogNotifier::requestMerge() {
+ AutoMutex _l(mMutex);
+ mPendingRequests = true;
+ mCond.signal();
+}
+
+bool AudioFlinger::MediaLogNotifier::threadLoop() {
+ // Wait until there are pending requests
+ {
+ AutoMutex _l(mMutex);
+ mPendingRequests = false; // to ignore past requests
+ while (!mPendingRequests) {
+ mCond.wait(mMutex);
+ // TODO may also need an exitPending check
+ }
+ mPendingRequests = false;
+ }
+ // Execute the actual MediaLogService binder call and ignore extra requests for a while
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
+ if (binder != 0) {
+ sp<IMediaLogService> mediaLogService(interface_cast<IMediaLogService>(binder));
+ mediaLogService->requestMergeWakeup();
+ }
+ usleep(kPostTriggerSleepPeriod);
+ return true;
+}
+
+void AudioFlinger::requestLogMerge() {
+ mMediaLogNotifier->requestMerge();
+}
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 44fd512..b79f09e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -472,6 +472,38 @@
const sp<IAudioFlingerClient> mAudioFlingerClient;
};
+ // --- MediaLogNotifier ---
+ // Thread in charge of notifying MediaLogService to start merging.
+ // Receives requests from AudioFlinger's binder activity. It is used to reduce the amount of
+ // binder calls to MediaLogService in case of bursts of AudioFlinger binder calls.
+ class MediaLogNotifier : public Thread {
+ public:
+ MediaLogNotifier();
+
+ // Requests a MediaLogService notification. It's ignored if there has recently been another
+ void requestMerge();
+ private:
+ // Every iteration blocks waiting for a request, then interacts with MediaLogService to
+ // start merging.
+ // As every MediaLogService binder call is expensive, once it gets a request it ignores the
+ // following ones for a period of time.
+ virtual bool threadLoop() override;
+
+ bool mPendingRequests;
+
+ // Mutex and condition variable around mPendingRequests' value
+ Mutex mMutex;
+ Condition mCond;
+
+ // Duration of the sleep period after a processed request
+ static const int kPostTriggerSleepPeriod = 1000000;
+ };
+
+ const sp<MediaLogNotifier> mMediaLogNotifier;
+
+ // This is a helper that is called during incoming binder calls.
+ void requestLogMerge();
+
class TrackHandle;
class RecordHandle;
class RecordThread;
@@ -563,6 +595,7 @@
virtual status_t getMmapPosition(struct audio_mmap_position *position);
virtual status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
virtual status_t stop(audio_port_handle_t handle);
+ virtual status_t standby();
private:
sp<MmapThread> mThread;
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index dca7bf9..caf7905 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -22,6 +22,7 @@
#include "Configuration.h"
#include <linux/futex.h>
#include <sys/syscall.h>
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#include "FastThread.h"
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b10e42c..14ff6ee 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2953,6 +2953,10 @@
#endif
while (!exitPending())
{
+ // Log merge requests are performed during AudioFlinger binder transactions, but
+ // that does not cover audio playback. It's requested here for that reason.
+ mAudioFlinger->requestLogMerge();
+
cpuStats.sample(myName);
Vector< sp<EffectChain> > effectChains;
@@ -7434,7 +7438,7 @@
{
MmapThread *thread = mThread.get();
// clear our strong reference before disconnecting the thread: the last strong reference
- // will be removed when closeInput/closeOutput is executed upono call from audio policy manager
+ // will be removed when closeInput/closeOutput is executed upon call from audio policy manager
// and the thread removed from mMMapThreads list causing the thread destruction.
mThread.clear();
if (thread != nullptr) {
@@ -7476,6 +7480,14 @@
return mThread->stop(handle);
}
+status_t AudioFlinger::MmapThreadHandle::standby()
+{
+ if (mThread == 0) {
+ return NO_INIT;
+ }
+ return mThread->standby();
+}
+
AudioFlinger::MmapThread::MmapThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
@@ -7484,11 +7496,13 @@
: ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev)
{
+ mStandby = true;
readHalParameters_l();
}
AudioFlinger::MmapThread::~MmapThread()
{
+ releaseWakeLock_l();
}
void AudioFlinger::MmapThread::onFirstRef()
@@ -7528,6 +7542,8 @@
if (mHalStream == 0) {
return NO_INIT;
}
+ mStandby = true;
+ acquireWakeLock();
return mHalStream->createMmapBuffer(minSizeFrames, info);
}
@@ -7542,7 +7558,7 @@
status_t AudioFlinger::MmapThread::start(const MmapStreamInterface::Client& client,
audio_port_handle_t *handle)
{
- ALOGV("%s clientUid %d", __FUNCTION__, client.clientUid);
+ ALOGV("%s clientUid %d mStandby %d", __FUNCTION__, client.clientUid, mStandby);
if (mHalStream == 0) {
return NO_INIT;
}
@@ -7556,6 +7572,7 @@
mHalStream->start();
portId = mPortId;
sessionId = mSessionId;
+ mStandby = false;
} else {
// for other tracks than first one, get a new port ID from APM.
sessionId = (audio_session_t)mAudioFlinger->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
@@ -7613,6 +7630,8 @@
} else {
AudioSystem::releaseInput(mId, sessionId);
}
+ } else {
+ mHalStream->stop();
}
return PERMISSION_DENIED;
}
@@ -7632,14 +7651,13 @@
broadcast_l();
- ALOGV("%s DONE handle %d", __FUNCTION__, portId);
+ ALOGV("%s DONE handle %d stream %p", __FUNCTION__, portId, mHalStream.get());
return NO_ERROR;
}
status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
{
-
ALOGV("%s handle %d", __FUNCTION__, handle);
if (mHalStream == 0) {
@@ -7685,6 +7703,22 @@
return NO_ERROR;
}
+status_t AudioFlinger::MmapThread::standby()
+{
+ ALOGV("%s", __FUNCTION__);
+
+ if (mHalStream == 0) {
+ return NO_INIT;
+ }
+ if (mActiveTracks.size() != 0) {
+ return INVALID_OPERATION;
+ }
+ mHalStream->standby();
+ mStandby = true;
+ releaseWakeLock();
+ return NO_ERROR;
+}
+
void AudioFlinger::MmapThread::readHalParameters_l()
{
@@ -7701,8 +7735,6 @@
bool AudioFlinger::MmapThread::threadLoop()
{
- acquireWakeLock();
-
checkSilentMode_l();
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
@@ -7724,18 +7756,10 @@
break;
}
- bool wakelockReleased = false;
- if (mActiveTracks.size() == 0) {
- releaseWakeLock_l();
- wakelockReleased = true;
- }
// wait until we have something to do...
ALOGV("%s going to sleep", myName.string());
mWaitWorkCV.wait(mLock);
ALOGV("%s waking up", myName.string());
- if (wakelockReleased) {
- acquireWakeLock_l();
- }
checkSilentMode_l();
@@ -7768,8 +7792,6 @@
mStandby = true;
}
- releaseWakeLock();
-
ALOGV("Thread %p type %d exiting", this, mType);
return false;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0a17a8e..422eeb5 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1540,6 +1540,7 @@
status_t getMmapPosition(struct audio_mmap_position *position);
status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
status_t stop(audio_port_handle_t handle);
+ status_t standby();
// RefBase
virtual void onFirstRef();
@@ -1549,6 +1550,7 @@
virtual void threadLoop_exit();
virtual void threadLoop_standby();
+ virtual bool shouldStandby_l() { return false; }
virtual status_t initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
virtual size_t frameCount() const { return mFrameCount; }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index c2981a1..32606ea 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -22,6 +22,7 @@
#include "TypeConverter.h"
#include <log/log.h>
+#include <cutils/atomic.h>
#include <utils/String8.h>
namespace android {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index aac23b4..6ed2cb7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -21,6 +21,7 @@
#include "HwModule.h"
#include "AudioGain.h"
#include <policy.h>
+#include <cutils/atomic.h>
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 31c145e..7634664 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -32,6 +32,7 @@
#include <AudioPolicyManagerInterface.h>
#include <AudioPolicyEngineInstance.h>
+#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <media/AudioParameter.h>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 7133709..702c92d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -622,7 +622,7 @@
}
} else {
status_t res = mCameraProviderManager->getCameraCharacteristics(
- String16::std_string(cameraId), cameraInfo);
+ String8(cameraId).string(), cameraInfo);
if (res != OK) {
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera "
"characteristics for device %s: %s (%d)", String8(cameraId).string(),
@@ -689,14 +689,14 @@
} else {
status_t res;
hardware::hidl_version maxVersion{0,0};
- res = mCameraProviderManager->getHighestSupportedVersion(String8::std_string(cameraId),
+ res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
&maxVersion);
if (res != OK) return -1;
deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
hardware::CameraInfo info;
if (facing) {
- res = mCameraProviderManager->getCameraInfo(String8::std_string(cameraId), &info);
+ res = mCameraProviderManager->getCameraInfo(cameraId.string(), &info);
if (res != OK) return -1;
*facing = info.facing;
}
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index b83d425..ffb657e 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "CameraClient"
//#define LOG_NDEBUG 0
+#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <gui/Surface.h>
#include <media/hardware/HardwareAPI.h>
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 79e7ff0..4428f75 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -321,7 +321,7 @@
return binder::Status::ok();
}
-binder::Status CameraDeviceClient::endConfigure(bool isConstrainedHighSpeed) {
+binder::Status CameraDeviceClient::endConfigure(int operatingMode) {
ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
__FUNCTION__, mInputStream.configured ? 1 : 0,
mStreamMap.size());
@@ -335,7 +335,16 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
+ if (operatingMode < 0) {
+ String8 msg = String8::format(
+ "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ msg.string());
+ }
+
// Sanitize the high speed session against necessary capability bit.
+ bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
if (isConstrainedHighSpeed) {
CameraMetadata staticInfo = mDevice->info();
camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
@@ -357,7 +366,7 @@
}
}
- status_t err = mDevice->configureStreams(isConstrainedHighSpeed);
+ status_t err = mDevice->configureStreams(operatingMode);
if (err == BAD_VALUE) {
String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 012beb4..2a95c88 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -70,70 +70,70 @@
const hardware::camera2::CaptureRequest& request,
bool streaming = false,
/*out*/
- hardware::camera2::utils::SubmitInfo *submitInfo = nullptr);
+ hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
// List of requests are copied.
virtual binder::Status submitRequestList(
const std::vector<hardware::camera2::CaptureRequest>& requests,
bool streaming = false,
/*out*/
- hardware::camera2::utils::SubmitInfo *submitInfo = nullptr);
+ hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
virtual binder::Status cancelRequest(int requestId,
/*out*/
- int64_t* lastFrameNumber = NULL);
+ int64_t* lastFrameNumber = NULL) override;
- virtual binder::Status beginConfigure();
+ virtual binder::Status beginConfigure() override;
- virtual binder::Status endConfigure(bool isConstrainedHighSpeed = false);
+ virtual binder::Status endConfigure(int operatingMode) override;
// Returns -EBUSY if device is not idle
- virtual binder::Status deleteStream(int streamId);
+ virtual binder::Status deleteStream(int streamId) override;
virtual binder::Status createStream(
const hardware::camera2::params::OutputConfiguration &outputConfiguration,
/*out*/
- int32_t* newStreamId = NULL);
+ int32_t* newStreamId = NULL) override;
// Create an input stream of width, height, and format.
virtual binder::Status createInputStream(int width, int height, int format,
/*out*/
- int32_t* newStreamId = NULL);
+ int32_t* newStreamId = NULL) override;
// Get the buffer producer of the input stream
virtual binder::Status getInputSurface(
/*out*/
- view::Surface *inputSurface);
+ view::Surface *inputSurface) override;
// Create a request object from a template.
virtual binder::Status createDefaultRequest(int templateId,
/*out*/
- hardware::camera2::impl::CameraMetadataNative* request);
+ hardware::camera2::impl::CameraMetadataNative* request) override;
// Get the static metadata for the camera
// -- Caller owns the newly allocated metadata
virtual binder::Status getCameraInfo(
/*out*/
- hardware::camera2::impl::CameraMetadataNative* cameraCharacteristics);
+ hardware::camera2::impl::CameraMetadataNative* cameraCharacteristics) override;
// Wait until all the submitted requests have finished processing
- virtual binder::Status waitUntilIdle();
+ virtual binder::Status waitUntilIdle() override;
// Flush all active and pending requests as fast as possible
virtual binder::Status flush(
/*out*/
- int64_t* lastFrameNumber = NULL);
+ int64_t* lastFrameNumber = NULL) override;
// Prepare stream by preallocating its buffers
- virtual binder::Status prepare(int32_t streamId);
+ virtual binder::Status prepare(int32_t streamId) override;
// Tear down stream resources by freeing its unused buffers
- virtual binder::Status tearDown(int32_t streamId);
+ virtual binder::Status tearDown(int32_t streamId) override;
// Prepare stream by preallocating up to maxCount of its buffers
- virtual binder::Status prepare2(int32_t maxCount, int32_t streamId);
+ virtual binder::Status prepare2(int32_t maxCount, int32_t streamId) override;
// Finalize the output configurations with surfaces not added before.
virtual binder::Status finalizeOutputConfigurations(int32_t streamId,
- const hardware::camera2::params::OutputConfiguration &outputConfiguration);
+ const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
/**
* Interface used by CameraService
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 98a3fcc..f9b062a 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -184,7 +184,7 @@
* - BAD_VALUE if the set of streams was invalid (e.g. fmts or sizes)
* - INVALID_OPERATION if the device was in the wrong state
*/
- virtual status_t configureStreams(bool isConstrainedHighSpeed = false) = 0;
+ virtual status_t configureStreams(int operatingMode = 0) = 0;
// get the buffer producer of the input stream
virtual status_t getInputBufferProducer(
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 3e4e631..b52c0d8 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -80,7 +80,7 @@
ALOGI("Opening camera %s", mName.string());
- status_t ret = manager->openSession(String8::std_string(mName), this, &mHidlDevice);
+ status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
if (ret != OK) {
ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
}
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index d45891f..d93b331 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -19,7 +19,6 @@
#define ATRACE_TAG ATRACE_TAG_CAMERA
#include <gui/ISurfaceComposer.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <private/gui/ComposerService.h>
#include <utils/Log.h>
#include <utils/Trace.h>
@@ -30,15 +29,7 @@
namespace camera3 {
-Camera3BufferManager::Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator) :
- mAllocator(allocator) {
- if (allocator == NULL) {
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- mAllocator = composer->createGraphicBufferAlloc();
- if (mAllocator == NULL) {
- ALOGE("createGraphicBufferAlloc failed");
- }
- }
+Camera3BufferManager::Camera3BufferManager() {
}
Camera3BufferManager::~Camera3BufferManager() {
@@ -79,10 +70,6 @@
}
Mutex::Autolock l(mLock);
- if (mAllocator == NULL) {
- ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
- return INVALID_OPERATION;
- }
// Check if this stream was registered with different stream set ID, if so, error out.
for (size_t i = 0; i < mStreamSetMap.size(); i++) {
@@ -132,10 +119,6 @@
Mutex::Autolock l(mLock);
ALOGV("%s: unregister stream %d with stream set %d", __FUNCTION__,
streamId, streamSetId);
- if (mAllocator == NULL) {
- ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
- return INVALID_OPERATION;
- }
if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
ALOGE("%s: stream %d with set id %d wasn't properly registered to this buffer manager!",
@@ -182,10 +165,6 @@
Mutex::Autolock l(mLock);
ALOGV("%s: get buffer for stream %d with stream set %d", __FUNCTION__,
streamId, streamSetId);
- if (mAllocator == NULL) {
- ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
- return INVALID_OPERATION;
- }
if (!checkIfStreamRegisteredLocked(streamId, streamSetId)) {
ALOGE("%s: stream %d is not registered with stream set %d yet!!!",
@@ -219,15 +198,18 @@
// Allocate one if there is no free buffer available.
if (buffer.graphicBuffer == nullptr) {
const StreamInfo& info = streamSet.streamInfoMap.valueFor(streamId);
- status_t res = OK;
buffer.fenceFd = -1;
- buffer.graphicBuffer = mAllocator->createGraphicBuffer(
- info.width, info.height, info.format, 1 /* layerCount */,
- info.combinedUsage, &res);
+
+ buffer.graphicBuffer = new GraphicBuffer(
+ info.width, info.height, PixelFormat(info.format), info.combinedUsage,
+ std::string("Camera3BufferManager pid [") +
+ std::to_string(getpid()) + "]");
+ status_t res = buffer.graphicBuffer->initCheck();
+
ALOGV("%s: allocating a new graphic buffer (%dx%d, format 0x%x) %p with handle %p",
__FUNCTION__, info.width, info.height, info.format,
buffer.graphicBuffer.get(), buffer.graphicBuffer->handle);
- if (res != OK) {
+ if (res < 0) {
ALOGE("%s: graphic buffer allocation failed: (error %d %s) ",
__FUNCTION__, res, strerror(-res));
return res;
@@ -331,10 +313,6 @@
Mutex::Autolock l(mLock);
ALOGV("Stream %d set %d: Buffer released", streamId, streamSetId);
- if (mAllocator == NULL) {
- ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
- return INVALID_OPERATION;
- }
if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
ALOGV("%s: signaling buffer release for an already unregistered stream "
@@ -363,10 +341,6 @@
Mutex::Autolock l(mLock);
ALOGV_IF(buffer != 0, "%s: return buffer (%p) with handle (%p) for stream %d and stream set %d",
__FUNCTION__, buffer.get(), buffer->handle, streamId, streamSetId);
- if (mAllocator == NULL) {
- ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
- return INVALID_OPERATION;
- }
if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
ALOGV("%s: returning buffer for an already unregistered stream (stream %d with set id %d),"
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.h b/services/camera/libcameraservice/device3/Camera3BufferManager.h
index f44c4a3..d1d7a6f 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.h
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.h
@@ -26,8 +26,6 @@
namespace android {
-class IGraphicBufferAlloc;
-
namespace camera3 {
struct StreamInfo;
@@ -46,7 +44,7 @@
*/
class Camera3BufferManager: public virtual RefBase {
public:
- explicit Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator = NULL);
+ explicit Camera3BufferManager();
virtual ~Camera3BufferManager();
@@ -188,12 +186,6 @@
static const size_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
- /**
- * mAllocator is the connection to SurfaceFlinger that is used to allocate new GraphicBuffer
- * objects.
- */
- sp<IGraphicBufferAlloc> mAllocator;
-
struct GraphicBufferEntry {
sp<GraphicBuffer> graphicBuffer;
int fenceFd;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f20556d..60c716f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -63,6 +63,7 @@
Camera3Device::Camera3Device(const String8 &id):
mId(id),
+ mOperatingMode(NO_MODE),
mIsConstrainedHighSpeedConfiguration(false),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
@@ -182,7 +183,7 @@
sp<ICameraDeviceSession> session;
ATRACE_BEGIN("CameraHal::openSession");
- status_t res = manager->openSession(String8::std_string(mId), this,
+ status_t res = manager->openSession(mId.string(), this,
/*out*/ &session);
ATRACE_END();
if (res != OK) {
@@ -190,7 +191,7 @@
return res;
}
- res = manager->getCameraCharacteristics(String8::std_string(mId), &mDeviceInfo);
+ res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
if (res != OK) {
SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
session->close();
@@ -514,19 +515,25 @@
return StreamRotation::ROTATION_0;
}
-StreamConfigurationMode Camera3Device::mapToStreamConfigurationMode(
- camera3_stream_configuration_mode_t operationMode) {
- switch(operationMode) {
- case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
- return StreamConfigurationMode::NORMAL_MODE;
- case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
- return StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
- case CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START:
- // Needs to be mapped by vendor extensions
- break;
+status_t Camera3Device::mapToStreamConfigurationMode(
+ camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
+ if (mode == nullptr) return BAD_VALUE;
+ if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+ switch(operationMode) {
+ case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
+ *mode = StreamConfigurationMode::NORMAL_MODE;
+ break;
+ case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+ *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
+ break;
+ default:
+ ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
+ return BAD_VALUE;
+ }
+ } else {
+ *mode = static_cast<StreamConfigurationMode>(operationMode);
}
- ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
- return StreamConfigurationMode::NORMAL_MODE;
+ return OK;
}
camera3_buffer_status_t Camera3Device::mapHidlBufferStatus(BufferStatus status) {
@@ -677,8 +684,12 @@
lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
}
lines.appendFormat(" Stream configuration:\n");
- lines.appendFormat(" Operation mode: %s \n", mIsConstrainedHighSpeedConfiguration ?
- "CONSTRAINED HIGH SPEED VIDEO" : "NORMAL");
+ const char *mode =
+ mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
+ mOperatingMode == static_cast<int>(
+ StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
+ "CUSTOM";
+ lines.appendFormat(" Operation mode: %s (%d) \n", mode, mOperatingMode);
if (mInputStream != NULL) {
write(fd, lines.string(), lines.size());
@@ -1093,7 +1104,9 @@
status_t res;
if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
- res = configureStreamsLocked();
+ // This point should only be reached via API1 (API2 must explicitly call configureStreams)
+ // so unilaterally select normal operating mode.
+ res = configureStreamsLocked(CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
// Stream configuration failed. Client might try other configuraitons.
if (res != OK) {
CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
@@ -1195,7 +1208,8 @@
// Continue captures if active at start
if (wasActive) {
ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
- res = configureStreamsLocked();
+ // Reuse current operating mode for new stream config
+ res = configureStreamsLocked(mOperatingMode);
if (res != OK) {
ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
__FUNCTION__, mNextStreamId, strerror(-res), res);
@@ -1357,7 +1371,8 @@
// Continue captures if active at start
if (wasActive) {
ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
- res = configureStreamsLocked();
+ // Reuse current operating mode for new stream config
+ res = configureStreamsLocked(mOperatingMode);
if (res != OK) {
CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
mNextStreamId, strerror(-res), res);
@@ -1501,19 +1516,14 @@
return INVALID_OPERATION;
}
-status_t Camera3Device::configureStreams(bool isConstrainedHighSpeed) {
+status_t Camera3Device::configureStreams(int operatingMode) {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
- if (mIsConstrainedHighSpeedConfiguration != isConstrainedHighSpeed) {
- mNeedConfig = true;
- mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
- }
-
- return configureStreamsLocked();
+ return configureStreamsLocked(operatingMode);
}
status_t Camera3Device::getInputBufferProducer(
@@ -2161,7 +2171,7 @@
mNeedConfig = true;
}
-status_t Camera3Device::configureStreamsLocked() {
+status_t Camera3Device::configureStreamsLocked(int operatingMode) {
ATRACE_CALL();
status_t res;
@@ -2170,6 +2180,21 @@
return INVALID_OPERATION;
}
+ if (operatingMode < 0) {
+ CLOGE("Invalid operating mode: %d", operatingMode);
+ return BAD_VALUE;
+ }
+
+ bool isConstrainedHighSpeed =
+ static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
+ operatingMode;
+
+ if (mOperatingMode != operatingMode) {
+ mNeedConfig = true;
+ mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
+ mOperatingMode = operatingMode;
+ }
+
if (!mNeedConfig) {
ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
return OK;
@@ -2188,9 +2213,7 @@
ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
camera3_stream_configuration config;
- config.operation_mode = mIsConstrainedHighSpeedConfiguration ?
- CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE :
- CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
+ config.operation_mode = mOperatingMode;
config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
Vector<camera3_stream_t*> streams;
@@ -3149,8 +3172,12 @@
}
}
- requestedConfiguration.operationMode = mapToStreamConfigurationMode(
- (camera3_stream_configuration_mode_t) config->operation_mode);
+ res = mapToStreamConfigurationMode(
+ (camera3_stream_configuration_mode_t) config->operation_mode,
+ /*out*/ &requestedConfiguration.operationMode);
+ if (res != OK) {
+ return res;
+ }
// Invoke configureStreams
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e19b62e..998cc0b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -135,7 +135,9 @@
status_t deleteStream(int id) override;
status_t deleteReprocessStream(int id) override;
- status_t configureStreams(bool isConstraiedHighSpeed = false) override;
+ status_t configureStreams(int operatingMode =
+ static_cast<int>(hardware::camera::device::V3_2::StreamConfigurationMode::NORMAL_MODE))
+ override;
status_t getInputBufferProducer(
sp<IGraphicBufferProducer> *producer) override;
@@ -212,6 +214,11 @@
// Camera device ID
const String8 mId;
+ // Current stream configuration mode;
+ int mOperatingMode;
+ // Constant to use for no set operating mode
+ static const int NO_MODE = -1;
+
// Flag indicating is the current active stream configuration is constrained high speed.
bool mIsConstrainedHighSpeedConfiguration;
@@ -508,7 +515,7 @@
* Take the currently-defined set of streams and configure the HAL to use
* them. This is a long-running operation (may be several hundered ms).
*/
- status_t configureStreamsLocked();
+ status_t configureStreamsLocked(int operatingMode);
/**
* Cancel stream configuration that did not finish successfully.
@@ -574,8 +581,9 @@
static hardware::camera::device::V3_2::ConsumerUsageFlags mapToConsumerUsage(uint32_t usage);
static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
camera3_stream_rotation_t rotation);
- static hardware::camera::device::V3_2::StreamConfigurationMode mapToStreamConfigurationMode(
- camera3_stream_configuration_mode_t operationMode);
+ // Returns a negative error code if the passed-in operation mode is not valid.
+ static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
+ /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
static uint32_t mapConsumerToFrameworkUsage(
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index deb6735..bf6af86 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -32,6 +32,8 @@
#include <utils/Trace.h>
+#include <cutils/atomic.h>
+
#include "Camera3StreamSplitter.h"
namespace android {
diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm.policy b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
index a8f2ca9..890d777 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
@@ -59,3 +59,8 @@
connect: 1
fcntl64: 1
rt_tgsigqueueinfo: 1
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
+recvmsg: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
index 165694c..96840a0 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
@@ -43,5 +43,13 @@
tgkill: 1
socket: 1
connect: 1
+recvmsg: 1
fcntl64: 1
rt_tgsigqueueinfo: 1
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
+getdents64: 1
+pipe2: 1
+ppoll: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
index 7e7b858..c95ddb7 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
@@ -34,5 +34,13 @@
# socket: arg0 == AF_LOCAL
socket: arg0 == 1
connect: 1
+recvmsg: 1
rt_tgsigqueueinfo: 1
writev: 1
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
+getdents64: 1
+pipe2: 1
+ppoll: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
index 189855c..19016cd 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
@@ -44,3 +44,10 @@
rt_sigprocmask: 1
fcntl64: 1
rt_tgsigqueueinfo: 1
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
+getdents64: 1
+pipe2: 1
+ppoll: 1
diff --git a/services/medialog/IMediaLogService.cpp b/services/medialog/IMediaLogService.cpp
index bc445ff..0e9b01e 100644
--- a/services/medialog/IMediaLogService.cpp
+++ b/services/medialog/IMediaLogService.cpp
@@ -29,6 +29,7 @@
enum {
REGISTER_WRITER = IBinder::FIRST_CALL_TRANSACTION,
UNREGISTER_WRITER,
+ REQUEST_MERGE_WAKEUP,
};
class BpMediaLogService : public BpInterface<IMediaLogService>
@@ -57,6 +58,13 @@
// FIXME ignores status
}
+ virtual void requestMergeWakeup() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor());
+ status_t status __unused = remote()->transact(REQUEST_MERGE_WAKEUP, data, &reply);
+ // FIXME ignores status
+ }
+
};
IMPLEMENT_META_INTERFACE(MediaLogService, "android.media.IMediaLogService");
@@ -84,6 +92,12 @@
return NO_ERROR;
}
+ case REQUEST_MERGE_WAKEUP: {
+ CHECK_INTERFACE(IMediaLogService, data, reply);
+ requestMergeWakeup();
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 4c81436..aaf1018 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -27,6 +27,23 @@
namespace android {
// static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+MediaLogService::MediaLogService() :
+ BnMediaLogService(),
+ mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
+ mMerger(mMergerShared, kMergeBufferSize),
+ mMergeReader(mMergerShared, kMergeBufferSize, mMerger),
+ mMergeThread(new NBLog::MergeThread(mMerger))
+{
+ mMergeThread->run("MergeThread");
+}
+
+MediaLogService::~MediaLogService()
+{
+ mMergeThread->requestExit();
+ mMergeThread->setTimeoutUs(0);
+ mMergeThread->join();
+ free(mMergerShared);
+}
void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
{
@@ -111,8 +128,7 @@
mLock.unlock();
}
#endif
-
- mMerger.merge();
+ // FIXME request merge to make sure log is up to date
mMergeReader.dump(fd);
return NO_ERROR;
}
@@ -123,4 +139,8 @@
return BnMediaLogService::onTransact(code, data, reply, flags);
}
+void MediaLogService::requestMergeWakeup() {
+ mMergeThread->wakeup();
+}
+
} // namespace android
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index e934844..c6b99f1 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -27,13 +27,8 @@
{
friend class BinderService<MediaLogService>; // for MediaLogService()
public:
- MediaLogService() :
- BnMediaLogService(),
- mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
- mMerger(mMergerShared, kMergeBufferSize),
- mMergeReader(mMergerShared, kMergeBufferSize, mMerger)
- {ALOGI("Nico creating MergeReader");}
- virtual ~MediaLogService() { free(mMergerShared); }
+ MediaLogService();
+ virtual ~MediaLogService() override;
virtual void onFirstRef() { }
static const char* getServiceName() { return "media.log"; }
@@ -47,6 +42,8 @@
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags);
+ virtual void requestMergeWakeup() override;
+
private:
// Internal dump
@@ -58,10 +55,10 @@
Mutex mLock;
Vector<NBLog::NamedReader> mNamedReaders;
-
NBLog::Shared *mMergerShared;
NBLog::Merger mMerger;
NBLog::MergeReader mMergeReader;
+ const sp<NBLog::MergeThread> mMergeThread;
};
} // namespace android
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
index 916fcc4..0c68cf1 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ b/services/soundtrigger/SoundTriggerHalHidl.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
+#include <stdatomic.h>
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 78845b7..5b8d990 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -544,10 +544,11 @@
ALOGV("remove client %p", moduleClient.get());
mModuleClients.removeAt(index);
- for (size_t i = 0; i < mModels.size(); i++) {
- sp<Model> model = mModels.valueAt(i);
+ // 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);
+ mModels.removeItemsAt(i - 1);
ALOGV("detach() unloading model %d", model->mHandle);
if (mHalInterface != 0) {
if (model->mState == Model::STATE_ACTIVE) {