Merge "Camera3Device: fix dereferencing null pointer crash" into nyc-dev
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index fad57ba..c78fc5d 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -79,7 +79,7 @@
return mBuffer;
}
-status_t CameraMetadata::unlock(const camera_metadata_t *buffer) {
+status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
if (!mLocked) {
ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
return INVALID_OPERATION;
diff --git a/camera/ndk/Android.mk b/camera/ndk/Android.mk
index ebd473d..40dbeef 100644
--- a/camera/ndk/Android.mk
+++ b/camera/ndk/Android.mk
@@ -49,6 +49,7 @@
libcamera_client \
libstagefright_foundation \
libcutils \
+ libcamera_metadata
LOCAL_CLANG := true
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 18718d3..85fe75b 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -39,6 +39,18 @@
}
EXPORT
+camera_status_t ACameraMetadata_getAllTags(
+ const ACameraMetadata* acm, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) {
+ ATRACE_CALL();
+ if (acm == nullptr || numTags == nullptr || tags == nullptr) {
+ ALOGE("%s: invalid argument! metadata %p, numTags %p, tags %p",
+ __FUNCTION__, acm, numTags, tags);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return acm->getTags(numTags, tags);
+}
+
+EXPORT
ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src) {
ATRACE_CALL();
if (src == nullptr) {
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
index 4fee09c..77b9a33 100644
--- a/camera/ndk/NdkCaptureRequest.cpp
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -87,6 +87,18 @@
return req->settings->getConstEntry(tag, entry);
}
+EXPORT
+camera_status_t ACaptureRequest_getAllTags(
+ const ACaptureRequest* req, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) {
+ ATRACE_CALL();
+ if (req == nullptr || numTags == nullptr || tags == nullptr) {
+ ALOGE("%s: invalid argument! request %p, numTags %p, tags %p",
+ __FUNCTION__, req, numTags, tags);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return req->settings->getTags(numTags, tags);
+}
+
#define SET_ENTRY(NAME,NDK_TYPE) \
EXPORT \
camera_status_t ACaptureRequest_setEntry_##NAME( \
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 880befe..6bca692 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -76,8 +76,8 @@
mHandler = new CallbackHandler();
mCbLooper->registerHandler(mHandler);
- CameraMetadata metadata = mChars->mData;
- camera_metadata_entry entry = metadata.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
+ const CameraMetadata& metadata = mChars->getInternalData();
+ camera_metadata_ro_entry entry = metadata.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
if (entry.count != 1) {
ALOGW("%s: bad count %zu for partial result count", __FUNCTION__, entry.count);
mPartialResultCount = 1;
@@ -279,7 +279,7 @@
const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
camera_status_t ret;
sp<CaptureRequest> req(new CaptureRequest());
- req->mMetadata = request->settings->mData;
+ req->mMetadata = request->settings->getInternalData();
req->mIsReprocess = false; // NDK does not support reprocessing yet
for (auto outputTarget : request->targets->mOutputs) {
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index fbc8d19..8366ade 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -162,6 +162,8 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
}
+ Mutex::Autolock _l(mLock);
+
camera_metadata_ro_entry rawEntry = mData.find(tag);
if (rawEntry.count == 0) {
ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
@@ -204,6 +206,38 @@
return updateImpl<camera_metadata_rational_t>(tag, count, data);
}
+camera_status_t
+ACameraMetadata::getTags(/*out*/int32_t* numTags,
+ /*out*/const uint32_t** tags) const {
+ Mutex::Autolock _l(mLock);
+ if (mTags.size() == 0) {
+ size_t entry_count = mData.entryCount();
+ mTags.setCapacity(entry_count);
+ const camera_metadata_t* rawMetadata = mData.getAndLock();
+ for (size_t i = 0; i < entry_count; i++) {
+ camera_metadata_ro_entry_t entry;
+ int ret = get_camera_metadata_ro_entry(rawMetadata, i, &entry);
+ if (ret != 0) {
+ ALOGE("%s: error reading metadata index %zu", __FUNCTION__, i);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ // Hide system key from users
+ if (sSystemTags.count(entry.tag) == 0) {
+ mTags.push_back(entry.tag);
+ }
+ }
+ mData.unlock(rawMetadata);
+ }
+
+ *numTags = mTags.size();
+ *tags = mTags.array();
+ return ACAMERA_OK;
+}
+
+const CameraMetadata&
+ACameraMetadata::getInternalData() {
+ return mData;
+}
// TODO: some of key below should be hidden from user
// ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
@@ -286,6 +320,49 @@
}
}
+// System tags that should be hidden from users
+std::unordered_set<uint32_t> ACameraMetadata::sSystemTags ({
+ ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
+ ANDROID_CONTROL_AE_PRECAPTURE_ID,
+ ANDROID_CONTROL_AF_TRIGGER_ID,
+ ANDROID_DEMOSAIC_MODE,
+ ANDROID_EDGE_STRENGTH,
+ ANDROID_FLASH_FIRING_POWER,
+ ANDROID_FLASH_FIRING_TIME,
+ ANDROID_FLASH_COLOR_TEMPERATURE,
+ ANDROID_FLASH_MAX_ENERGY,
+ ANDROID_FLASH_INFO_CHARGE_DURATION,
+ ANDROID_JPEG_MAX_SIZE,
+ ANDROID_JPEG_SIZE,
+ ANDROID_NOISE_REDUCTION_STRENGTH,
+ ANDROID_QUIRKS_METERING_CROP_REGION,
+ ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO,
+ ANDROID_QUIRKS_USE_ZSL_FORMAT,
+ ANDROID_REQUEST_INPUT_STREAMS,
+ ANDROID_REQUEST_METADATA_MODE,
+ ANDROID_REQUEST_OUTPUT_STREAMS,
+ ANDROID_REQUEST_TYPE,
+ ANDROID_REQUEST_MAX_NUM_REPROCESS_STREAMS,
+ ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+ ANDROID_SCALER_AVAILABLE_RAW_SIZES,
+ ANDROID_SENSOR_BASE_GAIN_FACTOR,
+ ANDROID_SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS,
+ ANDROID_SENSOR_TEMPERATURE,
+ ANDROID_SENSOR_PROFILE_HUE_SAT_MAP,
+ ANDROID_SENSOR_PROFILE_TONE_CURVE,
+ ANDROID_SENSOR_OPAQUE_RAW_SIZE,
+ ANDROID_SHADING_STRENGTH,
+ ANDROID_STATISTICS_HISTOGRAM_MODE,
+ ANDROID_STATISTICS_SHARPNESS_MAP_MODE,
+ ANDROID_STATISTICS_HISTOGRAM,
+ ANDROID_STATISTICS_SHARPNESS_MAP,
+ ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT,
+ ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
+ ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
+ ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
+ ANDROID_DEPTH_MAX_DEPTH_SAMPLES,
+});
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index 442e1dd..ab651a1 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -16,8 +16,12 @@
#ifndef _ACAMERA_METADATA_H
#define _ACAMERA_METADATA_H
+#include <unordered_set>
+
#include <sys/types.h>
+#include <utils/Mutex.h>
#include <utils/RefBase.h>
+#include <utils/Vector.h>
#include <camera/CameraMetadata.h>
#include "NdkCameraMetadata.h"
@@ -51,12 +55,17 @@
camera_status_t update(uint32_t tag, uint32_t count, const int64_t* data);
camera_status_t update(uint32_t tag, uint32_t count, const ACameraMetadata_rational* data);
+ camera_status_t getTags(/*out*/int32_t* numTags,
+ /*out*/const uint32_t** tags) const;
+
bool isNdkSupportedCapability(const int32_t capability);
- inline bool isVendorTag(const uint32_t tag);
- bool isCaptureRequestTag(const uint32_t tag);
+ static inline bool isVendorTag(const uint32_t tag);
+ static bool isCaptureRequestTag(const uint32_t tag);
void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats
+ const CameraMetadata& getInternalData();
+
template<typename INTERNAL_T, typename NDK_T>
camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {
if (mType != ACM_REQUEST) {
@@ -68,18 +77,27 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
}
+ Mutex::Autolock _l(mLock);
+
// Here we have to use reinterpret_cast because the NDK data type is
// exact copy of internal data type but they do not inherit from each other
status_t ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
if (ret == OK) {
+ mTags.clear();
return ACAMERA_OK;
} else {
return ACAMERA_ERROR_INVALID_PARAMETER;
}
}
- CameraMetadata mData;
+ private:
+ // guard access of public APIs: get/update/getTags
+ mutable Mutex mLock;
+ CameraMetadata mData;
+ mutable Vector<uint32_t> mTags; // updated in getTags, cleared by update
const ACAMERA_METADATA_TYPE mType;
+
+ static std::unordered_set<uint32_t> sSystemTags;
};
#endif // _ACAMERA_METADATA_H
diff --git a/include/camera/CameraMetadata.h b/include/camera/CameraMetadata.h
index db400de..28f47a1 100644
--- a/include/camera/CameraMetadata.h
+++ b/include/camera/CameraMetadata.h
@@ -64,7 +64,7 @@
* from getAndLock must be provided to guarantee that the right object is
* being unlocked.
*/
- status_t unlock(const camera_metadata_t *buffer);
+ status_t unlock(const camera_metadata_t *buffer) const;
/**
* Release a raw metadata buffer to the caller. After this call,
diff --git a/include/camera/ndk/NdkCameraMetadata.h b/include/camera/ndk/NdkCameraMetadata.h
index 56412ad..9b56a9d 100644
--- a/include/camera/ndk/NdkCameraMetadata.h
+++ b/include/camera/ndk/NdkCameraMetadata.h
@@ -93,7 +93,13 @@
camera_status_t ACameraMetadata_getConstEntry(
const ACameraMetadata*, uint32_t tag, ACameraMetadata_const_entry* entry);
-// TODO: need an API to list all tags in the metadata. Same for ACaptureRequest
+/*
+ * List all the entry tags in this metadata.
+ * The memory of tags is managed by ACameraMetadata itself and must NOT be free/delete
+ * by application. Do NOT access tags after calling ACameraMetadata_free
+ */
+camera_status_t ACameraMetadata_getAllTags(
+ const ACameraMetadata*, /*out*/int32_t* numTags, /*out*/const uint32_t** tags);
/**
* Copy a metadata. Duplicates a metadata structure.
diff --git a/include/camera/ndk/NdkCaptureRequest.h b/include/camera/ndk/NdkCaptureRequest.h
index 566d78f..d9fb164 100644
--- a/include/camera/ndk/NdkCaptureRequest.h
+++ b/include/camera/ndk/NdkCaptureRequest.h
@@ -54,6 +54,19 @@
*/
camera_status_t ACaptureRequest_getConstEntry(
const ACaptureRequest*, uint32_t tag, ACameraMetadata_const_entry* entry);
+
+/*
+ * List all the entry tags in this capture request.
+ * The memory of tags is managed by ACaptureRequest itself and must NOT be free/delete
+ * by application. Calling ACaptureRequest_setEntry_* API will invalidate previous
+ * output of ACaptureRequest_getAllTags. Do not access tags after calling
+ * ACaptureRequest_setEntry_*. To get new list of tags after updating capture request,
+ * application must call ACaptureRequest_getAllTags again.
+ * Do NOT access tags after calling ACaptureRequest_free.
+ */
+camera_status_t ACaptureRequest_getAllTags(
+ const ACaptureRequest*, /*out*/int32_t* numTags, /*out*/const uint32_t** tags);
+
/*
* Set an entry of corresponding type.
* The entry tag's type must match corresponding set API or an
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 65f415a..564b3f7 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -24,8 +24,9 @@
#include <media/stagefright/foundation/AString.h>
#include <utils/Log.h>
-inline static const char *asString(android::status_t i, const char *def = "??") {
- using namespace android;
+namespace android {
+
+inline static const char *asString(status_t i, const char *def = "??") {
switch (i) {
case NO_ERROR: return "NO_ERROR";
case UNKNOWN_ERROR: return "UNKNOWN_ERROR";
@@ -49,8 +50,6 @@
}
}
-namespace android {
-
#define LITERAL_TO_STRING_INTERNAL(x) #x
#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index bdfddc7..5f9a1c0 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -286,6 +286,7 @@
}
if (queue->mPulling && err == OK) {
msg->post(); // if simply paused, keep pulling source
+ break;
} else if (err == ERROR_END_OF_STREAM) {
ALOGV("stream ended, mbuf %p", mbuf);
} else if (err != OK) {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index ed807c6..7f8ed1f 100755
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -142,6 +142,8 @@
{
const SwAudioOutputCollection &outputs = mPolicyEngine->mApmObserver->getOutputs();
+ //FIXME: getStrategyForUsage() should return STRATEGY_ACCESSIBILITY and getDeviceForStrategy()
+ // should be implemented accordingly for STRATEGY_ACCESSIBILITY
if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY &&
(outputs.isStreamActive(AUDIO_STREAM_RING) ||
outputs.isStreamActive(AUDIO_STREAM_ALARM))) {
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 43664e6..f8ba3f2 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -195,18 +195,9 @@
routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
{
- const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
-
// usage to strategy mapping
switch (usage) {
case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
- if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
- outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
- return STRATEGY_SONIFICATION;
- }
- if (isInCall()) {
- return STRATEGY_PHONE;
- }
return STRATEGY_ACCESSIBILITY;
case AUDIO_USAGE_MEDIA:
@@ -245,6 +236,17 @@
const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
+ return getDeviceForStrategyInt(strategy, (DeviceVector&)availableOutputDevices,
+ availableInputDevices, outputs);
+}
+
+
+
+audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy,
+ DeviceVector &availableOutputDevices,
+ const DeviceVector &availableInputDevices,
+ const SwAudioOutputCollection &outputs) const
+{
uint32_t device = AUDIO_DEVICE_NONE;
uint32_t availableOutputDevicesType = availableOutputDevices.types();
@@ -260,14 +262,16 @@
case STRATEGY_SONIFICATION_RESPECTFUL:
if (isInCall()) {
- device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+ device = getDeviceForStrategyInt(
+ STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
} else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
// while media is playing on a remote device, use the the sonification behavior.
// Note that we test this usecase before testing if media is playing because
// the isStreamActive() method only informs about the activity of a stream, not
// if it's for local playback. Note also that we use the same delay between both tests
- device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+ device = getDeviceForStrategyInt(
+ STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
//user "safe" speaker if available instead of normal speaker to avoid triggering
//other acoustic safety mechanisms for notification
if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
@@ -275,12 +279,15 @@
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
- } else if (outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
+ } else if (outputs.isStreamActive(
+ AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
// while media is playing (or has recently played), use the same device
- device = getDeviceForStrategy(STRATEGY_MEDIA);
+ device = getDeviceForStrategyInt(
+ STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
} else {
// when media is not playing anymore, fall back on the sonification behavior
- device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+ device = getDeviceForStrategyInt(
+ STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
//user "safe" speaker if available instead of normal speaker to avoid triggering
//other acoustic safety mechanisms for notification
if ((device & AUDIO_DEVICE_OUT_SPEAKER) &&
@@ -294,7 +301,8 @@
case STRATEGY_DTMF:
if (!isInCall()) {
// when off call, DTMF strategy follows the same rules as MEDIA strategy
- device = getDeviceForStrategy(STRATEGY_MEDIA);
+ device = getDeviceForStrategyInt(
+ STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
break;
}
// when in call, DTMF and PHONE strategies follow the same rules
@@ -321,8 +329,8 @@
availableOutputDevicesType = availPrimaryOutputDevices;
}
}
- // for phone strategy, we first consider the forced use and then the available devices by order
- // of priority
+ // for phone strategy, we first consider the forced use and then the available devices by
+ // order of priority
switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
case AUDIO_POLICY_FORCE_BT_SCO:
if (!isInCall() || strategy != STRATEGY_DTMF) {
@@ -350,6 +358,8 @@
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
+ if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
if (!isInCall()) {
@@ -391,8 +401,6 @@
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
}
- device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
- if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
if (device) break;
device = mApmObserver->getDefaultOutputDevice()->type();
@@ -408,7 +416,8 @@
// If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
// handleIncallSonification().
if (isInCall()) {
- device = getDeviceForStrategy(STRATEGY_PHONE);
+ device = getDeviceForStrategyInt(
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
break;
}
// FALL THROUGH
@@ -429,7 +438,6 @@
// The second device used for sonification is the same as the device used by media strategy
// FALL THROUGH
- // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
case STRATEGY_ACCESSIBILITY:
if (strategy == STRATEGY_ACCESSIBILITY) {
// do not route accessibility prompts to a digital output currently configured with a
@@ -443,20 +451,35 @@
availableOutputDevicesType = availableOutputDevices.types() & ~devices;
}
}
+ availableOutputDevices =
+ availableOutputDevices.getDevicesFromType(availableOutputDevicesType);
+ if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
+ outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
+ return getDeviceForStrategyInt(
+ STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
+ }
+ if (isInCall()) {
+ return getDeviceForStrategyInt(
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
+ }
}
+ // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
// FALL THROUGH
+ // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
case STRATEGY_REROUTING:
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD)
- if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
+ if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ String8("0")) != 0) {
device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
}
if (isInCall() && (strategy == STRATEGY_MEDIA)) {
- device = getDeviceForStrategy(STRATEGY_PHONE);
+ device = getDeviceForStrategyInt(
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
break;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 8b6eaf6..ed93d1c 100755
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -125,6 +125,10 @@
routing_strategy getStrategyForStream(audio_stream_type_t stream);
routing_strategy getStrategyForUsage(audio_usage_t usage);
audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
+ audio_devices_t getDeviceForStrategyInt(routing_strategy strategy,
+ DeviceVector &availableOutputDevices,
+ const DeviceVector &availableInputDevices,
+ const SwAudioOutputCollection &outputs) const;
audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
audio_mode_t mPhoneState; /**< current phone state. */
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a7b90f4..21107a1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1794,8 +1794,15 @@
{
ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
mVolumeCurves->initStreamVolume(stream, indexMin, indexMax);
- if (stream == AUDIO_STREAM_MUSIC) {
- mVolumeCurves->initStreamVolume(AUDIO_STREAM_ACCESSIBILITY, indexMin, indexMax);
+
+ // initialize other private stream volumes which follow this one
+ routing_strategy strategy = getStrategy(stream);
+ for (int curStream = 0; curStream < AUDIO_STREAM_CNT; curStream++) {
+ routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
+ if (!strategiesMatchForvolume(strategy, curStrategy)) {
+ continue;
+ }
+ mVolumeCurves->initStreamVolume((audio_stream_type_t)curStream, indexMin, indexMax);
}
}
@@ -1823,38 +1830,43 @@
if (device == AUDIO_DEVICE_OUT_DEFAULT) {
mVolumeCurves->clearCurrentVolumeIndex(stream);
}
- mVolumeCurves->addCurrentVolumeIndex(stream, device, index);
+
+ // update other private stream volumes which follow this one
+ routing_strategy strategy = getStrategy(stream);
+ for (int curStream = 0; curStream < AUDIO_STREAM_CNT; curStream++) {
+ routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
+ if (!strategiesMatchForvolume(strategy, curStrategy)) {
+ continue;
+ }
+ mVolumeCurves->addCurrentVolumeIndex((audio_stream_type_t)curStream, device, index);
+ }
// update volume on all outputs whose current device is also selected by the same
// strategy as the device specified by the caller
- audio_devices_t selectedDevices = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
- // it is possible that the requested device is not selected by the strategy (e.g an explicit
- // audio patch is active causing getDevicesForStream() to return this device. We must make
- // sure that the device passed is part of the devices considered when applying volume below.
- selectedDevices |= device;
-
- //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
- audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
- if (stream == AUDIO_STREAM_MUSIC) {
- mVolumeCurves->addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index);
- accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
- }
-
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device());
- if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & selectedDevices) != 0)) {
- status_t volStatus = checkAndSetVolume(stream, index, desc, curDevice);
- if (volStatus != NO_ERROR) {
- status = volStatus;
+ for (int curStream = 0; curStream < AUDIO_STREAM_CNT; curStream++) {
+ routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
+ if (!strategiesMatchForvolume(strategy, curStrategy)) {
+ continue;
}
- }
- if ((accessibilityDevice != AUDIO_DEVICE_NONE) &&
- ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)))
- {
- status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
- index, desc, curDevice);
+ audio_devices_t curStreamDevice = getDeviceForStrategy(curStrategy, true /*fromCache*/);
+ // it is possible that the requested device is not selected by the strategy
+ // (e.g an explicit audio patch is active causing getDevicesForStream()
+ // to return this device. We must make sure that the device passed is part of the
+ // devices considered when applying volume below.
+ curStreamDevice |= device;
+
+ if (((device == AUDIO_DEVICE_OUT_DEFAULT) ||
+ ((curDevice & curStreamDevice) != 0))) {
+ status_t volStatus =
+ checkAndSetVolume((audio_stream_type_t)curStream, index, desc, curDevice);
+ if (volStatus != NO_ERROR) {
+ status = volStatus;
+ }
+ }
}
}
return status;
@@ -1957,7 +1969,17 @@
bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
- return mOutputs.isStreamActive(stream, inPastMs);
+ bool active = false;
+ routing_strategy strategy = getStrategy(stream);
+ for (int curStream = 0; curStream < AUDIO_STREAM_CNT && !active; curStream++) {
+ routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
+ if (!strategiesMatchForvolume(strategy, curStrategy)) {
+ continue;
+ }
+ active = mOutputs.isStreamActive((audio_stream_type_t)curStream, inPastMs);
+ }
+
+ return active;
}
bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
@@ -2838,7 +2860,7 @@
disconnectAudioSource(sourceDesc);
routing_strategy strategy = (routing_strategy) getStrategyForAttr(&sourceDesc->mAttributes);
- audio_stream_type_t stream = audio_attributes_to_stream_type(&sourceDesc->mAttributes);
+ audio_stream_type_t stream = streamTypefromAttributesInt(&sourceDesc->mAttributes);
sp<DeviceDescriptor> srcDeviceDesc = sourceDesc->mDevice;
audio_devices_t sinkDevice = getDeviceForStrategy(strategy, true);
@@ -2971,7 +2993,7 @@
}
removeAudioPatch(sourceDesc->mPatchDesc->mHandle);
- audio_stream_type_t stream = audio_attributes_to_stream_type(&sourceDesc->mAttributes);
+ audio_stream_type_t stream = streamTypefromAttributesInt(&sourceDesc->mAttributes);
sp<SwAudioOutputDescriptor> swOutputDesc = sourceDesc->mSwOutput.promote();
if (swOutputDesc != 0) {
stopSource(swOutputDesc, stream, false);
@@ -4170,10 +4192,10 @@
// use device for strategy phone
// 3: the strategy for enforced audible is active but not enforced on the output:
// use the device for strategy enforced audible
- // 4: the strategy accessibility is active on the output:
- // use device for strategy accessibility
- // 5: the strategy sonification is active on the output:
+ // 4: the strategy sonification is active on the output:
// use device for strategy sonification
+ // 5: the strategy accessibility is active on the output:
+ // use device for strategy accessibility
// 6: the strategy "respectful" sonification is active on the output:
// use device for strategy "respectful" sonification
// 7: the strategy media is active on the output:
@@ -4190,10 +4212,10 @@
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
- } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
- device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
+ } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
+ device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_MEDIA)) {
@@ -4229,6 +4251,13 @@
return device;
}
+bool AudioPolicyManager::strategiesMatchForvolume(routing_strategy strategy1,
+ routing_strategy strategy2) {
+ return ((strategy1 == strategy2) ||
+ ((strategy1 == STRATEGY_ACCESSIBILITY) && (strategy2 == STRATEGY_MEDIA)) ||
+ ((strategy1 == STRATEGY_MEDIA) && (strategy2 == STRATEGY_ACCESSIBILITY)));
+}
+
uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) {
return (uint32_t)getStrategy(stream);
}
@@ -4240,16 +4269,22 @@
if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_DEVICE_NONE;
}
- audio_devices_t devices;
+ audio_devices_t devices = AUDIO_DEVICE_NONE;
routing_strategy strategy = getStrategy(stream);
- devices = getDeviceForStrategy(strategy, true /*fromCache*/);
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs);
- for (size_t i = 0; i < outputs.size(); i++) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
- if (isStrategyActive(outputDesc, strategy)) {
- devices = outputDesc->device();
- break;
+ for (int curStrategy = 0; curStrategy < NUM_STRATEGIES; curStrategy++) {
+ if (!strategiesMatchForvolume(strategy, (routing_strategy)curStrategy)) {
+ continue;
}
+ audio_devices_t curDevices =
+ getDeviceForStrategy((routing_strategy)curStrategy, true /*fromCache*/);
+ SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(curDevices, mOutputs);
+ for (size_t i = 0; i < outputs.size(); i++) {
+ sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
+ if (isStrategyActive(outputDesc, (routing_strategy)curStrategy)) {
+ curDevices |= outputDesc->device();
+ }
+ }
+ devices |= curDevices;
}
/*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
@@ -4361,15 +4396,8 @@
// the device = the device from the descriptor in the RouteMap, and exit.
for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
- routing_strategy strat = getStrategy(route->mStreamType);
- // Special case for accessibility strategy which must follow any strategy it is
- // currently remapped to
- bool strategyMatch = (strat == strategy) ||
- ((strategy == STRATEGY_ACCESSIBILITY) &&
- ((mEngine->getStrategyForUsage(
- AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY) == strat) ||
- (strat == STRATEGY_MEDIA)));
- if (strategyMatch && route->isActive()) {
+ routing_strategy routeStrategy = getStrategy(route->mStreamType);
+ if ((routeStrategy == strategy) && route->isActive()) {
return route->mDeviceDescriptor->type();
}
}
@@ -5007,15 +5035,6 @@
case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
return AUDIO_STREAM_MUSIC;
case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
- if (isStreamActive(AUDIO_STREAM_ALARM)) {
- return AUDIO_STREAM_ALARM;
- }
- if (isStreamActive(AUDIO_STREAM_RING)) {
- return AUDIO_STREAM_RING;
- }
- if (isInCall()) {
- return AUDIO_STREAM_VOICE_CALL;
- }
return AUDIO_STREAM_ACCESSIBILITY;
case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
return AUDIO_STREAM_SYSTEM;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 38700fc..d6e48ab 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -506,6 +506,9 @@
void clearAudioSources(uid_t uid);
+ static bool strategiesMatchForvolume(routing_strategy strategy1,
+ routing_strategy strategy2);
+
uid_t mUidCached;
AudioPolicyClientInterface *mpClientInterface; // audio policy client interface
sp<SwAudioOutputDescriptor> mPrimaryOutput; // primary output descriptor
diff --git a/services/mediacodec/minijail/seccomp_policy/mediacodec-seccomp-arm.policy b/services/mediacodec/minijail/seccomp_policy/mediacodec-seccomp-arm.policy
index 75fb9c8..4be96d5 100644
--- a/services/mediacodec/minijail/seccomp_policy/mediacodec-seccomp-arm.policy
+++ b/services/mediacodec/minijail/seccomp_policy/mediacodec-seccomp-arm.policy
@@ -39,6 +39,7 @@
sched_get_priority_min: 1
statfs64: 1
sched_setscheduler: 1
+fstatat64: 1
# for attaching to debuggerd on process crash
sigaction: 1