Merge tag 'android-11.0.0_r48' of https://android.googlesource.com/platform//frameworks/av into r
Android 11.0.0 Release 48 (RD2A.211001.002)
Change-Id: I4bbe883091b412cdaecc4927547ae0c7df5b0af0
diff --git a/camera/Android.bp b/camera/Android.bp
index fa36bb3..21ef9ee 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -14,6 +14,7 @@
cc_library_shared {
name: "libcamera_client",
+ defaults: ["camera_parameter_library_defaults"],
aidl: {
export_aidl_headers: true,
@@ -32,7 +33,6 @@
// Source for camera interface parcelables, and manually-written interfaces
"Camera.cpp",
"CameraMetadata.cpp",
- "CameraParameters.cpp",
"CaptureResult.cpp",
"CameraParameters2.cpp",
"ICamera.cpp",
@@ -77,6 +77,16 @@
}
+cc_library_static {
+ name: "libcamera_parameters",
+
+ export_include_dirs: [
+ "include",
+ ],
+ srcs: ["CameraParameters.cpp"],
+
+}
+
// AIDL interface between camera clients and the camera service.
filegroup {
name: "libcamera_client_aidl",
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 68969cf..de8ac2f 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -237,6 +237,9 @@
void CameraParameters::set(const char *key, const char *value)
{
+ if (key == NULL || value == NULL)
+ return;
+
// XXX i think i can do this with strspn()
if (strchr(key, '=') || strchr(key, ';')) {
//XXX ALOGE("Key \"%s\"contains invalid character (= or ;)", key);
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index bef2ea0..be82ff4 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -51,7 +51,11 @@
data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
data.writeInt32(msgType);
data.writeInt32(ext1);
- data.writeInt32(ext2);
+ if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) {
+ data.writeFileDescriptor(ext2);
+ } else {
+ data.writeInt32(ext2);
+ }
remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -129,8 +133,13 @@
ALOGV("NOTIFY_CALLBACK");
CHECK_INTERFACE(ICameraClient, data, reply);
int32_t msgType = data.readInt32();
- int32_t ext1 = data.readInt32();
- int32_t ext2 = data.readInt32();
+ int32_t ext1 = data.readInt32();
+ int32_t ext2 = 0;
+ if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) {
+ ext2 = data.readFileDescriptor();
+ } else {
+ ext2 = data.readInt32();
+ }
notifyCallback(msgType, ext1, ext2);
return NO_ERROR;
} break;
diff --git a/camera/include/camera/CameraParameters2.h b/camera/include/camera/CameraParameters2.h
index f691cd6..5fae079 100644
--- a/camera/include/camera/CameraParameters2.h
+++ b/camera/include/camera/CameraParameters2.h
@@ -19,7 +19,7 @@
#include <utils/Vector.h>
#include <utils/String8.h>
-#include "CameraParameters.h"
+#include <camera/CameraParameters.h>
namespace android {
diff --git a/include/media/AudioSession.h b/include/media/AudioSession.h
new file mode 120000
index 0000000..005e48e
--- /dev/null
+++ b/include/media/AudioSession.h
@@ -0,0 +1 @@
+../../media/libaudioclient/include/media/AudioSession.h
\ No newline at end of file
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index e26a831..8dc7d9e 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -43,6 +43,7 @@
sp<IAudioFlinger> AudioSystem::gAudioFlinger;
sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
std::set<audio_error_callback> AudioSystem::gAudioErrorCallbacks;
+audio_session_callback AudioSystem::gAudioSessionCallback = NULL;
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
@@ -753,6 +754,17 @@
gRecordConfigCallback = cb;
}
+/*static*/ status_t AudioSystem::setAudioSessionCallback(audio_session_callback cb)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ Mutex::Autolock _l(gLock);
+ gAudioSessionCallback = cb;
+
+ return NO_ERROR;
+}
+
// client singleton for AudioPolicyService binder interface
// protected by gLockAPS
sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
@@ -1686,6 +1698,27 @@
return NO_ERROR;
}
+status_t AudioSystem::setAppVolume(const String8& packageName, const float volume)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setAppVolume(packageName, volume);
+}
+
+status_t AudioSystem::setAppMute(const String8& packageName, const bool mute)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setAppMute(packageName, mute);
+}
+
+status_t AudioSystem::listAppTrackDatas(unsigned int *num, AppTrackData *vols)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->listAppTrackDatas(num, vols);
+}
+
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
@@ -1812,6 +1845,32 @@
}
}
+// ---------------------------------------------------------------------------
+
+status_t AudioSystem::listAudioSessions(audio_stream_type_t stream,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->listAudioSessions(stream, sessions);
+}
+
+void AudioSystem::AudioPolicyServiceClient::onOutputSessionEffectsUpdate(
+ sp<AudioSessionInfo>& info, bool added)
+{
+ ALOGV("AudioPolicyServiceClient::onOutputSessionEffectsUpdate(%d, %d, %d)",
+ info->mStream, info->mSessionId, added);
+ audio_session_callback cb = NULL;
+ {
+ Mutex::Autolock _l(AudioSystem::gLock);
+ cb = gAudioSessionCallback;
+ }
+
+ if (cb != NULL) {
+ cb(AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE, info, added);
+ }
+}
+
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
{
{
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index d3a037c..0abcb0b 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -91,7 +91,10 @@
SET_MASTER_BALANCE,
GET_MASTER_BALANCE,
SET_EFFECT_SUSPENDED,
- SET_AUDIO_HAL_PIDS
+ SET_AUDIO_HAL_PIDS,
+ SET_APP_VOLUME,
+ SET_APP_MUTE,
+ LIST_ACTIVE_APP_VOLUMES
};
#define MAX_ITEMS_PER_LIST 1024
@@ -276,6 +279,48 @@
return NO_ERROR;
}
+ virtual status_t setAppVolume(const String8& packageName, const float value) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeString8(packageName);
+ data.writeFloat(value);
+ remote()->transact(SET_APP_VOLUME, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setAppMute(const String8& packageName, const bool mute) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeString8(packageName);
+ data.writeInt32(mute);
+ remote()->transact(SET_APP_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t listAppTrackDatas(unsigned int *num_volumes, AppTrackData *volumes)
+ {
+ if (num_volumes == NULL || (*num_volumes != 0 && volumes == NULL)) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ unsigned int numVolsReq = (volumes == NULL) ? 0 : *num_volumes;
+ data.writeInt32(numVolsReq);
+ status_t status = remote()->transact(LIST_ACTIVE_APP_VOLUMES, data, &reply);
+ if (status != NO_ERROR ||
+ (status = (status_t)reply.readInt32()) != NO_ERROR) {
+ return status;
+ }
+ *num_volumes = (unsigned int)reply.readInt32();
+ if (numVolsReq > *num_volumes) {
+ numVolsReq = *num_volumes;
+ }
+ if (numVolsReq > 0) {
+ reply.read(volumes, numVolsReq * sizeof(AppTrackData));
+ }
+ return status;
+ }
+
virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
audio_io_handle_t output)
{
@@ -1621,6 +1666,45 @@
reply->writeInt32(setAudioHalPids(pids));
return NO_ERROR;
}
+ case SET_APP_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ String8 packageName = data.readString8();
+ float volume = data.readFloat();
+ reply->writeInt32( setAppVolume(packageName, volume) );
+ return NO_ERROR;
+ }
+ case SET_APP_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ String8 packageName = data.readString8();
+ bool muted = data.readInt32();
+ reply->writeInt32( setAppMute(packageName, muted) );
+ return NO_ERROR;
+ }
+ case LIST_ACTIVE_APP_VOLUMES: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ unsigned int numReq = data.readInt32();
+ if (numReq > MAX_ITEMS_PER_LIST) {
+ numReq = MAX_ITEMS_PER_LIST;
+ }
+ unsigned int numVol = numReq;
+ AppTrackData *vols = new (std::nothrow) AppTrackData[numVol];
+ if (vols == NULL) {
+ reply->writeInt32(NO_MEMORY);
+ reply->writeInt32(0);
+ return NO_ERROR;
+ }
+ status_t status = listAppTrackDatas(&numVol, vols);
+ reply->writeInt32(status);
+ reply->writeInt32(numVol);
+ if (status == NO_ERROR) {
+ if (numReq > numVol) {
+ numReq = numVol;
+ }
+ reply->write(vols, numReq * sizeof(AppTrackData));
+ }
+ delete[] vols;
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 43a5369..d1d5477 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -120,6 +120,7 @@
AUDIO_MODULES_UPDATED, // oneway
SET_CURRENT_IME_UID,
REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER,
+ LIST_AUDIO_SESSIONS,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -1496,6 +1497,29 @@
if (status != NO_ERROR) return status;
return NO_ERROR;
}
+
+ virtual status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(streams);
+ status_t status = remote()->transact(LIST_AUDIO_SESSIONS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ status = reply.readInt32();
+ if (status == NO_ERROR) {
+ size_t size = (size_t)reply.readUint32();
+ for (size_t i = 0; i < size && reply.dataAvail() > 0; i++) {
+ sp<AudioSessionInfo> info = new AudioSessionInfo();
+ info->readFromParcel(reply);
+ sessions.push_back(info);
+ }
+ }
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -2231,6 +2255,23 @@
return NO_ERROR;
} break;
+ case LIST_AUDIO_SESSIONS: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t streams = (audio_stream_type_t)data.readInt32();
+
+ Vector< sp<AudioSessionInfo>> sessions;
+ status_t status = listAudioSessions(streams, sessions);
+
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeUint32(static_cast<uint32_t>(sessions.size()));
+ for (size_t i = 0; i < sessions.size(); i++) {
+ sessions[i]->writeToParcel(reply);
+ }
+ }
+ return NO_ERROR;
+ }
+
case ACQUIRE_SOUNDTRIGGER_SESSION: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_session_t session = AUDIO_SESSION_NONE;
diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp
index 0f9580c..eeefff9 100644
--- a/media/libaudioclient/IAudioPolicyServiceClient.cpp
+++ b/media/libaudioclient/IAudioPolicyServiceClient.cpp
@@ -33,6 +33,7 @@
MIX_STATE_UPDATE,
RECORDING_CONFIGURATION_UPDATE,
VOLUME_GROUP_CHANGED,
+ OUTPUT_SESSION_EFFECTS_UPDATE,
};
// ----------------------------------------------------------------------
@@ -149,6 +150,19 @@
data.writeInt32((int32_t) source);
remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
+ data.writeInt32(info->mStream);
+ data.writeInt32(info->mSessionId);
+ data.writeInt32(info->mFlags);
+ data.writeInt32(info->mChannelMask);
+ data.writeInt32(info->mUid);
+ data.writeInt32(added ? 1 : 0);
+ remote()->transact(OUTPUT_SESSION_EFFECTS_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient");
@@ -202,6 +216,20 @@
&deviceConfig, effects, patchHandle, source);
return NO_ERROR;
} break;
+ case OUTPUT_SESSION_EFFECTS_UPDATE: {
+ CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
+ audio_stream_type_t stream = static_cast<audio_stream_type_t>(data.readInt32());
+ audio_session_t sessionId = static_cast<audio_session_t>(data.readInt32());
+ audio_output_flags_t flags = static_cast<audio_output_flags_t>(data.readInt32());
+ audio_channel_mask_t channelMask = static_cast<audio_channel_mask_t>(data.readInt32());
+ uid_t uid = static_cast<uid_t>(data.readInt32());
+ bool added = data.readInt32() > 0;
+
+ sp<AudioSessionInfo> info = new AudioSessionInfo(
+ sessionId, stream, flags, channelMask, uid);
+ onOutputSessionEffectsUpdate(info, added);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/include/media/AppTrackData.h b/media/libaudioclient/include/media/AppTrackData.h
new file mode 100644
index 0000000..5fd6bb8
--- /dev/null
+++ b/media/libaudioclient/include/media/AppTrackData.h
@@ -0,0 +1,44 @@
+#ifndef APP_TRACK_DATA_H
+#define APP_TRACK_DATA_H
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+#define APP_TRACK_DATA_MAX_PACKAGENAME_LEN 128
+
+namespace android {
+ class AppTrackData : public Parcelable {
+ public:
+ char packageName[APP_TRACK_DATA_MAX_PACKAGENAME_LEN];
+ bool muted;
+ float volume;
+ bool active;
+
+ bool operator <(const AppTrackData &obj) const {
+ int t = strcmp(packageName, obj.packageName);
+ return t < 0;
+ }
+
+ /* Parcel */
+ status_t readFromParcel(const Parcel *parcel) override {
+ String8 pn = parcel->readString8();
+ strcpy(packageName, pn.c_str());
+ muted = parcel->readInt32();
+ volume = parcel->readFloat();
+ active = parcel->readInt32();
+ return NO_ERROR;
+ }
+
+ status_t writeToParcel(Parcel *parcel) const override {
+ (void)parcel->writeString8(String8(packageName));
+ (void)parcel->writeInt32(muted);
+ (void)parcel->writeFloat(volume);
+ (void)parcel->writeInt32(active);
+ return NO_ERROR;
+ }
+ };
+};
+
+#endif // APP_TRACK_DATA_H
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 00fe278..b7474fb 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -25,6 +25,7 @@
#include <utils/String8.h>
#include <utils/Vector.h>
#include <cutils/multiuser.h>
+#include <media/AudioSession.h>
namespace android {
@@ -48,6 +49,7 @@
// AudioSystem's implementation of the AudioPolicyClient interface
// keep in sync with AudioSystem.java
#define DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE 0
+#define AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE 10
#define MIX_STATE_DISABLED (-1)
#define MIX_STATE_IDLE 0
diff --git a/media/libaudioclient/include/media/AudioSession.h b/media/libaudioclient/include/media/AudioSession.h
new file mode 100644
index 0000000..2bae521
--- /dev/null
+++ b/media/libaudioclient/include/media/AudioSession.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIOSESSION_H
+#define ANDROID_AUDIOSESSION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <system/audio.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+// class to store streaminfo
+class AudioSessionInfo : public RefBase {
+public:
+ AudioSessionInfo(audio_session_t session, audio_stream_type_t stream, audio_output_flags_t flags,
+ audio_channel_mask_t channelMask, uid_t uid) :
+ mSessionId(session), mStream(stream), mFlags(flags), mChannelMask(channelMask),
+ mUid(uid), mRefCount(0) {}
+
+ AudioSessionInfo() : mSessionId((audio_session_t) 0), mStream(AUDIO_STREAM_DEFAULT), mFlags(AUDIO_OUTPUT_FLAG_NONE), mChannelMask(AUDIO_CHANNEL_NONE), mUid(0) {}
+
+ /*virtual*/ ~AudioSessionInfo() {}
+
+ audio_session_t mSessionId;
+ audio_stream_type_t mStream;
+ audio_output_flags_t mFlags;
+ audio_channel_mask_t mChannelMask;
+ uid_t mUid;
+
+ // AudioPolicyManager keeps mLock, no need for lock on reference count here
+ int mRefCount;
+
+ void readFromParcel(const Parcel &parcel) {
+ mSessionId = (audio_session_t) parcel.readInt32();
+ mStream = static_cast<audio_stream_type_t>(parcel.readInt32());
+ mFlags = static_cast<audio_output_flags_t>(parcel.readInt32());
+ mChannelMask = static_cast<audio_channel_mask_t>(parcel.readInt32());
+ mUid = static_cast<uid_t>(parcel.readInt32());
+ }
+
+ void writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32(mSessionId);
+ parcel->writeInt32(mStream);
+ parcel->writeInt32(mFlags);
+ parcel->writeInt32(mChannelMask);
+ parcel->writeInt32(mUid);
+ }
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOSESSION_H
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 19c2cbd..d9e8ade 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -47,10 +47,13 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source);
+typedef void (*audio_session_callback)(int event,
+ sp<AudioSessionInfo>& session, bool added);
class IAudioFlinger;
class IAudioPolicyService;
class String8;
+class AppTrackData;
class AudioSystem
{
@@ -120,6 +123,7 @@
static void setDynPolicyCallback(dynamic_policy_callback cb);
static void setRecordConfigCallback(record_config_callback);
+ static status_t setAudioSessionCallback(audio_session_callback cb);
// helper function to obtain AudioFlinger service handle
static const sp<IAudioFlinger> get_audio_flinger();
@@ -460,6 +464,9 @@
static status_t registerSoundTriggerCaptureStateListener(
const sp<CaptureStateListener>& listener);
+ static status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions);
+
// ----------------------------------------------------------------------------
class AudioVolumeGroupCallback : public RefBase
@@ -513,6 +520,10 @@
static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
+ static status_t setAppVolume(const String8& packageName, const float value);
+ static status_t setAppMute(const String8& packageName, const bool value);
+ static status_t listAppTrackDatas(unsigned int *num, AppTrackData *vols);
+
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
@@ -593,6 +604,7 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source);
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
private:
Mutex mLock;
@@ -619,6 +631,7 @@
static std::set<audio_error_callback> gAudioErrorCallbacks;
static dynamic_policy_callback gDynPolicyCallback;
static record_config_callback gRecordConfigCallback;
+ static audio_session_callback gAudioSessionCallback;
static size_t gInBuffSize;
// previous parameters for recording buffer size queries
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index bcc11f4..646c4e9 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -30,6 +30,7 @@
#include <media/DeviceDescriptorBase.h>
#include <media/IAudioTrack.h>
#include <media/IAudioFlingerClient.h>
+#include <media/AppTrackData.h>
#include <system/audio.h>
#include <system/audio_effect.h>
#include <system/audio_policy.h>
@@ -540,6 +541,10 @@
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
+
+ virtual status_t setAppVolume(const String8& packageName, const float value) = 0;
+ virtual status_t setAppMute(const String8& packageName, const bool value) = 0;
+ virtual status_t listAppTrackDatas(unsigned int *num, AppTrackData *vols) = 0;
};
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 376c6eb..b1001a8 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -254,6 +254,9 @@
virtual status_t registerSoundTriggerCaptureStateListener(
const sp<media::ICaptureStateListener>& listener,
bool* result) = 0;
+
+ virtual status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions) = 0;
};
diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
index 47b31ee..bc36f74 100644
--- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
+++ b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h
@@ -25,6 +25,7 @@
#include <system/audio_effect.h>
#include <media/AudioPolicy.h>
#include <media/AudioVolumeGroup.h>
+#include <media/AudioSession.h>
namespace android {
@@ -65,6 +66,8 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source) = 0;
+ // Notifies when a default effect set is attached to a session/stream
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added) = 0;
};
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 637322f..8be961c 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -240,7 +240,10 @@
const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
+ if (codec == -1) {
+ ALOGE("MediaProfiles::createVideoCodec failed to locate codec %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::VideoCodec *videoCodec =
new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec),
@@ -262,7 +265,10 @@
!strcmp("channels", atts[6]));
const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
+ if (codec == -1) {
+ ALOGE("MediaProfiles::createAudioCodec failed to locate codec %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::AudioCodec *audioCodec =
new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec),
@@ -282,7 +288,10 @@
const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]);
const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
+ if (codec == -1) {
+ ALOGE("MediaProfiles::createAudioDecoderCap failed to locate codec %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::AudioDecoderCap *cap =
new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec));
@@ -298,7 +307,10 @@
const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]);
const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
+ if (codec == -1) {
+ ALOGE("MediaProfiles::createVideoDecoderCap failed to locate codec %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::VideoDecoderCap *cap =
new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec));
@@ -322,7 +334,10 @@
const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
+ if (codec == -1) {
+ ALOGE("MediaProfiles::createVideoEncoderCap failed to locate codec %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::VideoEncoderCap *cap =
new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec),
@@ -346,7 +361,10 @@
const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
+ if (codec == -1) {
+ ALOGE("MediaProfiles::createAudioEncoderCap failed to locate codec %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::AudioEncoderCap *cap =
new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]),
@@ -386,11 +404,17 @@
const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/
sizeof(sCamcorderQualityNameMap[0]);
const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]);
- CHECK(quality != -1);
+ if (quality == -1) {
+ ALOGE("MediaProfiles::createCamcorderProfile failed to locate quality %s", atts[1]);
+ return nullptr;
+ }
const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]);
- CHECK(fileFormat != -1);
+ if (fileFormat == -1) {
+ ALOGE("MediaProfiles::createCamcorderProfile failed to locate file format %s", atts[1]);
+ return nullptr;
+ }
MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
profile->mCameraId = cameraId;
@@ -462,24 +486,39 @@
createAudioCodec(atts, profiles);
} else if (strcmp("VideoEncoderCap", name) == 0 &&
strcmp("true", atts[3]) == 0) {
- profiles->mVideoEncoders.add(createVideoEncoderCap(atts));
+ MediaProfiles::VideoEncoderCap* cap = createVideoEncoderCap(atts);
+ if (cap != nullptr) {
+ profiles->mVideoEncoders.add(cap);
+ }
} else if (strcmp("AudioEncoderCap", name) == 0 &&
strcmp("true", atts[3]) == 0) {
- profiles->mAudioEncoders.add(createAudioEncoderCap(atts));
+ MediaProfiles::AudioEncoderCap* cap = createAudioEncoderCap(atts);
+ if (cap != nullptr) {
+ profiles->mAudioEncoders.add(cap);
+ }
} else if (strcmp("VideoDecoderCap", name) == 0 &&
strcmp("true", atts[3]) == 0) {
- profiles->mVideoDecoders.add(createVideoDecoderCap(atts));
+ MediaProfiles::VideoDecoderCap* cap = createVideoDecoderCap(atts);
+ if (cap != nullptr) {
+ profiles->mVideoDecoders.add(cap);
+ }
} else if (strcmp("AudioDecoderCap", name) == 0 &&
strcmp("true", atts[3]) == 0) {
- profiles->mAudioDecoders.add(createAudioDecoderCap(atts));
+ MediaProfiles::AudioDecoderCap* cap = createAudioDecoderCap(atts);
+ if (cap != nullptr) {
+ profiles->mAudioDecoders.add(cap);
+ }
} else if (strcmp("EncoderOutputFileFormat", name) == 0) {
profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
} else if (strcmp("CamcorderProfiles", name) == 0) {
profiles->mCurrentCameraId = getCameraId(atts);
profiles->addStartTimeOffset(profiles->mCurrentCameraId, atts);
} else if (strcmp("EncoderProfile", name) == 0) {
- profiles->mCamcorderProfiles.add(
- createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds));
+ MediaProfiles::CamcorderProfile* profile = createCamcorderProfile(
+ profiles->mCurrentCameraId, atts, profiles->mCameraIds);
+ if (profile != nullptr) {
+ profiles->mCamcorderProfiles.add(profile);
+ }
} else if (strcmp("ImageEncoding", name) == 0) {
profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
}
diff --git a/media/libmedia/include/media/mediaplayer.h b/media/libmedia/include/media/mediaplayer.h
index 7c29e50..bb0d8ad 100644
--- a/media/libmedia/include/media/mediaplayer.h
+++ b/media/libmedia/include/media/mediaplayer.h
@@ -207,7 +207,8 @@
public virtual IMediaDeathNotifier
{
public:
- MediaPlayer(const std::string opPackageName = "");
+ MediaPlayer();
+ MediaPlayer(const std::string opPackageName);
~MediaPlayer();
void died();
void disconnect();
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 6079a2d..f1e48ad 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -41,6 +41,10 @@
using media::VolumeShaper;
+MediaPlayer::MediaPlayer() : MediaPlayer("" /*opPackageName*/)
+{
+}
+
MediaPlayer::MediaPlayer(const std::string opPackageName) : mOpPackageName(opPackageName)
{
ALOGV("constructor");
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 7897959..a7344de 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1663,7 +1663,7 @@
Size videoSize;
videoSize.width = mVideoWidth;
videoSize.height = mVideoHeight;
- if (mCaptureFpsEnable) {
+ if (mCaptureFpsEnable && mCaptureFps != mFrameRate) {
if (!(mCaptureFps > 0.)) {
ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps);
return BAD_VALUE;
@@ -1811,6 +1811,7 @@
preferBFrames = false;
tsLayers = 2; // use at least two layers as resulting video will likely be sped up
} else if (mCaptureFps > maxPlaybackFps) { // slow-mo
+ format->setInt32("high-frame-rate", 1);
maxPlaybackFps = mCaptureFps; // assume video will be played back at full capture speed
preferBFrames = false;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index c1c4b55..8a81ef1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2350,9 +2350,6 @@
void NuPlayer::performReset() {
ALOGV("performReset");
- CHECK(mAudioDecoder == NULL);
- CHECK(mVideoDecoder == NULL);
-
updatePlaybackTimer(true /* stopping */, "performReset");
updateRebufferingTimer(true /* stopping */, true /* exiting */);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 8e480bf..47881cc 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5294,9 +5294,7 @@
err = mOMXNode->getParameter(
(OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation,
&presentation, sizeof(presentation));
- if (err != OK) {
- return err;
- }
+ if (err == OK) {
notify->setInt32("aac-encoded-target-level",
presentation.nEncodedTargetLevel);
notify->setInt32("aac-drc-cut-level", presentation.nDrcCut);
@@ -5309,6 +5307,7 @@
notify->setInt32("aac-drc-album-mode", presentation.nDrcAlbumMode);
notify->setInt32("aac-drc-output-loudness",
presentation.nDrcOutputLoudness);
+ }
}
}
break;
@@ -7995,6 +7994,7 @@
// don't bother component if we don't have vendor extensions as they may not have implemented
// the android vendor extension support, which will lead to unnecessary OMX failure logs.
if (vendorKeys.empty()) {
+ mVendorExtensionsStatus = kExtensionsNone;
return OK;
}
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 9b3f420..be3fde8 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -162,6 +162,10 @@
return OMX_COLOR_FormatAndroidOpaque;
}
+ if (!strcmp(colorFormat, "YVU420SemiPlanar")) {
+ return OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
+ }
+
ALOGE("Uknown color format (%s), please add it to "
"CameraSource::getColorFormat", colorFormat);
@@ -338,6 +342,12 @@
return OK;
}
+static int32_t getHighSpeedFrameRate(const CameraParameters& params) {
+ const char* hsr = params.get("video-hsr");
+ int32_t rate = (hsr != NULL && strncmp(hsr, "off", 3)) ? strtol(hsr, NULL, 10) : 0;
+ return std::min(rate, 240);
+}
+
/*
* Configure the camera to use the requested video size
* (width and height) and/or frame rate. If both width and
@@ -385,11 +395,15 @@
}
if (frameRate != -1) {
- CHECK(frameRate > 0 && frameRate <= 120);
+ CHECK(frameRate > 0 && frameRate <= 240);
const char* supportedFrameRates =
params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
CHECK(supportedFrameRates != NULL);
ALOGV("Supported frame rates: %s", supportedFrameRates);
+ if (getHighSpeedFrameRate(*params)) {
+ ALOGI("Use default 30fps for HighSpeed %dfps", frameRate);
+ frameRate = 30;
+ }
char buf[4];
snprintf(buf, 4, "%d", frameRate);
if (strstr(supportedFrameRates, buf) == NULL) {
@@ -491,6 +505,8 @@
ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
return UNKNOWN_ERROR;
}
+ int32_t highSpeedRate = getHighSpeedFrameRate(params);
+ frameRateActual = highSpeedRate ? highSpeedRate : frameRateActual;
// Check the actual video frame rate against the target/requested
// video frame rate.
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index e0a6eb3..a00a178 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -298,7 +298,8 @@
// The first 2 output frames from the encoder are: decoder specific info and
// the compressed video frame data for the first input video frame.
if (mNumFramesEncoded >= 1 && *timestampUs <
- (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) {
+ (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs) &&
+ (mTimeBetweenFrameCaptureUs > mTimeBetweenTimeLapseVideoFramesUs + 1)) {
// Skip all frames from last encoded frame until
// sufficient time (mTimeBetweenFrameCaptureUs) has passed.
// Tell the camera to release its recording frame and return.
@@ -313,6 +314,12 @@
mLastTimeLapseFrameRealTimestampUs = *timestampUs;
*timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+ // Update start-time once the captured-time reaches the expected start-time.
+ // Not doing so will result in CameraSource always dropping frames since
+ // updated-timestamp will never intersect start-timestamp
+ if ((mNumFramesReceived == 0 && mLastTimeLapseFrameRealTimestampUs >= mStartTimeUs)) {
+ mStartTimeUs = *timestampUs;
+ }
return false;
}
return false;
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index c284ef7..1b3816d 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -111,8 +111,9 @@
}
}
- int finalUsage = usage | consumerUsage;
- ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage);
+ uint64_t finalUsage = (usage | consumerUsage) & 0xffffffffLL;
+ ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#" PRIx64,
+ usage, consumerUsage, finalUsage);
err = native_window_set_usage(nativeWindow, finalUsage);
if (err != NO_ERROR) {
ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
@@ -126,7 +127,7 @@
return err;
}
- ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x",
+ ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#" PRIx64,
nativeWindow, width, height, format, rotation, finalUsage);
return NO_ERROR;
}
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 8698d33..9e2a339 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -1,5 +1,6 @@
cc_defaults {
name: "libstagefright_bufferqueue-defaults",
+ defaults: ["stagefright_qcom_legacy_defaults"],
double_loadable: true,
srcs: [
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index cff14ac..d031e91 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -891,11 +891,13 @@
return UNKNOWN_ERROR;
}
+#ifndef QCOM_BSP_LEGACY
if ((android_dataspace)item.mDataspace != mLastDataspace) {
onDataspaceChanged_l(
item.mDataspace,
(android_pixel_format)item.mBuffer->getGraphicBuffer()->format);
}
+#endif
std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer;
// use a GraphicBuffer for now as component is using GraphicBuffers to hold references
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 78b4f19..a049fc5 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -1,5 +1,6 @@
cc_library_shared {
name: "libstagefright_omx",
+ defaults: ["stagefright_qcom_legacy_defaults"],
vendor_available: true,
vndk: {
enabled: true,
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index ac42373..d996e1a 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -453,7 +453,11 @@
mGraphicBufferEnabled[0] = false;
mGraphicBufferEnabled[1] = false;
mIsSecure = AString(name).endsWith(".secure");
+#ifdef QCOM_BSP_LEGACY
+ mLegacyAdaptiveExperiment = true;
+#else
mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled("legacy-adaptive");
+#endif
}
OMXNodeInstance::~OMXNodeInstance() {
@@ -580,6 +584,10 @@
break;
}
+ if (mActiveBuffers.size() > 0) {
+ freeActiveBuffers();
+ }
+
Mutex::Autolock _l(mLock);
status_t err = mOwner->freeNode(this);
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index afca7c4..1759ff6 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -11,6 +11,9 @@
cc_binary {
name: "mediaserver",
+ defaults: [
+ "camera_in_mediaserver_defaults",
+ ],
srcs: ["main_mediaserver.cpp"],
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 316732b..1621533 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -27,6 +27,10 @@
#include "RegisterExtensions.h"
// from LOCAL_C_INCLUDES
+#ifdef NO_CAMERA_SERVER
+#include "CameraService.h"
+#include <hidl/HidlTransportSupport.h>
+#endif
#include "MediaPlayerService.h"
#include "ResourceManagerService.h"
@@ -36,12 +40,20 @@
{
signal(SIGPIPE, SIG_IGN);
+#ifdef NO_CAMERA_SERVER
+ // Set 3 threads for HIDL calls
+ hardware::configureRpcThreadpool(3, /*willjoin*/ false);
+#endif
+
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
+#ifdef NO_CAMERA_SERVER
+ CameraService::instantiate();
+#endif
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
ProcessState::self()->startThreadPool();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 764fdc3..39fb5f3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -25,6 +25,7 @@
#include "Configuration.h"
#include <dirent.h>
#include <math.h>
+#include <stdio.h>
#include <signal.h>
#include <string>
#include <sys/time.h>
@@ -863,6 +864,15 @@
output.portId = portId;
if (lStatus == NO_ERROR) {
+
+ // set volume
+ String8 trackCreatorPackage = track->getPackageName();
+ if (!trackCreatorPackage.isEmpty() && mAppTrackDataConfigs.find(trackCreatorPackage) != mAppTrackDataConfigs.end()) {
+ AppTrackData config = mAppTrackDataConfigs[trackCreatorPackage];
+ track->setAppMute(config.muted);
+ track->setAppVolume(config.volume);
+ }
+
// Connect secondary outputs. Failure on a secondary output must not imped the primary
// Any secondary output setup failure will lead to a desync between the AP and AF until
// the track is destroyed.
@@ -1725,6 +1735,77 @@
return 0;
}
+status_t AudioFlinger::listAppTrackDatas(unsigned int *num, AppTrackData *vols)
+{
+ if (num == NULL || (*num != 0 && vols == NULL)) {
+ return BAD_VALUE;
+ }
+ std::set<AppTrackData> volSet;
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i);
+ thread->listAppTrackDatas(volSet);
+ }
+
+ if (vols == NULL || *num == 0) {
+ *num = volSet.size();
+ } else {
+ if (*num > volSet.size()) {
+ *num = volSet.size();
+ }
+ size_t written = 0;
+ for (AppTrackData vol : volSet) {
+ if (written >= *num) break;
+ strcpy(vols[written].packageName, vol.packageName);
+ vols[written].muted = vol.muted;
+ vols[written].active = vol.active;
+ vols[written++].volume = vol.volume;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::setAppVolume(const String8& packageName, const float value)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ t->setAppVolume(packageName, value);
+ }
+
+ if (mAppTrackDataConfigs.find(packageName) == mAppTrackDataConfigs.end()) {
+ AppTrackData vol;
+ strcpy(vol.packageName, packageName.c_str());
+ vol.volume = value;
+ vol.muted = false;
+ mAppTrackDataConfigs[packageName] = vol;
+ } else {
+ mAppTrackDataConfigs[packageName].volume = value;
+ }
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::setAppMute(const String8& packageName, const bool value)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ t->setAppMute(packageName, value);
+ }
+
+ if (mAppTrackDataConfigs.find(packageName) == mAppTrackDataConfigs.end()) {
+ AppTrackData vol;
+ strcpy(vol.packageName, packageName.c_str());
+ vol.volume = 1.0f;
+ vol.muted = value;
+ mAppTrackDataConfigs[packageName] = vol;
+ } else {
+ mAppTrackDataConfigs[packageName].muted = value;
+ }
+ return NO_ERROR;
+}
+
status_t AudioFlinger::setVoiceVolume(float value)
{
status_t ret = initCheck();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 20f561e..324226b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -106,6 +106,7 @@
class AudioMixer;
class AudioBuffer;
class AudioResampler;
+class AppTrackData;
class DeviceHalInterface;
class DevicesFactoryHalCallback;
class DevicesFactoryHalInterface;
@@ -330,6 +331,14 @@
Mutex mUnregisteredWritersLock;
public:
+ status_t setAppVolume(const String8& packageName, const float value);
+ status_t setAppMute(const String8& packageName, const bool value);
+ status_t listAppTrackDatas(unsigned int *num, AppTrackData *vols);
+
+private:
+ std::map<String8, AppTrackData> mAppTrackDataConfigs;
+
+public:
class SyncEvent;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 3dfeb83..ff1f9ac 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -2017,6 +2017,10 @@
{
Mutex::Autolock _l(mLock);
clearInputBuffer_l();
+
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ mEffects[i]->reset_l();
+ }
}
// Must be called with EffectChain::mLock locked
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a2df29b..918b814 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -136,10 +136,17 @@
sp<media::VolumeShaper::State> getVolumeShaperState(int id);
sp<media::VolumeHandler> getVolumeHandler() { return mVolumeHandler; }
/** Set the computed normalized final volume of the track.
- * !masterMute * masterVolume * streamVolume * averageLRVolume */
+ * !masterMute * !appMuted * masterVolume * streamVolume * averageLRVolume * appVolume */
void setFinalVolume(float volume);
float getFinalVolume() const { return mFinalVolume; }
+ void setAppVolume(float volume);
+ float getAppVolume() const { return mAppVolume; }
+ void setAppMute(bool val);
+ bool isAppMuted() { return mAppMuted; }
+
+ String8 getPackageName() const { return mPackageName; }
+
/** @return true if the track has changed (metadata or volume) since
* the last time this function was called,
* true if this function was never called since the track creation,
@@ -288,6 +295,8 @@
for (auto& tp : mTeePatches) { f(tp.patchTrack); }
};
+ String8 mPackageName;
+
// The following fields are only for fast tracks, and should be in a subclass
int mFastIndex; // index within FastMixerState::mFastTracks[];
// either mFastIndex == -1 if not isFastTrack()
@@ -300,7 +309,9 @@
volatile float mCachedVolume; // combined master volume and stream type volume;
// 'volatile' means accessed without lock or
// barrier, but is read/written atomically
- float mFinalVolume; // combine master volume, stream type volume and track volume
+ float mFinalVolume; // combine master volume, stream type volume and track volume and relative volume
+ float mAppVolume; // for separate process volume control
+ bool mAppMuted;
sp<AudioTrackServerProxy> mAudioTrackServerProxy;
bool mResumeToStopping; // track was paused in stopping state.
bool mFlushHwPending; // track requests for thread flush
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1d0147d..419a7cb 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -23,9 +23,11 @@
#include "Configuration.h"
#include <math.h>
#include <fcntl.h>
+#include <stdio.h>
#include <memory>
#include <sstream>
#include <string>
+#include <set>
#include <linux/futex.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -2405,6 +2407,43 @@
return index;
}
+void AudioFlinger::PlaybackThread::listAppTrackDatas(std::set<AppTrackData> &cup)
+{
+ Mutex::Autolock _l(mLock);
+ for (sp<Track> track : mTracks) {
+ if (!track->getPackageName().isEmpty()) {
+ AppTrackData av;
+ strcpy(av.packageName, track->getPackageName().c_str());
+ av.muted = track->isAppMuted();
+ av.volume = track->getAppVolume();
+ av.active = mActiveTracks.indexOf(track) >= 0;
+ cup.insert(av);
+ }
+ }
+}
+
+status_t AudioFlinger::PlaybackThread::setAppVolume(const String8& packageName, const float value)
+{
+ Mutex::Autolock _l(mLock);
+ for (sp<Track> track : mTracks) {
+ if (packageName == track->getPackageName()) {
+ track->setAppVolume(value);
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::setAppMute(const String8& packageName, const bool value)
+{
+ Mutex::Autolock _l(mLock);
+ for (sp<Track> track : mTracks) {
+ if (packageName == track->getPackageName()) {
+ track->setAppMute(value);
+ }
+ }
+ return NO_ERROR;
+}
+
uint32_t AudioFlinger::PlaybackThread::correctLatency_l(uint32_t latency) const
{
return latency;
@@ -5003,10 +5042,10 @@
}
sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
float volume;
- if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
+ if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute || track->isAppMuted()) {
volume = 0.f;
} else {
- volume = masterVolume * mStreamTypes[track->streamType()].volume;
+ volume = masterVolume * mStreamTypes[track->streamType()].volume * track->getAppVolume();
}
handleVoipVolume_l(&volume);
@@ -5163,13 +5202,13 @@
uint32_t vl, vr; // in U8.24 integer format
float vlf, vrf, vaf; // in [0.0, 1.0] float format
// read original volumes with volume control
- float v = masterVolume * mStreamTypes[track->streamType()].volume;
+ float v = masterVolume * mStreamTypes[track->streamType()].volume * track->getAppVolume();
// Always fetch volumeshaper volume to ensure state is updated.
const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
const float vh = track->getVolumeHandler()->getVolume(
track->mAudioTrackServerProxy->framesReleased()).first;
- if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
+ if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted() || track->isAppMuted()) {
v = 0;
}
@@ -5723,11 +5762,12 @@
proxy->framesReleased());
mVolumeShaperActive = shaperActive;
- if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
+ if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted() || track->isAppMuted()) {
left = right = 0;
} else {
float typeVolume = mStreamTypes[track->streamType()].volume;
- const float v = mMasterVolume * typeVolume * shaperVolume;
+ float appVolume = track->getAppVolume();
+ const float v = mMasterVolume * typeVolume * shaperVolume * appVolume;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
left = float_from_gain(gain_minifloat_unpack_left(vlr));
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 6b33ad5..b8356d3 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -845,6 +845,10 @@
void setVolumeForOutput_l(float left, float right) const override;
+ status_t setAppVolume(const String8& packageName, const float value);
+ status_t setAppMute(const String8& packageName, const bool muted);
+ void listAppTrackDatas(std::set<AppTrackData> &cup);
+
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
audio_stream_type_t streamType,
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f286d8a..1f4f622 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -567,6 +567,20 @@
ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
__func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
+ /* get package name */
+ PermissionController permissionController;
+ Vector<String16> packages;
+ permissionController.getPackagesForUid(uid, packages);
+ if (!packages.isEmpty()) {
+ mPackageName = String8(packages[0]);
+ } else {
+ mPackageName = "";
+ }
+
+ /* init app volume */
+ mAppMuted = false;
+ mAppVolume = 1.0f;
+
if (mCblk == NULL) {
return;
}
@@ -1264,6 +1278,16 @@
}
}
+void AudioFlinger::PlaybackThread::Track::setAppVolume(float volume)
+{
+ mAppVolume = volume;
+}
+
+void AudioFlinger::PlaybackThread::Track::setAppMute(bool val)
+{
+ mAppMuted = val;
+}
+
void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
{
*backInserter++ = {
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 8d0e5db..a350f6c 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -421,6 +421,8 @@
// sessions to be preempted on modules that do not support sound trigger
// recognition concurrently with audio capture.
virtual void setSoundTriggerCaptureState(bool active) = 0;
+
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& streamInfo, bool added) = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 0537365..4047d76 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -35,7 +35,7 @@
// For mixed output and inputs, the policy will use max mixer sampling rates.
// Do not limit sampling rate otherwise
-#define SAMPLE_RATE_HZ_MAX 192000
+#define SAMPLE_RATE_HZ_MAX 384000
// Used when a client opens a capture stream, without specifying a desired sample rate.
#define SAMPLE_RATE_HZ_DEFAULT 48000
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 39d1140..daced38 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -305,6 +305,7 @@
DeviceVector mDevices; /**< current devices this output is routed to */
wp<AudioPolicyMix> mPolicyMix; // non NULL when used by a dynamic policy
+ audio_io_handle_t mIoHandle; // output handle
protected:
const sp<PolicyAudioPort> mPolicyAudioPort;
@@ -404,7 +405,6 @@
DeviceVector filterSupportedDevices(const DeviceVector &devices) const;
const sp<IOProfile> mProfile; // I/O profile this output derives from
- audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
audio_output_flags_t mFlags; //
sp<SwAudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index d6d472b..e61af6f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -40,7 +40,7 @@
AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
AudioPolicyClientInterface *clientInterface)
- : mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
+ : mIoHandle(AUDIO_IO_HANDLE_NONE), mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
{
if (mPolicyAudioPort.get() != nullptr) {
mPolicyAudioPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -278,7 +278,7 @@
SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile,
AudioPolicyClientInterface *clientInterface)
: AudioOutputDescriptor(profile, clientInterface),
- mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
+ mProfile(profile), mLatency(0),
mFlags((audio_output_flags_t)0),
mOutput1(0), mOutput2(0), mDirectOpenCount(0),
mDirectClientSession(AUDIO_SESSION_NONE)
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7f339dc..136013a 100755
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -39,6 +39,11 @@
audio_mode_t getPhoneState() const override { return mPhoneState; }
+ void setDpConnAndAllowedForVoice(bool connAndAllowed) override
+ {
+ mDpConnAndAllowedForVoice = connAndAllowed;
+ }
+
status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) override
{
mForceUse[usage] = config;
@@ -118,6 +123,11 @@
return is_state_in_call(getPhoneState());
}
+ inline bool getDpConnAndAllowedForVoice() const
+ {
+ return mDpConnAndAllowedForVoice;
+ }
+
VolumeSource toVolumeSource(audio_stream_type_t stream) const
{
return static_cast<VolumeSource>(getVolumeGroupForStreamType(stream));
@@ -135,6 +145,8 @@
VolumeGroupMap mVolumeGroups;
LastRemovableMediaDevices mLastRemovableMediaDevices;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */
+ /* if display-port is connected and can be used for voip/voice */
+ bool mDpConnAndAllowedForVoice;
/** current forced use configuration. */
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index dfb20b5..650c15f 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -73,6 +73,14 @@
virtual audio_mode_t getPhoneState() const = 0;
/**
+ * Set whether display-port is connected and is allowed to be used
+ * for voice usecases
+ *
+ * @param[in] connAndAllowed: if display-port is connected and can be used
+ */
+ virtual void setDpConnAndAllowedForVoice(bool connAndAllowed) = 0;
+
+ /**
* Set Force Use config for a given usage.
*
* @param[in] usage for which a configuration shall be forced.
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index b14d2bb..37f1a98 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -250,6 +250,10 @@
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
if (!devices.isEmpty()) break;
}
+ if (getDpConnAndAllowedForVoice() && isInCall()) {
+ devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
+ if (!devices.isEmpty()) break;
+ }
devices = availableOutputDevices.getFirstDevicesFromTypes({
AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
@@ -340,6 +344,16 @@
}
}
}
+ // if display-port is connected and being used in voice usecase,
+ // play ringtone over speaker and display-port
+ if ((strategy == STRATEGY_SONIFICATION) && getDpConnAndAllowedForVoice()) {
+ DeviceVector devices2 = availableOutputDevices.getDevicesFromType(
+ AUDIO_DEVICE_OUT_AUX_DIGITAL);
+ if (!devices2.isEmpty()) {
+ devices.add(devices2);
+ break;
+ }
+ }
// The second device used for sonification is the same as the device used by media strategy
FALLTHROUGH_INTENDED;
@@ -371,6 +385,13 @@
// FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
case STRATEGY_REROUTING:
case STRATEGY_MEDIA: {
+ if (isInCall() && devices.isEmpty()) {
+ // when in call, get the device for Phone strategy
+ devices = getDevicesForStrategyInt(
+ STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
+ break;
+ }
+
DeviceVector devices2;
if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD)
@@ -407,7 +428,8 @@
getLastRemovableMediaDevices(GROUP_WIRED));
}
}
- if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
+ if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION) &&
+ (devices.isEmpty())) {
// no sonification on aux digital (e.g. HDMI)
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
}
@@ -416,6 +438,12 @@
devices2 = availableOutputDevices.getDevicesFromType(
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
}
+ if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION) &&
+ (devices.isEmpty())) {
+ // no sonification on WFD sink
+ devices2 = availableOutputDevices.getDevicesFromType(
+ AUDIO_DEVICE_OUT_PROXY);
+ }
if (devices2.isEmpty()) {
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index b588f89..b2a670e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -506,7 +506,7 @@
// when a device is disconnected, checks if an output is not used any more and
// returns its handle if any.
// transfers the audio tracks and effects from one output thread to another accordingly.
- status_t checkOutputsForDevice(const sp<DeviceDescriptor>& device,
+ virtual status_t checkOutputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs);
@@ -539,7 +539,7 @@
* Must be called before updateDevicesAndOutputs()
* @param attr to be considered
*/
- void checkOutputForAttributes(const audio_attributes_t &attr);
+ virtual void checkOutputForAttributes(const audio_attributes_t &attr);
bool followsSameRouting(const audio_attributes_t &lAttr,
const audio_attributes_t &rAttr) const;
@@ -685,10 +685,10 @@
uint32_t delayMs);
bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const;
- status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
+ virtual status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
const sp<TrackClientDescriptor>& client,
uint32_t *delayMs);
- status_t stopSource(const sp<SwAudioOutputDescriptor>& outputDesc,
+ virtual status_t stopSource(const sp<SwAudioOutputDescriptor>& outputDesc,
const sp<TrackClientDescriptor>& client);
void clearAudioPatches(uid_t uid);
@@ -787,7 +787,7 @@
std::unordered_set<audio_format_t> mManualSurroundFormats;
std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
-private:
+protected:
void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
// Add or remove AC3 DTS encodings based on user preferences.
@@ -840,7 +840,7 @@
std::vector<sp<AudioPolicyMix>> *secondaryMixes,
output_type_t *outputType);
// internal method to return the output handle for the given device and format
- audio_io_handle_t getOutputForDevices(
+ virtual audio_io_handle_t getOutputForDevices(
const DeviceVector &devices,
audio_session_t session,
audio_stream_type_t stream,
@@ -885,7 +885,7 @@
bool isValidAttributes(const audio_attributes_t *paa);
// Called by setDeviceConnectionState().
- status_t setDeviceConnectionStateInt(audio_devices_t deviceType,
+ virtual status_t setDeviceConnectionStateInt(audio_devices_t deviceType,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name,
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 9fa7a53..177c3cb 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -236,6 +236,13 @@
mAudioPolicyService->onAudioVolumeGroupChanged(group, flags);
}
+void AudioPolicyService::AudioPolicyClient::onOutputSessionEffectsUpdate(
+ sp<AudioSessionInfo>& info, bool added)
+{
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, added);
+}
+
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index b738633..a5e5bb8 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -31,6 +31,7 @@
#include <utils/SortedVector.h>
#include <cutils/config_utils.h>
#include <binder/IPCThreadState.h>
+#include "AudioPolicyService.h"
#include "AudioPolicyEffects.h"
namespace android {
@@ -39,7 +40,8 @@
// AudioPolicyEffects Implementation
// ----------------------------------------------------------------------------
-AudioPolicyEffects::AudioPolicyEffects()
+AudioPolicyEffects::AudioPolicyEffects(AudioPolicyService *audioPolicyService) :
+ mAudioPolicyService(audioPolicyService)
{
status_t loadResult = loadAudioEffectXmlConfig();
if (loadResult == NO_ERROR) {
@@ -238,6 +240,8 @@
{
status_t status = NO_ERROR;
+ ALOGV("addOutputSessionEffects %d", audioSession);
+
Mutex::Autolock _l(mLock);
// create audio processors according to stream
// FIXME: should we have specific post processing settings for internal streams?
@@ -245,6 +249,22 @@
if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
stream = AUDIO_STREAM_MUSIC;
}
+
+ // send the streaminfo notification only once
+ ssize_t sidx = mOutputAudioSessionInfo.indexOfKey(audioSession);
+ if (sidx >= 0) {
+ // AudioSessionInfo is existing and we just need to increase ref count
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(sidx);
+ info->mRefCount++;
+
+ if (info->mRefCount == 1) {
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, true);
+ }
+ ALOGV("addOutputSessionEffects(): session info %d refCount=%d", audioSession, info->mRefCount);
+ } else {
+ ALOGV("addOutputSessionEffects(): no output stream info found for stream");
+ }
+
ssize_t index = mOutputStreams.indexOfKey(stream);
if (index < 0) {
ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
@@ -290,6 +310,86 @@
return status;
}
+status_t AudioPolicyEffects::releaseOutputAudioSessionInfo(audio_io_handle_t /* output */,
+ audio_stream_type_t stream,
+ audio_session_t session)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session);
+ if (idx >= 0) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(idx);
+ if (info->mRefCount == 0) {
+ mOutputAudioSessionInfo.removeItemsAt(idx);
+ }
+ ALOGV("releaseOutputAudioSessionInfo() sessionId=%d refcount=%d",
+ session, info->mRefCount);
+ } else {
+ ALOGV("releaseOutputAudioSessionInfo() no session info found");
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyEffects::updateOutputAudioSessionInfo(audio_io_handle_t /* output */,
+ audio_stream_type_t stream,
+ audio_session_t session,
+ audio_output_flags_t flags,
+ const audio_config_t *config, uid_t uid)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ // TODO: Handle other stream types based on client registration
+ if (stream != AUDIO_STREAM_MUSIC) {
+ return NO_ERROR;
+ }
+
+ // update AudioSessionInfo. This is used in the stream open/close path
+ // to notify userspace applications about session creation and
+ // teardown, allowing the app to make decisions about effects for
+ // a particular stream. This is independent of the current
+ // output_session_processing feature which forcibly attaches a
+ // static list of effects to a stream.
+ ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session);
+ sp<AudioSessionInfo> info;
+ if (idx < 0) {
+ info = new AudioSessionInfo(session, stream, flags, config->channel_mask, uid);
+ mOutputAudioSessionInfo.add(session, info);
+ } else {
+ // the streaminfo may actually change
+ info = mOutputAudioSessionInfo.valueAt(idx);
+ info->mFlags = flags;
+ info->mChannelMask = config->channel_mask;
+ }
+
+ ALOGV("updateOutputAudioSessionInfo() sessionId=%d, flags=0x%x, channel_mask=0x%x uid=%d refCount=%d",
+ info->mSessionId, info->mFlags, info->mChannelMask, info->mUid, info->mRefCount);
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyEffects::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ ALOGV("listAudioSessions() streams %d", streams);
+
+ for (unsigned int i = 0; i < mOutputAudioSessionInfo.size(); i++) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(i);
+ if (streams == -1 || info->mStream == streams) {
+ sessions.push_back(info);
+ }
+ }
+
+ return NO_ERROR;
+}
+
status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t audioSession)
@@ -299,7 +399,19 @@
(void) stream; // argument not used for now
Mutex::Autolock _l(mLock);
- ssize_t index = mOutputSessions.indexOfKey(audioSession);
+ ssize_t index = mOutputAudioSessionInfo.indexOfKey(audioSession);
+ if (index >= 0) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(index);
+ info->mRefCount--;
+ if (info->mRefCount == 0) {
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, false);
+ }
+ ALOGV("releaseOutputSessionEffects(): session=%d refCount=%d", info->mSessionId, info->mRefCount);
+ } else {
+ ALOGV("releaseOutputSessionEffects: no stream info was attached to this stream");
+ }
+
+ index = mOutputSessions.indexOfKey(audioSession);
if (index < 0) {
ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
return NO_ERROR;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 81c728d..137e37f 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -31,6 +31,8 @@
namespace android {
+class AudioPolicyService;
+
// ----------------------------------------------------------------------------
// AudioPolicyEffects class
@@ -44,7 +46,7 @@
// The constructor will parse audio_effects.conf
// First it will look whether vendor specific file exists,
// otherwise it will parse the system default file.
- AudioPolicyEffects();
+ AudioPolicyEffects(AudioPolicyService *audioPolicyService);
virtual ~AudioPolicyEffects();
// NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
@@ -106,6 +108,19 @@
// Remove the default stream effect from wherever it's attached.
status_t removeStreamDefaultEffect(audio_unique_id_t id);
+ status_t updateOutputAudioSessionInfo(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t audioSession,
+ audio_output_flags_t flags,
+ const audio_config_t *config, uid_t uid);
+
+ status_t releaseOutputAudioSessionInfo(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t audioSession);
+
+ status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions);
+
private:
void initDefaultDeviceEffects();
@@ -276,6 +291,11 @@
* We must store the reference of the furture garantee real asynchronous operation.
*/
std::future<void> mDefaultDeviceEffectFuture;
+
+ // Stream info for session events
+ KeyedVector< audio_session_t, sp<AudioSessionInfo> > mOutputAudioSessionInfo;
+
+ AudioPolicyService *mAudioPolicyService;
};
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index df27f6e..0b15713 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -235,61 +235,72 @@
}
ALOGV("%s()", __func__);
- Mutex::Autolock _l(mLock);
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
- const uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (!isAudioServerOrMediaServerUid(callingUid) || uid == (uid_t)-1) {
- ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
- "%s uid %d tried to pass itself off as %d", __func__, callingUid, uid);
- uid = callingUid;
- }
- if (!mPackageManager.allowPlaybackCapture(uid)) {
- attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
- }
- if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
- && !bypassInterruptionPolicyAllowed(pid, uid)) {
- attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
- }
- AutoCallerClear acc;
- AudioPolicyInterface::output_type_t outputType;
- result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
- config,
- &flags, selectedDeviceId, portId,
- secondaryOutputs,
- &outputType);
-
- // FIXME: Introduce a way to check for the the telephony device before opening the output
- if (result == NO_ERROR) {
- // enforce permission (if any) required for each type of input
- switch (outputType) {
- case AudioPolicyInterface::API_OUTPUT_LEGACY:
- break;
- case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
- if (!modifyPhoneStateAllowed(pid, uid)) {
- ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
- __func__, uid);
- result = PERMISSION_DENIED;
- }
- break;
- case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
- if (!modifyAudioRoutingAllowed(pid, uid)) {
- ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
- __func__, uid);
- result = PERMISSION_DENIED;
- }
- break;
- case AudioPolicyInterface::API_OUTPUT_INVALID:
- default:
- LOG_ALWAYS_FATAL("%s() encountered an invalid output type %d",
- __func__, (int)outputType);
+ const uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ if (!isAudioServerOrMediaServerUid(callingUid) || uid == (uid_t)-1) {
+ ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
+ "%s uid %d tried to pass itself off as %d", __func__, callingUid, uid);
+ uid = callingUid;
}
+ if (!mPackageManager.allowPlaybackCapture(uid)) {
+ attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
+ }
+ if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
+ && !bypassInterruptionPolicyAllowed(pid, uid)) {
+ attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
+ }
+ AutoCallerClear acc;
+ AudioPolicyInterface::output_type_t outputType;
+ result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+ config,
+ &flags, selectedDeviceId, portId,
+ secondaryOutputs,
+ &outputType);
+
+ // FIXME: Introduce a way to check for the the telephony device before opening the output
+ if (result == NO_ERROR) {
+ // enforce permission (if any) required for each type of input
+ switch (outputType) {
+ case AudioPolicyInterface::API_OUTPUT_LEGACY:
+ break;
+ case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
+ if (!modifyPhoneStateAllowed(pid, uid)) {
+ ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
+ __func__, uid);
+ result = PERMISSION_DENIED;
+ }
+ break;
+ case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
+ if (!modifyAudioRoutingAllowed(pid, uid)) {
+ ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
+ __func__, uid);
+ result = PERMISSION_DENIED;
+ }
+ break;
+ case AudioPolicyInterface::API_OUTPUT_INVALID:
+ default:
+ LOG_ALWAYS_FATAL("%s() encountered an invalid output type %d",
+ __func__, (int)outputType);
+ }
+ }
+
+ if (result == NO_ERROR) {
+ sp <AudioPlaybackClient> client =
+ new AudioPlaybackClient(*attr, *output, uid, pid, session, *portId, *selectedDeviceId, *stream);
+ mAudioPlaybackClients.add(*portId, client);
+ }
+
+ audioPolicyEffects = mAudioPolicyEffects;
}
- if (result == NO_ERROR) {
- sp <AudioPlaybackClient> client =
- new AudioPlaybackClient(*attr, *output, uid, pid, session, *portId, *selectedDeviceId, *stream);
- mAudioPlaybackClients.add(*portId, client);
+ if (result == NO_ERROR && audioPolicyEffects != 0) {
+ audioPolicyEffects->updateOutputAudioSessionInfo(*output, *stream,
+ session, flags, config, uid);
}
+
return result;
}
@@ -393,11 +404,20 @@
audioPolicyEffects->releaseOutputSessionEffects(
client->io, client->stream, client->session);
}
- Mutex::Autolock _l(mLock);
- mAudioPlaybackClients.removeItem(portId);
+ {
+ Mutex::Autolock _l(mLock);
+ mAudioPlaybackClients.removeItem(portId);
- // called from internal thread: no need to clear caller identity
- mAudioPolicyManager->releaseOutput(portId);
+ audioPolicyEffects = mAudioPolicyEffects;
+
+ // called from internal thread: no need to clear caller identity
+ mAudioPolicyManager->releaseOutput(portId);
+ }
+
+ if (audioPolicyEffects != 0) {
+ audioPolicyEffects->releaseOutputAudioSessionInfo(client->io,
+ client->stream, client->session);
+ }
}
status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
@@ -1534,4 +1554,24 @@
return NO_ERROR;
}
+status_t AudioPolicyService::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+
+ if (audioPolicyEffects != 0) {
+ return audioPolicyEffects->listAudioSessions(streams, sessions);
+ }
+
+ // no errors here if effects are not available
+ return NO_ERROR;
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a6e8989..fbd7614 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -78,7 +78,7 @@
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
}
// load audio processing modules
- sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
+ sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects(this);
sp<UidPolicy> uidPolicy = new UidPolicy(this);
sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
{
@@ -293,6 +293,21 @@
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
+void AudioPolicyService::onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
+{
+ ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)",
+ info->mStream, info->mSessionId, added);
+ mOutputCommandThread->effectSessionUpdateCommand(info, added);
+}
+
+void AudioPolicyService::doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(info, added);
+ }
+}
+
AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
const sp<IAudioPolicyServiceClient>& client,
uid_t uid,
@@ -337,6 +352,13 @@
}
}
+void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate(
+ sp<AudioSessionInfo>& info, bool added)
+{
+ if (mAudioPolicyServiceClient != 0) {
+ mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(info, added);
+ }
+}
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
const String8& regId, int32_t state)
@@ -1366,6 +1388,20 @@
svc->doOnNewAudioModulesAvailable();
mLock.lock();
} break;
+ case EFFECT_SESSION_UPDATE: {
+ EffectSessionUpdateData *data =
+ (EffectSessionUpdateData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing effect session update %d %d %d",
+ data->mAudioSessionInfo->mStream, data->mAudioSessionInfo->mSessionId,
+ data->mAdded);
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnOutputSessionEffectsUpdate(data->mAudioSessionInfo, data->mAdded);
+ mLock.lock();
+ } break;
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -1662,6 +1698,20 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
+ sp<AudioSessionInfo>& streamInfo, bool added)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = EFFECT_SESSION_UPDATE;
+ EffectSessionUpdateData *data = new EffectSessionUpdateData();
+ data->mAudioSessionInfo = streamInfo;
+ data->mAdded = added;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)",
+ streamInfo->mStream, streamInfo->mSessionId, added);
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 869a963..fc61cce 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -288,6 +288,9 @@
status_t doStopOutput(audio_port_handle_t portId);
void doReleaseOutput(audio_port_handle_t portId);
+ virtual status_t listAudioSessions(audio_stream_type_t stream,
+ Vector< sp<AudioSessionInfo>>& sessions);
+
status_t clientCreateAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
int delayMs);
@@ -327,6 +330,9 @@
audio_session_t sessionId,
bool suspended);
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+ void doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+
private:
AudioPolicyService() ANDROID_API;
virtual ~AudioPolicyService();
@@ -475,6 +481,7 @@
RECORDING_CONFIGURATION_UPDATE,
SET_EFFECT_SUSPENDED,
AUDIO_MODULES_UPDATE,
+ EFFECT_SESSION_UPDATE,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -522,6 +529,8 @@
bool suspended);
void audioModulesUpdateCommand();
void insertCommand_l(AudioCommand *command, int delayMs = 0);
+ void effectSessionUpdateCommand(sp<AudioSessionInfo>& info, bool added);
+
private:
class AudioCommandData;
@@ -625,6 +634,12 @@
bool mSuspended;
};
+ class EffectSessionUpdateData : public AudioCommandData {
+ public:
+ sp<AudioSessionInfo> mAudioSessionInfo;
+ bool mAdded;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -743,6 +758,8 @@
void setSoundTriggerCaptureState(bool active) override;
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+
private:
AudioPolicyService *mAudioPolicyService;
};
@@ -771,6 +788,8 @@
audio_source_t source);
void setAudioPortCallbacksEnabled(bool enabled);
void setAudioVolumeGroupCallbacksEnabled(bool enabled);
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info,
+ bool added);
uid_t uid() {
return mUid;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 501d922..76fae25 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -18,6 +18,11 @@
cc_library_shared {
name: "libcameraservice",
+ defaults: [
+ "no_cameraserver_defaults",
+ "qti_camera_device_defaults",
+ "target_camera_needs_client_info_defaults",
+ ],
// Camera service source
@@ -127,7 +132,8 @@
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.5",
- "android.hardware.camera.device@3.6"
+ "android.hardware.camera.device@3.6",
+ "vendor.lineage.camera.motor@1.0"
],
static_libs: [
@@ -157,6 +163,5 @@
"-Werror",
"-Wno-ignored-qualifiers",
],
-
}
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index e629cdd..7e8cc5b 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -512,6 +512,22 @@
return device->setPreviewWindow(mSurface);
}
+static void notifyCallback(int32_t, int32_t, int32_t, void*) {
+ /* Empty */
+}
+
+static void dataCallback(int32_t, const sp<IMemory>&, camera_frame_metadata_t*, void*) {
+ /* Empty */
+}
+
+static void dataCallbackTimestamp(nsecs_t, int32_t, const sp<IMemory>&, void*) {
+ /* Empty */
+}
+
+static void dataCallbackTimestampBatch(int32_t, const std::vector<HandleTimestampMessage>&,
+ void*) {
+ /* Empty */
+}
status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
const String8& cameraId) {
sp<CameraHardwareInterface> device =
@@ -525,7 +541,8 @@
}
// need to set __get_memory in set_callbacks().
- device->setCallbacks(NULL, NULL, NULL, NULL, NULL);
+ device->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp,
+ dataCallbackTimestampBatch, this);
mParameters = device->getParameters();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e2fcb5a..ae9616b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -24,6 +24,10 @@
#include <cstring>
#include <ctime>
#include <string>
+#ifdef TARGET_NEEDS_CLIENT_INFO
+#include <iostream>
+#include <fstream>
+#endif
#include <sys/types.h>
#include <inttypes.h>
#include <pthread.h>
@@ -77,6 +81,8 @@
#include "utils/TagMonitor.h"
#include "utils/CameraThreadState.h"
+#include <vendor/lineage/camera/motor/1.0/ICameraMotor.h>
+
namespace {
const char* kPermissionServiceName = "permission";
}; // namespace anonymous
@@ -94,6 +100,7 @@
using hardware::camera::common::V1_0::TorchModeStatus;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
using hardware::camera2::utils::ConcurrentCameraIdCombination;
+using vendor::lineage::camera::motor::V1_0::ICameraMotor;
// ----------------------------------------------------------------------------
// Logging support -- this is for debugging only
@@ -252,8 +259,14 @@
proxyBinder->pingForUserUpdate();
}
-void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeStatus status,
- SystemCameraKind systemCameraKind) {
+void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeStatus status) {
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ status_t res = getSystemCameraKind(cameraId, &systemCameraKind);
+ if (res != OK) {
+ ALOGE("%s: Could not get system camera kind for camera id %s", __FUNCTION__,
+ cameraId.string());
+ return;
+ }
Mutex::Autolock lock(mStatusListenerLock);
for (auto& i : mListenerList) {
if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(),
@@ -347,7 +360,7 @@
Mutex::Autolock al(mTorchStatusMutex);
mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
- broadcastTorchModeStatus(id, TorchModeStatus::AVAILABLE_OFF, deviceKind);
+ broadcastTorchModeStatus(id, TorchModeStatus::AVAILABLE_OFF);
}
updateCameraNumAndIds();
@@ -508,19 +521,12 @@
void CameraService::onTorchStatusChanged(const String8& cameraId,
TorchModeStatus newStatus) {
- SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
- status_t res = getSystemCameraKind(cameraId, &systemCameraKind);
- if (res != OK) {
- ALOGE("%s: Could not get system camera kind for camera id %s", __FUNCTION__,
- cameraId.string());
- return;
- }
Mutex::Autolock al(mTorchStatusMutex);
- onTorchStatusChangedLocked(cameraId, newStatus, systemCameraKind);
+ onTorchStatusChangedLocked(cameraId, newStatus);
}
void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
- TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
+ TorchModeStatus newStatus) {
ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
__FUNCTION__, cameraId.string(), newStatus);
@@ -569,7 +575,7 @@
}
}
}
- broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
+ broadcastTorchModeStatus(cameraId, newStatus);
}
static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
@@ -963,7 +969,11 @@
Status CameraService::initializeShimMetadata(int cameraId) {
int uid = CameraThreadState::getCallingUid();
+#ifdef NO_CAMERA_SERVER
+ String16 internalPackageName("media");
+#else
String16 internalPackageName("cameraserver");
+#endif
String8 id = String8::format("%d", cameraId);
Status ret = Status::ok();
sp<Client> tmp = nullptr;
@@ -1044,7 +1054,9 @@
static bool isTrustedCallingUid(uid_t uid) {
switch (uid) {
case AID_MEDIA: // mediaserver
+#ifndef NO_CAMERA_SERVER
case AID_CAMERASERVER: // cameraserver
+#endif
case AID_RADIO: // telephony
return true;
default:
@@ -1177,6 +1189,7 @@
clientName8.string(), clientUid, clientPid, cameraId.string());
}
+#ifndef NO_CAMERA_SERVER
// Make sure the UID is in an active state to use the camera
if (!mUidPolicy->isUidActive(callingUid, String16(clientName8))) {
int32_t procState = mUidPolicy->getProcState(callingUid);
@@ -1188,6 +1201,7 @@
clientName8.string(), clientUid, clientPid, cameraId.string(),
callingUid, procState);
}
+#endif
// If sensor privacy is enabled then prevent access to the camera
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -1782,6 +1796,11 @@
} else {
// Otherwise, add client to active clients list
finishConnectLocked(client, partial);
+
+ sp<ICameraMotor> cameraMotor = ICameraMotor::getService();
+ if (cameraMotor != nullptr) {
+ cameraMotor->onConnect(cameraId.string());
+ }
}
} // lock is destroyed, allow further connect calls
@@ -2437,7 +2456,8 @@
ret = true;
}
}
-
+ //clear the evicted client list before acquring service lock again.
+ evicted.clear();
// Reacquire mServiceLock
mServiceLock.lock();
@@ -2849,6 +2869,11 @@
}
mDisconnected = true;
+ sp<ICameraMotor> cameraMotor = ICameraMotor::getService();
+ if (cameraMotor != nullptr) {
+ cameraMotor->onDisconnect(mCameraIdStr.string());
+ }
+
sCameraService->removeByClient(this);
sCameraService->logDisconnected(mCameraIdStr, mClientPid, String8(mClientPackageName));
sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
@@ -2883,6 +2908,10 @@
return mClientPackageName;
}
+bool CameraService::BasicClient::isFaceUnlockPackage() const {
+ std::string cpn = String8(mClientPackageName).string();
+ return cpn.compare("org.pixelexperience.faceunlock") == 0;
+}
int CameraService::BasicClient::getClientPid() const {
return mClientPid;
@@ -2943,7 +2972,7 @@
mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
String16("start camera ") + String16(mCameraIdStr));
- if (res == AppOpsManager::MODE_ERRORED) {
+ if (!isFaceUnlockPackage() && res == AppOpsManager::MODE_ERRORED) {
ALOGI("Camera %s: Access for \"%s\" has been revoked",
mCameraIdStr.string(), String8(mClientPackageName).string());
return PERMISSION_DENIED;
@@ -2951,7 +2980,7 @@
// If the calling Uid is trusted (a native service), the AppOpsManager could
// return MODE_IGNORED. Do not treat such case as error.
- if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
+ if (!isFaceUnlockPackage() && !mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
ALOGI("Camera %s: Access for \"%s\" has been restricted",
mCameraIdStr.string(), String8(mClientPackageName).string());
// Return the same error as for device policy manager rejection
@@ -2977,6 +3006,12 @@
// Notify listeners of camera open/close status
sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName);
+#ifdef TARGET_NEEDS_CLIENT_INFO
+ std::ofstream cpf("/data/misc/aosp/client_package_name");
+ std::string cpn = String8(mClientPackageName).string();
+ cpf << cpn;
+#endif
+
return OK;
}
@@ -3797,7 +3832,7 @@
TorchModeStatus::AVAILABLE_OFF :
TorchModeStatus::NOT_AVAILABLE;
if (torchStatus != newTorchStatus) {
- onTorchStatusChangedLocked(cameraId, newTorchStatus, deviceKind);
+ onTorchStatusChangedLocked(cameraId, newTorchStatus);
}
}
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 5c4c96b..a192202 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -295,6 +295,9 @@
// Override rotate-and-crop AUTO behavior
virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) = 0;
+ // Return if current package is face unlock
+ virtual bool isFaceUnlockPackage() const;
+
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
@@ -995,8 +998,7 @@
// handle torch mode status change and invoke callbacks. mTorchStatusMutex
// should be locked.
void onTorchStatusChangedLocked(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
- SystemCameraKind systemCameraKind);
+ hardware::camera::common::V1_0::TorchModeStatus newStatus);
// get a camera's torch status. mTorchStatusMutex should be locked.
status_t getTorchStatusLocked(const String8 &cameraId,
@@ -1085,8 +1087,7 @@
static void pingCameraServiceProxy();
void broadcastTorchModeStatus(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus status,
- SystemCameraKind systemCameraKind);
+ hardware::camera::common::V1_0::TorchModeStatus status);
void disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect);
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 892996c..43da23e 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -55,6 +55,9 @@
mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
mPlayShutterSound = true;
+
+ mLongshotEnabled = false;
+ mBurstCnt = 0;
LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}
@@ -672,6 +675,10 @@
CAMERA_MSG_COMPRESSED_IMAGE);
enableMsgType(picMsgType);
+ mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter");
+ if(mBurstCnt <= 0)
+ mBurstCnt = 1;
+ LOG1("mBurstCnt = %d", mBurstCnt);
return mHardware->takePicture();
}
@@ -755,6 +762,20 @@
} else if (cmd == CAMERA_CMD_PING) {
// If mHardware is 0, checkPidAndHardware will return error.
return OK;
+ } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) {
+ enableMsgType(CAMERA_MSG_STATS_DATA);
+ } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) {
+ disableMsgType(CAMERA_MSG_STATS_DATA);
+ } else if (cmd == CAMERA_CMD_METADATA_ON) {
+ enableMsgType(CAMERA_MSG_META_DATA);
+ } else if (cmd == CAMERA_CMD_METADATA_OFF) {
+ disableMsgType(CAMERA_MSG_META_DATA);
+ } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) {
+ mLongshotEnabled = true;
+ } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) {
+ mLongshotEnabled = false;
+ disableMsgType(CAMERA_MSG_SHUTTER);
+ disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
}
return mHardware->sendCommand(cmd, arg1, arg2);
@@ -954,7 +975,9 @@
c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
}
- disableMsgType(CAMERA_MSG_SHUTTER);
+ if ( !mLongshotEnabled ) {
+ disableMsgType(CAMERA_MSG_SHUTTER);
+ }
// Shutters only happen in response to takePicture, so mark device as
// idle now, until preview is restarted
@@ -1040,7 +1063,13 @@
// picture callback - compressed picture ready
void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
- disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+ if (mBurstCnt)
+ mBurstCnt--;
+
+ if (!mBurstCnt && !mLongshotEnabled) {
+ LOG1("handleCompressedPicture mBurstCnt = %d", mBurstCnt);
+ disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+ }
sp<hardware::ICameraClient> c = mRemoteCallback;
mLock.unlock();
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index a7eb960..12d6ad5 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -183,6 +183,9 @@
// This function keeps trying to grab mLock, or give up if the message
// is found to be disabled. It returns true if mLock is grabbed.
bool lockIfMessageWanted(int32_t msgType);
+
+ bool mLongshotEnabled;
+ int mBurstCnt;
};
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e35b436..8cb7130 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -92,6 +92,13 @@
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0) {
+ mPrivilegedClient = false;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.vendor.camera.privapp.list", value, "");
+ String16 packagelist(value);
+ if (packagelist.contains(clientPackageName.string())) {
+ mPrivilegedClient = true;
+ }
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
@@ -1425,7 +1432,7 @@
uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
GraphicBuffer::USAGE_HW_TEXTURE |
GraphicBuffer::USAGE_HW_COMPOSER;
- bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
+ bool flexibleConsumer = !mPrivilegedClient && (consumerUsage & disallowedFlags) == 0 &&
(consumerUsage & allowedFlags) != 0;
surface = new Surface(gbp, useAsync);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 9d3874f..378099f 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -335,6 +335,7 @@
static const int32_t REQUEST_ID_NONE = -1;
int32_t mRequestIdCounter;
+ static inline bool mPrivilegedClient;
// The list of output streams whose surfaces are deferred. We have to track them separately
// as there are no surfaces available and can not be put into mStreamMap. Once the deferred
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 62ef681..61cada6 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -136,6 +136,27 @@
return hardware::Void();
}
+#ifdef QTI_CAMERA_DEVICE
+hardware::Return<void> CameraHardwareInterface::QDataCallback(
+ DataCallbackMsg msgType, uint32_t data, uint32_t bufferIndex,
+ const vendor::qti::hardware::camera::device::V1_0::QCameraFrameMetadata& metadata) {
+ camera_memory_t* mem = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(mHidlMemPoolMapLock);
+ if (mHidlMemPoolMap.count(data) == 0) {
+ ALOGE("%s: memory pool ID %d not found", __FUNCTION__, data);
+ return hardware::Void();
+ }
+ mem = mHidlMemPoolMap.at(data);
+ }
+ camera_frame_metadata_t md;
+ md.number_of_faces = metadata.faces.size();
+ md.faces = (camera_face_t*) metadata.faces.data();
+ sDataCb((int32_t) msgType, mem, bufferIndex, &md, this);
+ return hardware::Void();
+}
+#endif
+
hardware::Return<void> CameraHardwareInterface::dataCallbackTimestamp(
DataCallbackMsg msgType, uint32_t data,
uint32_t bufferIndex, int64_t timestamp) {
@@ -591,12 +612,16 @@
// Either document why it is safe in this case or address the
// issue (e.g. by copying).
VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) mem->unsecurePointer();
- // Caching the handle here because md->pHandle will be subject to HAL's edit
- native_handle_t* nh = md->pHandle;
- hidl_handle frame = nh;
- mHidlDevice->releaseRecordingFrameHandle(heapId, bufferIndex, frame);
- native_handle_close(nh);
- native_handle_delete(nh);
+ if (md->eType == kMetadataBufferTypeNativeHandleSource) {
+ // Caching the handle here because md->pHandle will be subject to HAL's edit
+ native_handle_t* nh = md->pHandle;
+ hidl_handle frame = nh;
+ mHidlDevice->releaseRecordingFrameHandle(heapId, bufferIndex, frame);
+ native_handle_close(nh);
+ native_handle_delete(nh);
+ } else {
+ mHidlDevice->releaseRecordingFrame(heapId, bufferIndex);
+ }
} else {
mHidlDevice->releaseRecordingFrame(heapId, bufferIndex);
}
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index e519b04..4a20b6a 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -29,6 +29,9 @@
#include <hardware/camera.h>
#include <common/CameraProviderManager.h>
+#ifdef QTI_CAMERA_DEVICE
+#include <vendor/qti/hardware/camera/device/1.0/IQCameraDeviceCallback.h>
+#endif
namespace android {
@@ -85,7 +88,11 @@
class CameraHardwareInterface :
public virtual RefBase,
+#ifdef QTI_CAMERA_DEVICE
+ public virtual vendor::qti::hardware::camera::device::V1_0::IQCameraDeviceCallback,
+#else
public virtual hardware::camera::device::V1_0::ICameraDeviceCallback,
+#endif
public virtual hardware::camera::device::V1_0::ICameraDevicePreviewCallback {
public:
@@ -395,6 +402,12 @@
hardware::camera::device::V1_0::DataCallbackMsg msgType,
const hardware::hidl_vec<
hardware::camera::device::V1_0::HandleTimestampMessage>&) override;
+#ifdef QTI_CAMERA_DEVICE
+ hardware::Return<void> QDataCallback(
+ hardware::camera::device::V1_0::DataCallbackMsg msgType,
+ uint32_t data, uint32_t bufferIndex,
+ const vendor::qti::hardware::camera::device::V1_0::QCameraFrameMetadata& metadata) override;
+#endif
/**
* Implementation of android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d5f136b..abe274a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -627,9 +627,6 @@
(maxJpegResolution.width * maxJpegResolution.height);
ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
kMinJpegBufferSize;
- if (jpegBufferSize > maxJpegBufferSize) {
- jpegBufferSize = maxJpegBufferSize;
- }
return jpegBufferSize;
}