Merge "Extract out test utility functions from resampler_tests"
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 22199fa..85f44f0 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -77,6 +77,32 @@
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
+status_t Camera::connectLegacy(int cameraId, int halVersion,
+ const String16& clientPackageName,
+ int clientUid,
+ sp<Camera>& camera)
+{
+ ALOGV("%s: connect legacy camera device", __FUNCTION__);
+ sp<Camera> c = new Camera(cameraId);
+ sp<ICameraClient> cl = c;
+ status_t status = NO_ERROR;
+ const sp<ICameraService>& cs = CameraBaseT::getCameraService();
+
+ if (cs != 0) {
+ status = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
+ clientUid, /*out*/c->mCamera);
+ }
+ if (status == OK && c->mCamera != 0) {
+ c->mCamera->asBinder()->linkToDeath(c);
+ c->mStatus = NO_ERROR;
+ camera = c;
+ } else {
+ ALOGW("An error occurred while connecting to camera: %d", cameraId);
+ c.clear();
+ }
+ return status;
+}
+
status_t Camera::reconnect()
{
ALOGV("reconnect");
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index b86651f..5485205 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "BpCameraService"
#include <utils/Log.h>
#include <utils/Errors.h>
+#include <utils/String16.h>
#include <stdint.h>
#include <sys/types.h>
@@ -185,6 +186,29 @@
return status;
}
+ // connect to camera service (android.hardware.Camera)
+ virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient, int cameraId,
+ int halVersion,
+ const String16 &clientPackageName, int clientUid,
+ /*out*/sp<ICamera>& device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+ data.writeStrongBinder(cameraClient->asBinder());
+ data.writeInt32(cameraId);
+ data.writeInt32(halVersion);
+ data.writeString16(clientPackageName);
+ data.writeInt32(clientUid);
+ remote()->transact(BnCameraService::CONNECT_LEGACY, data, &reply);
+
+ if (readExceptionCode(reply)) return -EPROTO;
+ status_t status = reply.readInt32();
+ if (reply.readInt32() != 0) {
+ device = interface_cast<ICamera>(reply.readStrongBinder());
+ }
+ return status;
+ }
+
// connect to camera service (pro client)
virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb, int cameraId,
const String16 &clientPackageName, int clientUid,
@@ -253,6 +277,41 @@
if (readExceptionCode(reply)) return -EPROTO;
return reply.readInt32();
}
+
+ virtual status_t getLegacyParameters(int cameraId, String16* parameters) {
+ if (parameters == NULL) {
+ ALOGE("%s: parameters must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Parcel data, reply;
+
+ data.writeInt32(cameraId);
+ remote()->transact(BnCameraService::GET_LEGACY_PARAMETERS, data, &reply);
+ if (readExceptionCode(reply)) return -EPROTO;
+
+ status_t res = data.readInt32();
+ int32_t length = data.readInt32(); // -1 means null
+ if (length > 0) {
+ *parameters = data.readString16();
+ } else {
+ *parameters = String16();
+ }
+
+ return res;
+ }
+
+ virtual status_t supportsCameraApi(int cameraId, int apiVersion) {
+ Parcel data, reply;
+
+ data.writeInt32(cameraId);
+ data.writeInt32(apiVersion);
+ remote()->transact(BnCameraService::SUPPORTS_CAMERA_API, data, &reply);
+ if (readExceptionCode(reply)) return -EPROTO;
+
+ status_t res = data.readInt32();
+ return res;
+ }
};
IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
@@ -387,6 +446,50 @@
reply->writeInt32(removeListener(listener));
return NO_ERROR;
} break;
+ case GET_LEGACY_PARAMETERS: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ int cameraId = data.readInt32();
+ String16 parameters;
+
+ reply->writeNoException();
+ // return value
+ reply->writeInt32(getLegacyParameters(cameraId, ¶meters));
+ // out parameters
+ reply->writeInt32(1); // parameters is always available
+ reply->writeString16(parameters);
+ return NO_ERROR;
+ } break;
+ case SUPPORTS_CAMERA_API: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ int cameraId = data.readInt32();
+ int apiVersion = data.readInt32();
+
+ reply->writeNoException();
+ // return value
+ reply->writeInt32(supportsCameraApi(cameraId, apiVersion));
+ return NO_ERROR;
+ } break;
+ case CONNECT_LEGACY: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ sp<ICameraClient> cameraClient =
+ interface_cast<ICameraClient>(data.readStrongBinder());
+ int32_t cameraId = data.readInt32();
+ int32_t halVersion = data.readInt32();
+ const String16 clientName = data.readString16();
+ int32_t clientUid = data.readInt32();
+ sp<ICamera> camera;
+ status_t status = connectLegacy(cameraClient, cameraId, halVersion,
+ clientName, clientUid, /*out*/camera);
+ reply->writeNoException();
+ reply->writeInt32(status);
+ if (camera != NULL) {
+ reply->writeInt32(1);
+ reply->writeStrongBinder(camera->asBinder());
+ } else {
+ reply->writeInt32(0);
+ }
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index c2a8f1b..af84069 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
#define LOG_TAG "ScreenRecord"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -27,9 +31,6 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
-#include <stdlib.h>
-#include <assert.h>
-
#include "screenrecord.h"
#include "Overlay.h"
#include "TextRenderer.h"
@@ -235,7 +236,7 @@
char textBuf[64];
getTimeString_l(monotonicNsec, textBuf, sizeof(textBuf));
- String8 timeStr(String8::format("%s f=%lld (%zd)",
+ String8 timeStr(String8::format("%s f=%" PRId64 " (%zd)",
textBuf, frameNumber, mTotalDroppedFrames));
mTextRenderer.drawString(mTexProgram, Program::kIdentity, 0, 0, timeStr);
diff --git a/cmds/screenrecord/TextRenderer.cpp b/cmds/screenrecord/TextRenderer.cpp
index 784055c..6a9176b 100644
--- a/cmds/screenrecord/TextRenderer.cpp
+++ b/cmds/screenrecord/TextRenderer.cpp
@@ -353,6 +353,6 @@
}
}
- ALOGV("goodPos=%d for str='%s'", goodPos, str);
+ ALOGV("goodPos=%zu for str='%s'", goodPos, str);
return const_cast<char*>(str + goodPos);
}
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 02ed53a..02df1d2 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -14,6 +14,19 @@
* limitations under the License.
*/
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <unistd.h>
+
#define LOG_TAG "ScreenRecord"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
@@ -36,18 +49,6 @@
#include <media/stagefright/MediaMuxer.h>
#include <media/ICrypto.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <getopt.h>
-#include <sys/wait.h>
-#include <termios.h>
-#include <assert.h>
-
#include "screenrecord.h"
#include "Overlay.h"
#include "FrameOutput.h"
@@ -354,7 +355,7 @@
case NO_ERROR:
// got a buffer
if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) != 0) {
- ALOGV("Got codec config buffer (%u bytes)", size);
+ ALOGV("Got codec config buffer (%zu bytes)", size);
if (muxer != NULL) {
// ignore this -- we passed the CSD into MediaMuxer when
// we got the format change notification
@@ -362,7 +363,7 @@
}
}
if (size != 0) {
- ALOGV("Got data in buffer %d, size=%d, pts=%lld",
+ ALOGV("Got data in buffer %zu, size=%zu, pts=%" PRId64,
bufIndex, size, ptsUsec);
{ // scope
@@ -473,7 +474,7 @@
ALOGV("Encoder stopping (req=%d)", gStopRequested);
if (gVerbose) {
- printf("Encoder stopping; recorded %u frames in %lld seconds\n",
+ printf("Encoder stopping; recorded %u frames in %" PRId64 " seconds\n",
debugNumFrames, nanoseconds_to_seconds(
systemTime(CLOCK_MONOTONIC) - startWhenNsec));
}
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 79682b8..2b60842 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -74,6 +74,10 @@
const String16& clientPackageName,
int clientUid);
+ static status_t connectLegacy(int cameraId, int halVersion,
+ const String16& clientPackageName,
+ int clientUid, sp<Camera>& camera);
+
virtual ~Camera();
status_t reconnect();
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 6e48f22..f7f06bb 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -32,6 +32,7 @@
class ICameraDeviceCallbacks;
class CameraMetadata;
class VendorTagDescriptor;
+class String16;
class ICameraService : public IInterface
{
@@ -49,12 +50,24 @@
REMOVE_LISTENER,
GET_CAMERA_CHARACTERISTICS,
GET_CAMERA_VENDOR_TAG_DESCRIPTOR,
+ GET_LEGACY_PARAMETERS,
+ SUPPORTS_CAMERA_API,
+ CONNECT_LEGACY,
};
enum {
USE_CALLING_UID = -1
};
+ enum {
+ API_VERSION_1 = 1,
+ API_VERSION_2 = 2,
+ };
+
+ enum {
+ CAMERA_HAL_API_VERSION_UNSPECIFIED = -1
+ };
+
public:
DECLARE_META_INTERFACE(CameraService);
@@ -105,6 +118,30 @@
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device) = 0;
+
+ virtual status_t getLegacyParameters(
+ int cameraId,
+ /*out*/
+ String16* parameters) = 0;
+
+ /**
+ * Returns OK if device supports camera2 api,
+ * returns -EOPNOTSUPP if it doesn't.
+ */
+ virtual status_t supportsCameraApi(
+ int cameraId, int apiVersion) = 0;
+
+ /**
+ * Connect the device as a legacy device for a given HAL version.
+ * For halVersion, use CAMERA_API_DEVICE_VERSION_* for a particular
+ * version, or CAMERA_HAL_API_VERSION_UNSPECIFIED for a service-selected version.
+ */
+ virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient,
+ int cameraId, int halVersion,
+ const String16& clientPackageName,
+ int clientUid,
+ /*out*/
+ sp<ICamera>& device) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index a4722cb..c89ceaa 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -99,6 +99,8 @@
// to be non-zero if status == NO_ERROR
static status_t getOutputSamplingRate(uint32_t* samplingRate,
audio_stream_type_t stream);
+ static status_t getOutputSamplingRateForAttr(uint32_t* samplingRate,
+ const audio_attributes_t *attr);
static status_t getOutputFrameCount(size_t* frameCount,
audio_stream_type_t stream);
static status_t getOutputLatency(uint32_t* latency,
@@ -212,7 +214,12 @@
audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL);
-
+ static audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+ const audio_offload_info_t *offloadInfo = NULL);
static status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session);
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 79db323..3492520 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -253,7 +253,8 @@
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
int uid = -1,
- pid_t pid = -1);
+ pid_t pid = -1,
+ audio_attributes_t* pAttributes = NULL);
/* Result of constructing the AudioTrack. This must be checked for successful initialization
* before using any AudioTrack API (except for set()), because using
@@ -586,6 +587,11 @@
AudioTrack(const AudioTrack& other);
AudioTrack& operator = (const AudioTrack& other);
+ void setAttributesFromStreamType(audio_stream_type_t streamType);
+ void setStreamTypeFromAttributes(audio_attributes_t& aa);
+ /* paa is guaranteed non-NULL */
+ bool isValidAttributes(const audio_attributes_t *paa);
+
/* a small internal class to handle the callback */
class AudioTrackThread : public Thread
{
@@ -626,6 +632,8 @@
nsecs_t processAudioBuffer();
bool isOffloaded() const;
+ bool isDirect() const;
+ bool isOffloadedOrDirect() const;
// caller must hold lock on mLock for all _l methods
@@ -642,6 +650,13 @@
bool isOffloaded_l() const
{ return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; }
+ bool isOffloadedOrDirect_l() const
+ { return (mFlags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|
+ AUDIO_OUTPUT_FLAG_DIRECT)) != 0; }
+
+ bool isDirect_l() const
+ { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
+
// Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
@@ -667,6 +682,7 @@
transfer_type mTransfer;
audio_offload_info_t mOffloadInfoCopy;
const audio_offload_info_t* mOffloadInfo;
+ audio_attributes_t mAttributes;
// mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data. For 8-bit PCM data, it's
// twice as large as mFrameSize because data is expanded to 16-bit before it's stored in buffer.
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index c742810..fc8be20 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -50,6 +50,7 @@
TRACK_TIMED = 1, // client requests a TimedAudioTrack
TRACK_FAST = 2, // client requests a fast AudioTrack or AudioRecord
TRACK_OFFLOAD = 4, // client requests offload to hw codec
+ TRACK_DIRECT = 8, // client requests a direct output
};
typedef uint32_t track_flags_t;
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index d422aa3..959e4c3 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -56,6 +56,12 @@
audio_channel_mask_t channelMask = 0,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL) = 0;
+ virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ audio_channel_mask_t channelMask = 0,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+ const audio_offload_info_t *offloadInfo = NULL) = 0;
virtual status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session = 0) = 0;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 50b444a..f865d38 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -18,7 +18,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "AudioRecord"
+#include <inttypes.h>
#include <sys/resource.h>
+
#include <binder/IPCThreadState.h>
#include <media/AudioRecord.h>
#include <utils/Log.h>
@@ -468,7 +470,7 @@
if (frameCount == 0) {
frameCount = minFrameCount;
} else if (frameCount < minFrameCount) {
- ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount);
+ ALOGE("frameCount %zu < minFrameCount %zu", frameCount, minFrameCount);
return BAD_VALUE;
}
@@ -555,17 +557,17 @@
mCblk = cblk;
// note that temp is the (possibly revised) value of frameCount
if (temp < frameCount || (frameCount == 0 && temp == 0)) {
- ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
+ ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
}
frameCount = temp;
mAwaitBoost = false;
if (mFlags & AUDIO_INPUT_FLAG_FAST) {
if (trackFlags & IAudioFlinger::TRACK_FAST) {
- ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %u", frameCount);
+ ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
mAwaitBoost = true;
} else {
- ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
+ ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
// once denied, do not request again if IAudioRecord is re-created
mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
}
@@ -740,7 +742,7 @@
if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
// sanity-check. user is most-likely passing an error code, and it would
// make the return value ambiguous (actualSize vs error).
- ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", buffer, userSize, userSize);
+ ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize);
return BAD_VALUE;
}
@@ -921,10 +923,10 @@
size_t nonContig;
status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
- "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount);
+ "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount);
requested = &ClientProxy::kNonBlocking;
size_t avail = audioBuffer.frameCount + nonContig;
- ALOGV("obtainBuffer(%u) returned %u = %u + %u err %d",
+ ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d",
mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
if (err != NO_ERROR) {
if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
@@ -952,8 +954,8 @@
// Sanity check on returned size
if (ssize_t(readSize) < 0 || readSize > reqSize) {
- ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes",
- reqSize, (int) readSize);
+ ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
+ reqSize, ssize_t(readSize));
return NS_NEVER;
}
@@ -1092,7 +1094,7 @@
ns = 1000000000LL;
// fall through
default:
- LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns);
+ LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
pauseInternal(ns);
return true;
}
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 15b32ff..a47d45c 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -245,6 +245,19 @@
return getSamplingRate(output, samplingRate);
}
+status_t AudioSystem::getOutputSamplingRateForAttr(uint32_t* samplingRate,
+ const audio_attributes_t *attr)
+{
+ if (attr == NULL) {
+ return BAD_VALUE;
+ }
+ audio_io_handle_t output = getOutputForAttr(attr);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+ return getSamplingRate(output, samplingRate);
+}
+
status_t AudioSystem::getSamplingRate(audio_io_handle_t output,
uint32_t* samplingRate)
{
@@ -310,7 +323,7 @@
return BAD_VALUE;
}
- ALOGV("getFrameCount() output %d, frameCount %d", output, *frameCount);
+ ALOGV("getFrameCount() output %d, frameCount %zu", output, *frameCount);
return NO_ERROR;
}
@@ -476,7 +489,7 @@
OutputDescriptor *outputDesc = new OutputDescriptor(*desc);
gOutputs.add(ioHandle, outputDesc);
- ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x frameCount %u "
+ ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x frameCount %zu "
"latency %d",
outputDesc->samplingRate, outputDesc->format, outputDesc->channelMask,
outputDesc->frameCount, outputDesc->latency);
@@ -501,7 +514,7 @@
desc = (const OutputDescriptor *)param2;
ALOGV("ioConfigChanged() new config for output %d samplingRate %u, format %#x channel mask %#x "
- "frameCount %d latency %d",
+ "frameCount %zu latency %d",
ioHandle, desc->samplingRate, desc->format,
desc->channelMask, desc->frameCount, desc->latency);
OutputDescriptor *outputDesc = gOutputs.valueAt(index);
@@ -633,6 +646,19 @@
return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
}
+audio_io_handle_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo)
+{
+ if (attr == NULL) return 0;
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return 0;
+ return aps->getOutputForAttr(attr, samplingRate, format, channelMask, flags, offloadInfo);
+}
+
status_t AudioSystem::startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session)
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e6827ee..898d58d 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -15,12 +15,13 @@
** limitations under the License.
*/
-
//#define LOG_NDEBUG 0
#define LOG_TAG "AudioTrack"
+#include <inttypes.h>
#include <math.h>
#include <sys/resource.h>
+
#include <audio_utils/primitives.h>
#include <binder/IPCThreadState.h>
#include <media/AudioTrack.h>
@@ -89,7 +90,7 @@
streamType, sampleRate);
return BAD_VALUE;
}
- ALOGV("getMinFrameCount=%d: afFrameCount=%d, minBufCount=%d, afSampleRate=%d, afLatency=%d",
+ ALOGV("getMinFrameCount=%zu: afFrameCount=%zu, minBufCount=%d, afSampleRate=%d, afLatency=%d",
*frameCount, afFrameCount, minBufCount, afSampleRate, afLatency);
return NO_ERROR;
}
@@ -103,6 +104,10 @@
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0)
{
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
+ mAttributes.usage = AUDIO_USAGE_UNKNOWN;
+ mAttributes.flags = 0x0;
+ strcpy(mAttributes.tags, "");
}
AudioTrack::AudioTrack(
@@ -129,7 +134,7 @@
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
- offloadInfo, uid, pid);
+ offloadInfo, uid, pid, NULL /*no audio attributes*/);
}
AudioTrack::AudioTrack(
@@ -156,7 +161,7 @@
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
- uid, pid);
+ uid, pid, NULL /*no audio attributes*/);
}
AudioTrack::~AudioTrack()
@@ -199,7 +204,8 @@
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
int uid,
- pid_t pid)
+ pid_t pid,
+ audio_attributes_t* pAttributes)
{
ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"flags #%x, notificationFrames %u, sessionId %d, transferType %d",
@@ -245,7 +251,7 @@
ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
sharedBuffer->size());
- ALOGV("set() streamType %d frameCount %u flags %04x", streamType, frameCount, flags);
+ ALOGV("set() streamType %d frameCount %zu flags %04x", streamType, frameCount, flags);
AutoMutex lock(mLock);
@@ -259,18 +265,33 @@
if (streamType == AUDIO_STREAM_DEFAULT) {
streamType = AUDIO_STREAM_MUSIC;
}
- if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
- ALOGE("Invalid stream type %d", streamType);
- return BAD_VALUE;
+
+ if (pAttributes == NULL) {
+ if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
+ ALOGE("Invalid stream type %d", streamType);
+ return BAD_VALUE;
+ }
+ setAttributesFromStreamType(streamType);
+ mStreamType = streamType;
+ } else {
+ if (!isValidAttributes(pAttributes)) {
+ ALOGE("Invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
+ pAttributes->usage, pAttributes->content_type, pAttributes->flags,
+ pAttributes->tags);
+ }
+ // stream type shouldn't be looked at, this track has audio attributes
+ memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
+ setStreamTypeFromAttributes(mAttributes);
+ ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]",
+ mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
}
- mStreamType = streamType;
status_t status;
if (sampleRate == 0) {
- status = AudioSystem::getOutputSamplingRate(&sampleRate, streamType);
+ status = AudioSystem::getOutputSamplingRateForAttr(&sampleRate, &mAttributes);
if (status != NO_ERROR) {
ALOGE("Could not get output sample rate for stream type %d; status %d",
- streamType, status);
+ mStreamType, status);
return status;
}
}
@@ -314,7 +335,7 @@
((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
}
// only allow deep buffering for music stream type
- if (streamType != AUDIO_STREAM_MUSIC) {
+ if (mStreamType != AUDIO_STREAM_MUSIC) {
flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
}
@@ -615,12 +636,12 @@
status_t AudioTrack::setSampleRate(uint32_t rate)
{
- if (mIsTimed || isOffloaded()) {
+ if (mIsTimed || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
uint32_t afSamplingRate;
- if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
+ if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) {
return NO_INIT;
}
// Resampler implementation limits input sampling rate to 2 x output sampling rate.
@@ -646,7 +667,7 @@
// sample rate can be updated during playback by the offloaded decoder so we need to
// query the HAL and update if needed.
// FIXME use Proxy return channel to update the rate from server and avoid polling here
- if (isOffloaded_l()) {
+ if (isOffloadedOrDirect_l()) {
if (mOutput != AUDIO_IO_HANDLE_NONE) {
uint32_t sampleRate = 0;
status_t status = AudioSystem::getSamplingRate(mOutput, &sampleRate);
@@ -660,7 +681,7 @@
status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
{
- if (mSharedBuffer == 0 || mIsTimed || isOffloaded()) {
+ if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
@@ -694,7 +715,7 @@
status_t AudioTrack::setMarkerPosition(uint32_t marker)
{
// The only purpose of setting marker position is to get a callback
- if (mCbf == NULL || isOffloaded()) {
+ if (mCbf == NULL || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
@@ -707,7 +728,7 @@
status_t AudioTrack::getMarkerPosition(uint32_t *marker) const
{
- if (isOffloaded()) {
+ if (isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
if (marker == NULL) {
@@ -723,7 +744,7 @@
status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod)
{
// The only purpose of setting position update period is to get a callback
- if (mCbf == NULL || isOffloaded()) {
+ if (mCbf == NULL || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
@@ -736,7 +757,7 @@
status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const
{
- if (isOffloaded()) {
+ if (isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
if (updatePeriod == NULL) {
@@ -751,7 +772,7 @@
status_t AudioTrack::setPosition(uint32_t position)
{
- if (mSharedBuffer == 0 || mIsTimed || isOffloaded()) {
+ if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
if (position > mFrameCount) {
@@ -784,10 +805,10 @@
}
AutoMutex lock(mLock);
- if (isOffloaded_l()) {
+ if (isOffloadedOrDirect_l()) {
uint32_t dspFrames = 0;
- if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) {
+ if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) {
ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition);
*position = mPausedPosition;
return NO_ERROR;
@@ -822,7 +843,7 @@
status_t AudioTrack::reload()
{
- if (mSharedBuffer == 0 || mIsTimed || isOffloaded()) {
+ if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) {
return INVALID_OPERATION;
}
@@ -867,12 +888,12 @@
return NO_INIT;
}
- audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat,
+ audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat,
mChannelMask, mFlags, mOffloadInfo);
if (output == AUDIO_IO_HANDLE_NONE) {
- ALOGE("Could not get audio output for stream type %d, sample rate %u, format %#x, "
- "channel mask %#x, flags %#x",
- mStreamType, mSampleRate, mFormat, mChannelMask, mFlags);
+ ALOGE("Could not get audio output for stream type %d, usage %d, sample rate %u, format %#x,"
+ " channel mask %#x, flags %#x",
+ mStreamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
return BAD_VALUE;
}
{
@@ -973,14 +994,14 @@
// Ensure that buffer depth covers at least audio hardware latency
uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
- ALOGV("afFrameCount=%d, minBufCount=%d, afSampleRate=%u, afLatency=%d",
+ ALOGV("afFrameCount=%zu, minBufCount=%d, afSampleRate=%u, afLatency=%d",
afFrameCount, minBufCount, afSampleRate, afLatency);
if (minBufCount <= nBuffering) {
minBufCount = nBuffering;
}
size_t minFrameCount = (afFrameCount*mSampleRate*minBufCount)/afSampleRate;
- ALOGV("minFrameCount: %u, afFrameCount=%d, minBufCount=%d, sampleRate=%u, afSampleRate=%u"
+ ALOGV("minFrameCount: %zu, afFrameCount=%zu, minBufCount=%d, sampleRate=%u, afSampleRate=%u"
", afLatency=%d",
minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency);
@@ -988,7 +1009,7 @@
frameCount = minFrameCount;
} else if (frameCount < minFrameCount) {
// not ALOGW because it happens all the time when playing key clicks over A2DP
- ALOGV("Minimum buffer size corrected from %d to %d",
+ ALOGV("Minimum buffer size corrected from %zu to %zu",
frameCount, minFrameCount);
frameCount = minFrameCount;
}
@@ -1018,6 +1039,10 @@
trackFlags |= IAudioFlinger::TRACK_OFFLOAD;
}
+ if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ trackFlags |= IAudioFlinger::TRACK_DIRECT;
+ }
+
size_t temp = frameCount; // temp may be replaced by a revised value of frameCount,
// but we will still need the original value also
sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType,
@@ -1071,14 +1096,14 @@
// In current design, AudioTrack client checks and ensures frame count validity before
// passing it to AudioFlinger so AudioFlinger should not return a different value except
// for fast track as it uses a special method of assigning frame count.
- ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
+ ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
}
frameCount = temp;
mAwaitBoost = false;
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
if (trackFlags & IAudioFlinger::TRACK_FAST) {
- ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount);
+ ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu", frameCount);
mAwaitBoost = true;
if (mSharedBuffer == 0) {
// Theoretically double-buffering is not required for fast tracks,
@@ -1089,7 +1114,7 @@
}
}
} else {
- ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
+ ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
// once denied, do not request again if IAudioTrack is re-created
mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
if (mSharedBuffer == 0) {
@@ -1109,6 +1134,16 @@
//return NO_INIT;
}
}
+ if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ if (trackFlags & IAudioFlinger::TRACK_DIRECT) {
+ ALOGV("AUDIO_OUTPUT_FLAG_DIRECT successful");
+ } else {
+ ALOGW("AUDIO_OUTPUT_FLAG_DIRECT denied by server");
+ mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+ // FIXME This is a warning, not an error, so don't return error status
+ //return NO_INIT;
+ }
+ }
// We retain a copy of the I/O handle, but don't own the reference
mOutput = output;
@@ -1304,6 +1339,16 @@
return INVALID_OPERATION;
}
+ if (isDirect()) {
+ AutoMutex lock(mLock);
+ int32_t flags = android_atomic_and(
+ ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END),
+ &mCblk->mFlags);
+ if (flags & CBLK_INVALID) {
+ return DEAD_OBJECT;
+ }
+ }
+
if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
// Sanity-check: user is most-likely passing an error code, and it would
// make the return value ambiguous (actualSize vs error).
@@ -1452,7 +1497,7 @@
// for offloaded tracks restoreTrack_l() will just update the sequence and clear
// AudioSystem cache. We should not exit here but after calling the callback so
// that the upper layers can recreate the track
- if (!isOffloaded_l() || (mSequence == mObservedSequence)) {
+ if (!isOffloadedOrDirect_l() || (mSequence == mObservedSequence)) {
status_t status = restoreTrack_l("processAudioBuffer");
mLock.unlock();
// Run again immediately, but with a new IAudioTrack
@@ -1578,7 +1623,7 @@
mObservedSequence = sequence;
mCbf(EVENT_NEW_IAUDIOTRACK, mUserData, NULL);
// for offloaded tracks, just wait for the upper layers to recreate the track
- if (isOffloaded()) {
+ if (isOffloadedOrDirect()) {
return NS_INACTIVE;
}
}
@@ -1636,10 +1681,10 @@
size_t nonContig;
status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
- "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount);
+ "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount);
requested = &ClientProxy::kNonBlocking;
size_t avail = audioBuffer.frameCount + nonContig;
- ALOGV("obtainBuffer(%u) returned %u = %u + %u err %d",
+ ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d",
mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
if (err != NO_ERROR) {
if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR ||
@@ -1674,8 +1719,8 @@
// Sanity check on returned size
if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) {
- ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes",
- reqSize, (int) writtenSize);
+ ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
+ reqSize, ssize_t(writtenSize));
return NS_NEVER;
}
@@ -1736,7 +1781,7 @@
status_t AudioTrack::restoreTrack_l(const char *from)
{
ALOGW("dead IAudioTrack, %s, creating a new one from %s()",
- isOffloaded_l() ? "Offloaded" : "PCM", from);
+ isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
++mSequence;
status_t result;
@@ -1744,7 +1789,7 @@
// output parameters in createTrack_l()
AudioSystem::clearAudioConfigCache();
- if (isOffloaded_l()) {
+ if (isOffloadedOrDirect_l()) {
// FIXME re-creation of offloaded tracks is not yet implemented
return DEAD_OBJECT;
}
@@ -1830,6 +1875,19 @@
return isOffloaded_l();
}
+bool AudioTrack::isDirect() const
+{
+ AutoMutex lock(mLock);
+ return isDirect_l();
+}
+
+bool AudioTrack::isOffloadedOrDirect() const
+{
+ AutoMutex lock(mLock);
+ return isOffloadedOrDirect_l();
+}
+
+
status_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const
{
@@ -1858,6 +1916,136 @@
return mProxy->getUnderrunFrames();
}
+void AudioTrack::setAttributesFromStreamType(audio_stream_type_t streamType) {
+ mAttributes.flags = 0x0;
+
+ switch(streamType) {
+ case AUDIO_STREAM_DEFAULT:
+ case AUDIO_STREAM_MUSIC:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ mAttributes.usage = AUDIO_USAGE_MEDIA;
+ break;
+ case AUDIO_STREAM_VOICE_CALL:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+ break;
+ case AUDIO_STREAM_ENFORCED_AUDIBLE:
+ mAttributes.flags |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
+ // intended fall through, attributes in common with STREAM_SYSTEM
+ case AUDIO_STREAM_SYSTEM:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ mAttributes.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_RING:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ mAttributes.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ break;
+ case AUDIO_STREAM_ALARM:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ mAttributes.usage = AUDIO_USAGE_ALARM;
+ break;
+ case AUDIO_STREAM_NOTIFICATION:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ mAttributes.usage = AUDIO_USAGE_NOTIFICATION;
+ break;
+ case AUDIO_STREAM_BLUETOOTH_SCO:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+ mAttributes.flags |= AUDIO_FLAG_SCO;
+ break;
+ case AUDIO_STREAM_DTMF:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ break;
+ case AUDIO_STREAM_TTS:
+ mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ mAttributes.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ break;
+ default:
+ ALOGE("invalid stream type %d when converting to attributes", streamType);
+ }
+}
+
+void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) {
+ // flags to stream type mapping
+ if ((aa.flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
+ mStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
+ return;
+ }
+ if ((aa.flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
+ mStreamType = AUDIO_STREAM_BLUETOOTH_SCO;
+ return;
+ }
+
+ // usage to stream type mapping
+ switch (aa.usage) {
+ case AUDIO_USAGE_MEDIA:
+ case AUDIO_USAGE_GAME:
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ mStreamType = AUDIO_STREAM_MUSIC;
+ return;
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ mStreamType = AUDIO_STREAM_SYSTEM;
+ return;
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ mStreamType = AUDIO_STREAM_VOICE_CALL;
+ return;
+
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ mStreamType = AUDIO_STREAM_DTMF;
+ return;
+
+ case AUDIO_USAGE_ALARM:
+ mStreamType = AUDIO_STREAM_ALARM;
+ return;
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ mStreamType = AUDIO_STREAM_RING;
+ return;
+
+ case AUDIO_USAGE_NOTIFICATION:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ mStreamType = AUDIO_STREAM_NOTIFICATION;
+ return;
+
+ case AUDIO_USAGE_UNKNOWN:
+ default:
+ mStreamType = AUDIO_STREAM_MUSIC;
+ }
+}
+
+bool AudioTrack::isValidAttributes(const audio_attributes_t *paa) {
+ // has flags that map to a strategy?
+ if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO)) != 0) {
+ return true;
+ }
+
+ // has known usage?
+ switch (paa->usage) {
+ case AUDIO_USAGE_UNKNOWN:
+ case AUDIO_USAGE_MEDIA:
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ case AUDIO_USAGE_ALARM:
+ case AUDIO_USAGE_NOTIFICATION:
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ case AUDIO_USAGE_GAME:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
// =========================================================================
void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
@@ -1918,7 +2106,7 @@
ns = 1000000000LL;
// fall through
default:
- LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns);
+ LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
pauseInternal(ns);
return true;
}
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 0dbfa62..eec025e 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -135,7 +135,7 @@
// pipe should not be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
if (mIsOut) {
- ALOGE("Shared memory control block is corrupt (filled=%d, mFrameCount=%u); "
+ ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); "
"shutting down", filled, mFrameCount);
mIsShutdown = true;
status = NO_INIT;
@@ -338,7 +338,7 @@
ssize_t filled = rear - front;
// pipe should not be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
- ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled);
+ ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
return 0;
}
return (size_t)filled;
@@ -555,7 +555,7 @@
ssize_t filled = rear - front;
// pipe should not already be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
- ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled);
+ ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
mIsShutdown = true;
}
if (mIsShutdown) {
@@ -642,7 +642,7 @@
}
// FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time
if (!mIsOut || (mAvailToClient + stepCount >= minimum)) {
- ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum);
+ ALOGV("mAvailToClient=%zu stepCount=%zu minimum=%zu", mAvailToClient, stepCount, minimum);
int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
if (!(old & CBLK_FUTEX_WAKE)) {
(void) syscall(__NR_futex, &cblk->mFutex,
@@ -675,7 +675,7 @@
ssize_t filled = rear - cblk->u.mStreaming.mFront;
// pipe should not already be overfull
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
- ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled);
+ ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
mIsShutdown = true;
return 0;
}
@@ -834,7 +834,7 @@
size_t newPosition = position + stepCount;
int32_t setFlags = 0;
if (!(position <= newPosition && newPosition <= mFrameCount)) {
- ALOGW("%s newPosition %u outside [%u, %u]", __func__, newPosition, position, mFrameCount);
+ ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position, mFrameCount);
newPosition = mFrameCount;
} else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) {
if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) {
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 4992798..7d1ddfd 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -112,7 +112,7 @@
if (allprintable) {
// since 'buf' is empty, ICU would return a UTF-8 matcher with low confidence, so
// no need to even call it
- ALOGV("all tags are printable, assuming ascii (%d)", strlen(buf));
+ ALOGV("all tags are printable, assuming ascii (%zu)", strlen(buf));
} else {
ucsdet_setText(csd, buf, strlen(buf), &status);
int32_t matches;
@@ -267,11 +267,11 @@
Vector<const UCharsetMatch*> matches;
UErrorCode status = U_ZERO_ERROR;
- ALOGV("%d matches", nummatches);
+ ALOGV("%zu matches", nummatches);
for (size_t i = 0; i < nummatches; i++) {
const char *encname = ucsdet_getName(ucma[i], &status);
int confidence = ucsdet_getConfidence(ucma[i], &status);
- ALOGV("%d: %s %d", i, encname, confidence);
+ ALOGV("%zu: %s %d", i, encname, confidence);
matches.push_back(ucma[i]);
}
@@ -287,7 +287,7 @@
return matches[0];
}
- ALOGV("considering %d matches", num);
+ ALOGV("considering %zu matches", num);
// keep track of how many "special" characters result when converting the input using each
// encoding
@@ -315,7 +315,7 @@
freqcoverage = frequent_ja_coverage;
}
- ALOGV("%d: %s %d", i, encname, confidence);
+ ALOGV("%zu: %s %d", i, encname, confidence);
UConverter *conv = ucnv_open(encname, &status);
const char *source = input;
const char *sourceLimit = input + len;
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 77d131b..41a9065 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -64,7 +64,8 @@
RELEASE_AUDIO_PATCH,
LIST_AUDIO_PATCHES,
SET_AUDIO_PORT_CONFIG,
- REGISTER_CLIENT
+ REGISTER_CLIENT,
+ GET_OUTPUT_FOR_ATTR
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -155,6 +156,36 @@
return static_cast <audio_io_handle_t> (reply.readInt32());
}
+ virtual audio_io_handle_t getOutputForAttr(
+ const audio_attributes_t *attr,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ if (attr == NULL) {
+ ALOGE("Writing NULL audio attributes - shouldn't happen");
+ return (audio_io_handle_t) 0;
+ }
+ data.write(attr, sizeof(audio_attributes_t));
+ data.writeInt32(samplingRate);
+ data.writeInt32(static_cast <uint32_t>(format));
+ data.writeInt32(channelMask);
+ data.writeInt32(static_cast <uint32_t>(flags));
+ // hasOffloadInfo
+ if (offloadInfo == NULL) {
+ data.writeInt32(0);
+ } else {
+ data.writeInt32(1);
+ data.write(offloadInfo, sizeof(audio_offload_info_t));
+ }
+ remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
+ return static_cast <audio_io_handle_t> (reply.readInt32());
+ }
+
virtual status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session)
@@ -614,6 +645,30 @@
return NO_ERROR;
} break;
+ case GET_OUTPUT_FOR_ATTR: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_attributes_t *attr = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+ data.read(attr, sizeof(audio_attributes_t));
+ uint32_t samplingRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ audio_channel_mask_t channelMask = data.readInt32();
+ audio_output_flags_t flags =
+ static_cast <audio_output_flags_t>(data.readInt32());
+ bool hasOffloadInfo = data.readInt32() != 0;
+ audio_offload_info_t offloadInfo;
+ if (hasOffloadInfo) {
+ data.read(&offloadInfo, sizeof(audio_offload_info_t));
+ }
+ audio_io_handle_t output = getOutputForAttr(attr,
+ samplingRate,
+ format,
+ channelMask,
+ flags,
+ hasOffloadInfo ? &offloadInfo : NULL);
+ reply->writeInt32(static_cast <int>(output));
+ return NO_ERROR;
+ } break;
+
case START_OUTPUT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 432d890..38f717c 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -15,8 +15,10 @@
** limitations under the License.
*/
+#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
+
#include <binder/Parcel.h>
#include <media/IMediaHTTPService.h>
#include <media/IMediaMetadataRetriever.h>
@@ -125,7 +127,7 @@
sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
{
- ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
+ ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option);
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
data.writeInt64(timeUs);
@@ -237,7 +239,7 @@
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
int64_t timeUs = data.readInt64();
int option = data.readInt32();
- ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
+ ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option);
#ifndef DISABLE_GROUP_SCHEDULE_HACK
setSchedPolicy(data);
#endif
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 8e58162..95af006 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -17,6 +17,10 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "IMediaRecorder"
+
+#include <inttypes.h>
+#include <unistd.h>
+
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <camera/ICamera.h>
@@ -24,8 +28,6 @@
#include <media/IMediaRecorder.h>
#include <gui/Surface.h>
#include <gui/IGraphicBufferProducer.h>
-#include <unistd.h>
-
namespace android {
@@ -167,7 +169,7 @@
}
status_t setOutputFile(int fd, int64_t offset, int64_t length) {
- ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+ ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeFileDescriptor(fd);
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 28238c4..e9e453b 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -475,7 +475,7 @@
}
void MediaProfiles::initRequiredProfileRefs(const Vector<int>& cameraIds) {
- ALOGV("Number of camera ids: %d", cameraIds.size());
+ ALOGV("Number of camera ids: %zu", cameraIds.size());
CHECK(cameraIds.size() > 0);
mRequiredProfileRefs = new RequiredProfiles[cameraIds.size()];
for (size_t i = 0, n = cameraIds.size(); i < n; ++i) {
@@ -602,14 +602,14 @@
int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
if (index != -1) {
- ALOGV("Profile quality %d for camera %d already exists",
+ ALOGV("Profile quality %d for camera %zu already exists",
profile->mQuality, cameraId);
CHECK(index == refIndex);
continue;
}
// Insert the new profile
- ALOGV("Add a profile: quality %d=>%d for camera %d",
+ ALOGV("Add a profile: quality %d=>%d for camera %zu",
mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
profile->mQuality, cameraId);
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
index a55e09c..2aa0592 100644
--- a/media/libmedia/SoundPool.cpp
+++ b/media/libmedia/SoundPool.cpp
@@ -16,6 +16,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoundPool"
+
+#include <inttypes.h>
+
#include <utils/Log.h>
#define USE_SHARED_MEM_BUFFER
@@ -212,7 +215,7 @@
int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
{
- ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d",
+ ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
fd, offset, length, priority);
Mutex::Autolock lock(&mLock);
sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
@@ -462,7 +465,8 @@
mFd = dup(fd);
mOffset = offset;
mLength = length;
- ALOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset);
+ ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
+ mSampleID, mFd, mLength, mOffset);
}
void Sample::init()
@@ -516,7 +520,7 @@
ALOGE("Unable to load sample: %s", mUrl);
goto error;
}
- ALOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d",
+ ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
mHeap->getBase(), mSize, sampleRate, numChannels);
if (sampleRate > kMaxSampleRate) {
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 1d6bb6f..39a239d 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -18,6 +18,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetadataRetriever"
+#include <inttypes.h>
+
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <media/mediametadataretriever.h>
@@ -114,7 +116,7 @@
status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
{
- ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+ ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
Mutex::Autolock _l(mLock);
if (mRetriever == 0) {
ALOGE("retriever is not initialized");
@@ -129,7 +131,7 @@
sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
{
- ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
+ ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d)", timeUs, option);
Mutex::Autolock _l(mLock);
if (mRetriever == 0) {
ALOGE("retriever is not initialized");
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 0be01a9..406f9f2 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -17,12 +17,14 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer"
-#include <utils/Log.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/Log.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
@@ -157,7 +159,7 @@
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
- ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+ ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
@@ -194,7 +196,7 @@
(mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
if ((mPlayer != NULL) && hasBeenInitialized) {
- ALOGV("invoke %d", request.dataSize());
+ ALOGV("invoke %zu", request.dataSize());
return mPlayer->invoke(request, reply);
}
ALOGE("invoke failed: wrong state %X", mCurrentState);
@@ -818,7 +820,7 @@
audio_format_t* pFormat,
const sp<IMemoryHeap>& heap, size_t *pSize)
{
- ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
+ ALOGV("decode(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
status_t status;
const sp<IMediaPlayerService>& service = getMediaPlayerService();
if (service != 0) {
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 3710e46..c8192e9 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -17,6 +17,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaRecorder"
+
+#include <inttypes.h>
+
#include <utils/Log.h>
#include <media/mediarecorder.h>
#include <binder/IServiceManager.h>
@@ -286,7 +289,7 @@
status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
{
- ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+ ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 297f4fc..23b221d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -369,7 +369,7 @@
SINF *sinf = mFirstSINF;
while (sinf) {
SINF *next = sinf->next;
- delete sinf->IPMPData;
+ delete[] sinf->IPMPData;
delete sinf;
sinf = next;
}
@@ -694,7 +694,10 @@
return ERROR_MALFORMED;
}
sinf->len = dataLen - 3;
- sinf->IPMPData = new char[sinf->len];
+ sinf->IPMPData = new (std::nothrow) char[sinf->len];
+ if (sinf->IPMPData == NULL) {
+ return ERROR_MALFORMED;
+ }
data_offset += 2;
if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
@@ -1112,7 +1115,10 @@
return ERROR_MALFORMED;
}
- pssh.data = new uint8_t[pssh.datalen];
+ pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
+ if (pssh.data == NULL) {
+ return ERROR_MALFORMED;
+ }
ALOGV("allocated pssh @ %p", pssh.data);
ssize_t requested = (ssize_t) pssh.datalen;
if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
@@ -1794,7 +1800,10 @@
size = 0;
}
- uint8_t *buffer = new uint8_t[size + chunk_size];
+ uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
+ if (buffer == NULL) {
+ return ERROR_MALFORMED;
+ }
if (size > 0) {
memcpy(buffer, data, size);
@@ -2111,7 +2120,10 @@
return ERROR_MALFORMED;
}
- uint8_t *buffer = new uint8_t[size + 1];
+ uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
+ if (buffer == NULL) {
+ return ERROR_MALFORMED;
+ }
if (mDataSource->readAt(
offset, buffer, size) != (ssize_t)size) {
delete[] buffer;
@@ -2298,7 +2310,10 @@
return ERROR_MALFORMED;
}
- uint8_t *buffer = new uint8_t[size];
+ uint8_t *buffer = new (std::nothrow) uint8_t[size];
+ if (buffer == NULL) {
+ return ERROR_MALFORMED;
+ }
if (mDataSource->readAt(
offset, buffer, size) != (ssize_t)size) {
delete[] buffer;
@@ -2917,7 +2932,11 @@
mGroup->add_buffer(new MediaBuffer(max_size));
- mSrcBuffer = new uint8_t[max_size];
+ mSrcBuffer = new (std::nothrow) uint8_t[max_size];
+ if (mSrcBuffer == NULL) {
+ // file probably specified a bad max size
+ return ERROR_MALFORMED;
+ }
mStarted = true;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 6130084..79bdfe8 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -54,6 +54,7 @@
return mStreamType;
}
bool isOffloaded() const { return (mFlags & IAudioFlinger::TRACK_OFFLOAD) != 0; }
+ bool isDirect() const { return (mFlags & IAudioFlinger::TRACK_DIRECT) != 0; }
status_t setParameters(const String8& keyValuePairs);
status_t attachAuxEffect(int EffectId);
void setAuxBuffer(int EffectId, int32_t *buffer);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d6390b1..8ce819c 100755
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1660,7 +1660,7 @@
track->mState = TrackBase::STOPPED;
if (!trackActive) {
removeTrack_l(track);
- } else if (track->isFastTrack() || track->isOffloaded()) {
+ } else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
track->mState = TrackBase::STOPPING_1;
}
@@ -1868,7 +1868,9 @@
}
mNormalFrameCount = multiplier * mFrameCount;
// round up to nearest 16 frames to satisfy AudioMixer
- mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
+ if (mType == MIXER || mType == DUPLICATING) {
+ mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
+ }
ALOGI("HAL output buffer size %u frames, normal sink buffer size %u frames", mFrameCount,
mNormalFrameCount);
@@ -2656,7 +2658,7 @@
if (mNormalSink != 0) {
return mNormalSink->getTimestamp(timestamp);
}
- if (mType == OFFLOAD && mOutput->stream->get_presentation_position) {
+ if ((mType == OFFLOAD || mType == DIRECT) && mOutput->stream->get_presentation_position) {
uint64_t position64;
int ret = mOutput->stream->get_presentation_position(
mOutput->stream, &position64, ×tamp.mTime);
@@ -3947,14 +3949,16 @@
// The first time a track is added we wait
// for all its buffers to be filled before processing it
uint32_t minFrames;
- if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing()) {
+ if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()) {
minFrames = mNormalFrameCount;
} else {
minFrames = 1;
}
- if ((track->framesReady() >= minFrames) && track->isReady() &&
- !track->isPaused() && !track->isTerminated())
+ ALOGI("prepareTracks_l minFrames %d state %d frames ready %d, ",
+ minFrames, track->mState, track->framesReady());
+ if ((track->framesReady() >= minFrames) && track->isReady() && !track->isPaused() &&
+ !track->isStopping_2() && !track->isStopped())
{
ALOGVV("track %d s=%08x [OK]", track->name(), cblk->mServer);
@@ -3981,17 +3985,26 @@
if (!mEffectChains.isEmpty() && last) {
mEffectChains[0]->clearInputBuffer();
}
-
- ALOGVV("track %d s=%08x [NOT READY]", track->name(), cblk->mServer);
- if ((track->sharedBuffer() != 0) || track->isTerminated() ||
- track->isStopped() || track->isPaused()) {
+ if (track->isStopping_1()) {
+ track->mState = TrackBase::STOPPING_2;
+ }
+ if ((track->sharedBuffer() != 0) || track->isStopped() ||
+ track->isStopping_2() || track->isPaused()) {
// We have consumed all the buffers of this track.
// Remove it from the list of active tracks.
- // TODO: implement behavior for compressed audio
- size_t audioHALFrames = (latency_l() * mSampleRate) / 1000;
+ size_t audioHALFrames;
+ if (audio_is_linear_pcm(mFormat)) {
+ audioHALFrames = (latency_l() * mSampleRate) / 1000;
+ } else {
+ audioHALFrames = 0;
+ }
+
size_t framesWritten = mBytesWritten / mFrameSize;
if (mStandby || !last ||
track->presentationComplete(framesWritten, audioHALFrames)) {
+ if (track->isStopping_2()) {
+ track->mState = TrackBase::STOPPED;
+ }
if (track->isStopped()) {
track->reset();
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 1e906ad..4fbb973 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -706,7 +706,7 @@
if (playbackThread->mActiveTracks.indexOf(this) < 0) {
reset();
mState = STOPPED;
- } else if (!isFastTrack() && !isOffloaded()) {
+ } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
mState = STOPPED;
} else {
// For fast tracks prepareTracks_l() will set state to STOPPING_2
@@ -860,7 +860,7 @@
}
Mutex::Autolock _l(thread->mLock);
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- if (!isOffloaded()) {
+ if (!isOffloaded() && !isDirect()) {
if (!playbackThread->mLatchQValid) {
mPreviousValid = false;
return INVALID_OPERATION;
@@ -980,8 +980,6 @@
}
if (framesWritten >= mPresentationCompleteFrames || isOffloaded()) {
- ALOGV("presentationComplete() session %d complete: framesWritten %d",
- mSessionId, framesWritten);
triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
mAudioTrackServerProxy->setStreamEndDone();
return true;
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index c025a45..33e4397 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -90,6 +90,12 @@
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo) = 0;
+ virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding stream.
virtual status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index 8cc386a..6342d8f 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -131,6 +131,22 @@
format, channelMask, flags, offloadInfo);
}
+audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo)
+{
+ if (mAudioPolicyManager == NULL) {
+ return 0;
+ }
+ ALOGV("getOutput()");
+ Mutex::Autolock _l(mLock);
+ return mAudioPolicyManager->getOutputForAttr(attr, samplingRate,
+ format, channelMask, flags, offloadInfo);
+}
+
status_t AudioPolicyService::startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session)
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index d4c9374..aa810bc 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -122,6 +122,11 @@
STRING_TO_ENUM(AUDIO_FORMAT_MP3),
STRING_TO_ENUM(AUDIO_FORMAT_AAC),
STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
+ STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1),
+ STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2),
+ STRING_TO_ENUM(AUDIO_FORMAT_OPUS),
+ STRING_TO_ENUM(AUDIO_FORMAT_AC3),
+ STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
};
const StringToEnum sOutChannelsNameToEnumTable[] = {
@@ -623,13 +628,53 @@
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
- audio_io_handle_t output = 0;
- uint32_t latency = 0;
+
routing_strategy strategy = getStrategy(stream);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
device, stream, samplingRate, format, channelMask, flags);
+ return getOutputForDevice(device, stream, samplingRate,format, channelMask, flags,
+ offloadInfo);
+}
+
+audio_io_handle_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo)
+{
+ if (attr == NULL) {
+ ALOGE("getOutputForAttr() called with NULL audio attributes");
+ return 0;
+ }
+ ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s",
+ attr->usage, attr->content_type, attr->tags);
+
+ // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go
+ routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr);
+ audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
+ ALOGV("getOutputForAttr() device %d, samplingRate %d, format %x, channelMask %x, flags %x",
+ device, samplingRate, format, channelMask, flags);
+
+ audio_stream_type_t stream = streamTypefromAttributesInt(attr);
+ return getOutputForDevice(device, stream, samplingRate, format, channelMask, flags,
+ offloadInfo);
+}
+
+audio_io_handle_t AudioPolicyManager::getOutputForDevice(
+ audio_devices_t device,
+ audio_stream_type_t stream,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo)
+{
+ audio_io_handle_t output = 0;
+ uint32_t latency = 0;
+
#ifdef AUDIO_POLICY_TEST
if (mCurOutput != 0) {
ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d",
@@ -3239,6 +3284,44 @@
}
}
+uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
+ // flags to strategy mapping
+ if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
+ return (uint32_t) STRATEGY_ENFORCED_AUDIBLE;
+ }
+
+ // usage to strategy mapping
+ switch (attr->usage) {
+ case AUDIO_USAGE_MEDIA:
+ case AUDIO_USAGE_GAME:
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ return (uint32_t) STRATEGY_MEDIA;
+
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ return (uint32_t) STRATEGY_PHONE;
+
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ return (uint32_t) STRATEGY_DTMF;
+
+ case AUDIO_USAGE_ALARM:
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ return (uint32_t) STRATEGY_SONIFICATION;
+
+ case AUDIO_USAGE_NOTIFICATION:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL;
+
+ case AUDIO_USAGE_UNKNOWN:
+ default:
+ return (uint32_t) STRATEGY_MEDIA;
+ }
+}
+
void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
switch(stream) {
case AUDIO_STREAM_MUSIC:
@@ -5916,4 +5999,46 @@
mHwModules.add(module);
}
+audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr)
+{
+ // flags to stream type mapping
+ if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
+ return AUDIO_STREAM_ENFORCED_AUDIBLE;
+ }
+ if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
+ return AUDIO_STREAM_BLUETOOTH_SCO;
+ }
+
+ // usage to stream type mapping
+ switch (attr->usage) {
+ case AUDIO_USAGE_MEDIA:
+ case AUDIO_USAGE_GAME:
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ return AUDIO_STREAM_MUSIC;
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ return AUDIO_STREAM_SYSTEM;
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ return AUDIO_STREAM_VOICE_CALL;
+
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ return AUDIO_STREAM_DTMF;
+
+ case AUDIO_USAGE_ALARM:
+ return AUDIO_STREAM_ALARM;
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ return AUDIO_STREAM_RING;
+
+ case AUDIO_USAGE_NOTIFICATION:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ return AUDIO_STREAM_NOTIFICATION;
+
+ case AUDIO_USAGE_UNKNOWN:
+ default:
+ return AUDIO_STREAM_MUSIC;
+ }
+}
}; // namespace android
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index 1abeb6a..c23d994 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -84,6 +84,12 @@
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo);
+ virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo);
virtual status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session = 0);
@@ -116,6 +122,8 @@
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
+ // return the strategy corresponding to the given audio attributes
+ virtual uint32_t getStrategyForAttr(const audio_attributes_t *attr);
// return the enabled output devices for the given stream type
virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
@@ -755,6 +763,17 @@
uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
// converts device address to string sent to audio HAL via setParameters
static String8 addressToParameter(audio_devices_t device, const String8 address);
+ // internal method to return the output handle for the given device and format
+ audio_io_handle_t getOutputForDevice(
+ audio_devices_t device,
+ audio_stream_type_t stream,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo);
+ // internal function to derive a stream type value from audio attributes
+ audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr);
};
};
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 66d9cad..69673cd 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -70,6 +70,12 @@
audio_output_flags_t flags =
AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL);
+ virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ audio_channel_mask_t channelMask = 0,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+ const audio_offload_info_t *offloadInfo = NULL);
virtual status_t startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session = 0);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 280478c..b8227a7 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -261,35 +261,20 @@
return ret;
}
- ssize_t index = -1;
- { // Scope for service lock
- Mutex::Autolock lock(mServiceLock);
- index = mShimParams.indexOfKey(cameraId);
- // Release service lock so initializeShimMetadata can be called correctly.
- }
-
- if (index < 0) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- ret = initializeShimMetadata(cameraId);
- IPCThreadState::self()->restoreCallingIdentity(token);
- if (ret != OK) {
- return ret;
- }
+ CameraParameters shimParams;
+ if ((ret = getLegacyParametersLazy(cameraId, /*out*/&shimParams)) != OK) {
+ // Error logged by callee
+ return ret;
}
Vector<Size> sizes;
Vector<Size> jpegSizes;
Vector<int32_t> formats;
const char* supportedPreviewFormats;
- { // Scope for service lock
- Mutex::Autolock lock(mServiceLock);
- index = mShimParams.indexOfKey(cameraId);
-
- mShimParams[index].getSupportedPreviewSizes(/*out*/sizes);
-
- mShimParams[index].getSupportedPreviewFormats(/*out*/formats);
-
- mShimParams[index].getSupportedPictureSizes(/*out*/jpegSizes);
+ {
+ shimParams.getSupportedPreviewSizes(/*out*/sizes);
+ shimParams.getSupportedPreviewFormats(/*out*/formats);
+ shimParams.getSupportedPictureSizes(/*out*/jpegSizes);
}
// Always include IMPLEMENTATION_DEFINED
@@ -481,6 +466,7 @@
int uid = getCallingUid();
status_t ret = validateConnect(cameraId, uid);
if (ret != OK) {
+ // Error already logged by callee
return ret;
}
@@ -503,6 +489,7 @@
client);
if (ret != OK) {
+ // Error already logged by callee
return ret;
}
}
@@ -524,6 +511,52 @@
return OK;
}
+status_t CameraService::getLegacyParametersLazy(int cameraId,
+ /*out*/
+ CameraParameters* parameters) {
+
+ ALOGV("%s: for cameraId: %d", __FUNCTION__, cameraId);
+
+ status_t ret = 0;
+
+ if (parameters == NULL) {
+ ALOGE("%s: parameters must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ ssize_t index = -1;
+ { // Scope for service lock
+ Mutex::Autolock lock(mServiceLock);
+ index = mShimParams.indexOfKey(cameraId);
+ // Release service lock so initializeShimMetadata can be called correctly.
+
+ if (index >= 0) {
+ *parameters = mShimParams[index];
+ }
+ }
+
+ if (index < 0) {
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ ret = initializeShimMetadata(cameraId);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ if (ret != OK) {
+ // Error already logged by callee
+ return ret;
+ }
+
+ { // Scope for service lock
+ Mutex::Autolock lock(mServiceLock);
+ index = mShimParams.indexOfKey(cameraId);
+
+ LOG_ALWAYS_FATAL_IF(index < 0, "index should have been initialized");
+
+ *parameters = mShimParams[index];
+ }
+ }
+
+ return OK;
+}
+
status_t CameraService::validateConnect(int cameraId,
/*inout*/
int& clientUid) const {
@@ -626,7 +659,8 @@
int clientUid,
int callingPid,
/*out*/
- sp<Client>& client) {
+ sp<Client>& client,
+ int halVersion) {
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
@@ -639,28 +673,48 @@
cameraId);
}
- switch(deviceVersion) {
- case CAMERA_DEVICE_API_VERSION_1_0:
- client = new CameraClient(this, cameraClient,
- clientPackageName, cameraId,
- facing, callingPid, clientUid, getpid());
- break;
- case CAMERA_DEVICE_API_VERSION_2_0:
- case CAMERA_DEVICE_API_VERSION_2_1:
- case CAMERA_DEVICE_API_VERSION_3_0:
- case CAMERA_DEVICE_API_VERSION_3_1:
- case CAMERA_DEVICE_API_VERSION_3_2:
- client = new Camera2Client(this, cameraClient,
- clientPackageName, cameraId,
- facing, callingPid, clientUid, getpid(),
- deviceVersion);
- break;
- case -1:
- ALOGE("Invalid camera id %d", cameraId);
- return BAD_VALUE;
- default:
- ALOGE("Unknown camera device HAL version: %d", deviceVersion);
- return INVALID_OPERATION;
+ if (halVersion < 0 || halVersion == deviceVersion) {
+ // Default path: HAL version is unspecified by caller, create CameraClient
+ // based on device version reported by the HAL.
+ switch(deviceVersion) {
+ case CAMERA_DEVICE_API_VERSION_1_0:
+ client = new CameraClient(this, cameraClient,
+ clientPackageName, cameraId,
+ facing, callingPid, clientUid, getpid());
+ break;
+ case CAMERA_DEVICE_API_VERSION_2_0:
+ case CAMERA_DEVICE_API_VERSION_2_1:
+ case CAMERA_DEVICE_API_VERSION_3_0:
+ case CAMERA_DEVICE_API_VERSION_3_1:
+ case CAMERA_DEVICE_API_VERSION_3_2:
+ client = new Camera2Client(this, cameraClient,
+ clientPackageName, cameraId,
+ facing, callingPid, clientUid, getpid(),
+ deviceVersion);
+ break;
+ case -1:
+ ALOGE("Invalid camera id %d", cameraId);
+ return BAD_VALUE;
+ default:
+ ALOGE("Unknown camera device HAL version: %d", deviceVersion);
+ return INVALID_OPERATION;
+ }
+ } else {
+ // A particular HAL version is requested by caller. Create CameraClient
+ // based on the requested HAL version.
+ if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
+ halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+ // Only support higher HAL version device opened as HAL1.0 device.
+ client = new CameraClient(this, cameraClient,
+ clientPackageName, cameraId,
+ facing, callingPid, clientUid, getpid());
+ } else {
+ // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
+ ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
+ " opened as HAL %x device", halVersion, deviceVersion,
+ CAMERA_DEVICE_API_VERSION_1_0);
+ return INVALID_OPERATION;
+ }
}
status_t status = connectFinishUnsafe(client, client->getRemote());
@@ -729,6 +783,63 @@
return OK;
}
+status_t CameraService::connectLegacy(
+ const sp<ICameraClient>& cameraClient,
+ int cameraId, int halVersion,
+ const String16& clientPackageName,
+ int clientUid,
+ /*out*/
+ sp<ICamera>& device) {
+
+ if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_3) {
+ ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
+ __FUNCTION__, mModule->common.module_api_version);
+ return INVALID_OPERATION;
+ }
+
+ String8 clientName8(clientPackageName);
+ int callingPid = getCallingPid();
+
+ LOG1("CameraService::connect legacy E (pid %d \"%s\", id %d)", callingPid,
+ clientName8.string(), cameraId);
+
+ status_t status = validateConnect(cameraId, /*inout*/clientUid);
+ if (status != OK) {
+ return status;
+ }
+
+ sp<Client> client;
+ {
+ Mutex::Autolock lock(mServiceLock);
+ sp<BasicClient> clientTmp;
+ if (!canConnectUnsafe(cameraId, clientPackageName,
+ cameraClient->asBinder(),
+ /*out*/clientTmp)) {
+ return -EBUSY;
+ } else if (client.get() != NULL) {
+ device = static_cast<Client*>(clientTmp.get());
+ return OK;
+ }
+
+ status = connectHelperLocked(cameraClient,
+ cameraId,
+ clientPackageName,
+ clientUid,
+ callingPid,
+ client,
+ halVersion);
+ if (status != OK) {
+ return status;
+ }
+
+ }
+ // important: release the mutex here so the client can call back
+ // into the service from its destructor (can be at the end of the call)
+
+ device = client;
+ return OK;
+}
+
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
const sp<IBinder>& remoteCallback) {
status_t status = client->initialize(mModule);
@@ -791,8 +902,8 @@
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
- client = new ProCamera2Client(this, cameraCb, String16(),
- cameraId, facing, callingPid, USE_CALLING_UID, getpid());
+ client = new ProCamera2Client(this, cameraCb, clientPackageName,
+ cameraId, facing, callingPid, clientUid, getpid());
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
@@ -871,8 +982,8 @@
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
- client = new CameraDeviceClient(this, cameraCb, String16(),
- cameraId, facing, callingPid, USE_CALLING_UID, getpid());
+ client = new CameraDeviceClient(this, cameraCb, clientPackageName,
+ cameraId, facing, callingPid, clientUid, getpid());
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
@@ -961,6 +1072,78 @@
return BAD_VALUE;
}
+status_t CameraService::getLegacyParameters(
+ int cameraId,
+ /*out*/
+ String16* parameters) {
+ ALOGV("%s: for camera ID = %d", __FUNCTION__, cameraId);
+
+ if (parameters == NULL) {
+ ALOGE("%s: parameters must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ status_t ret = 0;
+
+ CameraParameters shimParams;
+ if ((ret = getLegacyParametersLazy(cameraId, /*out*/&shimParams)) != OK) {
+ // Error logged by caller
+ return ret;
+ }
+
+ String8 shimParamsString8 = shimParams.flatten();
+ String16 shimParamsString16 = String16(shimParamsString8);
+
+ *parameters = shimParamsString16;
+
+ return OK;
+}
+
+status_t CameraService::supportsCameraApi(int cameraId, int apiVersion) {
+ ALOGV("%s: for camera ID = %d", __FUNCTION__, cameraId);
+
+ switch (apiVersion) {
+ case API_VERSION_1:
+ case API_VERSION_2:
+ break;
+ default:
+ ALOGE("%s: Bad API version %d", __FUNCTION__, apiVersion);
+ return BAD_VALUE;
+ }
+
+ int facing = -1;
+ int deviceVersion = getDeviceVersion(cameraId, &facing);
+
+ switch(deviceVersion) {
+ case CAMERA_DEVICE_API_VERSION_1_0:
+ case CAMERA_DEVICE_API_VERSION_2_0:
+ case CAMERA_DEVICE_API_VERSION_2_1:
+ case CAMERA_DEVICE_API_VERSION_3_0:
+ case CAMERA_DEVICE_API_VERSION_3_1:
+ if (apiVersion == API_VERSION_2) {
+ ALOGV("%s: Camera id %d uses HAL prior to HAL3.2, doesn't support api2 without shim",
+ __FUNCTION__, cameraId);
+ return -EOPNOTSUPP;
+ } else { // if (apiVersion == API_VERSION_1) {
+ ALOGV("%s: Camera id %d uses older HAL before 3.2, but api1 is always supported",
+ __FUNCTION__, cameraId);
+ return OK;
+ }
+ case CAMERA_DEVICE_API_VERSION_3_2:
+ ALOGV("%s: Camera id %d uses HAL3.2 or newer, supports api1/api2 directly",
+ __FUNCTION__, cameraId);
+ return OK;
+ case -1:
+ ALOGE("%s: Invalid camera id %d", __FUNCTION__, cameraId);
+ return BAD_VALUE;
+ default:
+ ALOGE("%s: Unknown camera device HAL version: %d", __FUNCTION__, deviceVersion);
+ return INVALID_OPERATION;
+ }
+
+ return OK;
+}
+
void CameraService::removeClientByRemote(const wp<IBinder>& remoteBinder) {
int callingPid = getCallingPid();
LOG1("CameraService::removeClientByRemote E (pid %d)", callingPid);
@@ -1090,6 +1273,8 @@
switch (code) {
case BnCameraService::CONNECT:
case BnCameraService::CONNECT_PRO:
+ case BnCameraService::CONNECT_DEVICE:
+ case BnCameraService::CONNECT_LEGACY:
const int pid = getCallingPid();
const int self_pid = getpid();
if (pid != self_pid) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ee39d52..28590eb 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -83,6 +83,11 @@
/*out*/
sp<ICamera>& device);
+ virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient, int cameraId,
+ int halVersion, const String16& clientPackageName, int clientUid,
+ /*out*/
+ sp<ICamera>& device);
+
virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb,
int cameraId, const String16& clientPackageName, int clientUid,
/*out*/
@@ -100,6 +105,15 @@
virtual status_t removeListener(
const sp<ICameraServiceListener>& listener);
+ virtual status_t getLegacyParameters(
+ int cameraId,
+ /*out*/
+ String16* parameters);
+
+ // OK = supports api of that version, -EOPNOTSUPP = does not support
+ virtual status_t supportsCameraApi(
+ int cameraId, int apiVersion);
+
// Extra permissions checks
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -414,6 +428,14 @@
status_t initializeShimMetadata(int cameraId);
/**
+ * Get the cached CameraParameters for the camera. If they haven't been
+ * cached yet, then initialize them for the first time.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ status_t getLegacyParametersLazy(int cameraId, /*out*/CameraParameters* parameters);
+
+ /**
* Generate the CameraCharacteristics metadata required by the Camera2 API
* from the available HAL1 CameraParameters and CameraInfo.
*
@@ -433,7 +455,8 @@
int clientUid,
int callingPid,
/*out*/
- sp<Client>& client);
+ sp<Client>& client,
+ int halVersion = CAMERA_HAL_API_VERSION_UNSPECIFIED);
};
} // namespace android
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 30b7bb8..517226d 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -79,7 +79,7 @@
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
- return NO_INIT;
+ return res;
}
mHardware->setCallbacks(notifyCallback,
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 87b2807..925b645 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -92,8 +92,22 @@
status_t initialize(hw_module_t *module)
{
ALOGI("Opening camera %s", mName.string());
- int rc = module->methods->open(module, mName.string(),
- (hw_device_t **)&mDevice);
+ camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
+ camera_info info;
+ status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
+ if (res != OK) return res;
+
+ int rc = OK;
+ if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
+ info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
+ // Open higher version camera device as HAL1.0 device.
+ rc = cameraModule->open_legacy(module, mName.string(),
+ CAMERA_DEVICE_API_VERSION_1_0,
+ (hw_device_t **)&mDevice);
+ } else {
+ rc = module->methods->open(module, mName.string(),
+ (hw_device_t **)&mDevice);
+ }
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;