1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <binder/IServiceManager.h>
18 #include <media/AidlConversionUtil.h>
19 #include <media/PlayerBase.h>
20
21 #define max(a, b) ((a) > (b) ? (a) : (b))
22 #define min(a, b) ((a) < (b) ? (a) : (b))
23
24 namespace android {
25 using aidl_utils::binderStatusFromStatusT;
26 using media::VolumeShaperConfiguration;
27 using media::VolumeShaperOperation;
28
29 //--------------------------------------------------------------------------------------------------
PlayerBase()30 PlayerBase::PlayerBase() : BnPlayer(),
31 mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
32 mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
33 mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
34 {
35 ALOGD("PlayerBase::PlayerBase()");
36 // use checkService() to avoid blocking if audio service is not up yet
37 sp<IBinder> binder = defaultServiceManager()->checkService(String16("audio"));
38 if (binder == 0) {
39 ALOGE("PlayerBase(): binding to audio service failed, service up?");
40 } else {
41 mAudioManager = interface_cast<IAudioManager>(binder);
42 }
43 }
44
45
~PlayerBase()46 PlayerBase::~PlayerBase() {
47 ALOGD("PlayerBase::~PlayerBase()");
48 baseDestroy();
49 }
50
init(player_type_t playerType,audio_usage_t usage,audio_session_t sessionId)51 void PlayerBase::init(player_type_t playerType, audio_usage_t usage, audio_session_t sessionId) {
52 if (mAudioManager == 0) {
53 ALOGE("AudioPlayer realize: no audio service, player will not be registered");
54 } else {
55 mPIId = mAudioManager->trackPlayer(playerType, usage, AUDIO_CONTENT_TYPE_UNKNOWN, this,
56 sessionId);
57 }
58 }
59
triggerPortIdUpdate(audio_port_handle_t portId) const60 void PlayerBase::triggerPortIdUpdate(audio_port_handle_t portId) const {
61 if (mAudioManager == nullptr) {
62 ALOGE("%s: no audio service, player %d will not update portId %d",
63 __func__,
64 mPIId,
65 portId);
66 return;
67 }
68
69 if (mPIId != PLAYER_PIID_INVALID && portId != AUDIO_PORT_HANDLE_NONE) {
70 mAudioManager->playerEvent(mPIId, android::PLAYER_UPDATE_PORT_ID, { portId });
71 }
72 }
73
baseDestroy()74 void PlayerBase::baseDestroy() {
75 serviceReleasePlayer();
76 if (mAudioManager != 0) {
77 mAudioManager.clear();
78 }
79 }
80
81 //------------------------------------------------------------------------------
servicePlayerEvent(player_state_t event,const DeviceIdVector & deviceIds)82 void PlayerBase::servicePlayerEvent(player_state_t event, const DeviceIdVector& deviceIds) {
83 if (mAudioManager != 0) {
84 bool changed = false;
85 {
86 Mutex::Autolock _l(mDeviceIdLock);
87 changed = !areDeviceIdsEqual(deviceIds, mLastReportedDeviceIds);
88 mLastReportedDeviceIds = deviceIds;
89 }
90
91 {
92 Mutex::Autolock _l(mPlayerStateLock);
93 // PLAYER_UPDATE_DEVICE_ID is not saved as an actual state, instead it is used to update
94 // device ID only.
95 if ((event != PLAYER_UPDATE_DEVICE_ID) && (event != mLastReportedEvent)) {
96 mLastReportedEvent = event;
97 changed = true;
98 }
99 }
100 if (changed && (mPIId != PLAYER_PIID_INVALID)) {
101 mAudioManager->playerEvent(mPIId, event, deviceIds);
102 }
103 }
104 }
105
serviceReleasePlayer()106 void PlayerBase::serviceReleasePlayer() {
107 if (mAudioManager != 0
108 && mPIId != PLAYER_PIID_INVALID) {
109 mAudioManager->releasePlayer(mPIId);
110 }
111 }
112
113 //FIXME temporary method while some player state is outside of this class
reportEvent(player_state_t event,const DeviceIdVector & deviceIds)114 void PlayerBase::reportEvent(player_state_t event, const DeviceIdVector& deviceIds) {
115 servicePlayerEvent(event, deviceIds);
116 }
117
baseUpdateDeviceIds(const DeviceIdVector & deviceIds)118 void PlayerBase::baseUpdateDeviceIds(const DeviceIdVector& deviceIds) {
119 servicePlayerEvent(PLAYER_UPDATE_DEVICE_ID, deviceIds);
120 }
121
startWithStatus(const DeviceIdVector & deviceIds)122 status_t PlayerBase::startWithStatus(const DeviceIdVector& deviceIds) {
123 status_t status = playerStart();
124 if (status == NO_ERROR) {
125 servicePlayerEvent(PLAYER_STATE_STARTED, deviceIds);
126 } else {
127 ALOGW("PlayerBase::start() error %d", status);
128 }
129 return status;
130 }
131
pauseWithStatus()132 status_t PlayerBase::pauseWithStatus() {
133 status_t status = playerPause();
134 if (status == NO_ERROR) {
135 servicePlayerEvent(PLAYER_STATE_PAUSED, {});
136 } else {
137 ALOGW("PlayerBase::pause() error %d", status);
138 }
139 return status;
140 }
141
stopWithStatus()142 status_t PlayerBase::stopWithStatus() {
143 status_t status = playerStop();
144
145 if (status == NO_ERROR) {
146 servicePlayerEvent(PLAYER_STATE_STOPPED, {});
147 } else {
148 ALOGW("PlayerBase::stop() error %d", status);
149 }
150 return status;
151 }
152
153 //------------------------------------------------------------------------------
154 // Implementation of IPlayer
start()155 binder::Status PlayerBase::start() {
156 ALOGD("PlayerBase::start() from IPlayer");
157 DeviceIdVector deviceIds;
158 {
159 Mutex::Autolock _l(mDeviceIdLock);
160 deviceIds = mLastReportedDeviceIds;
161 }
162 (void)startWithStatus(deviceIds);
163 return binder::Status::ok();
164 }
165
pause()166 binder::Status PlayerBase::pause() {
167 ALOGD("PlayerBase::pause() from IPlayer");
168 (void)pauseWithStatus();
169 return binder::Status::ok();
170 }
171
172
stop()173 binder::Status PlayerBase::stop() {
174 ALOGD("PlayerBase::stop() from IPlayer");
175 (void)stopWithStatus();
176 return binder::Status::ok();
177 }
178
setVolume(float vol)179 binder::Status PlayerBase::setVolume(float vol) {
180 ALOGD("PlayerBase::setVolume() from IPlayer");
181 {
182 Mutex::Autolock _l(mSettingsLock);
183 mVolumeMultiplierL = vol;
184 mVolumeMultiplierR = vol;
185 }
186 status_t status = playerSetVolume();
187 if (status != NO_ERROR) {
188 ALOGW("PlayerBase::setVolume() error %d", status);
189 }
190 return binderStatusFromStatusT(status);
191 }
192
setPan(float pan)193 binder::Status PlayerBase::setPan(float pan) {
194 ALOGD("PlayerBase::setPan() from IPlayer");
195 {
196 Mutex::Autolock _l(mSettingsLock);
197 pan = min(max(-1.0f, pan), 1.0f);
198 if (pan >= 0.0f) {
199 mPanMultiplierL = 1.0f - pan;
200 mPanMultiplierR = 1.0f;
201 } else {
202 mPanMultiplierL = 1.0f;
203 mPanMultiplierR = 1.0f + pan;
204 }
205 }
206 status_t status = playerSetVolume();
207 if (status != NO_ERROR) {
208 ALOGW("PlayerBase::setPan() error %d", status);
209 }
210 return binderStatusFromStatusT(status);
211 }
212
setStartDelayMs(int32_t delayMs __unused)213 binder::Status PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
214 ALOGW("setStartDelay() is not supported");
215 return binder::Status::ok();
216 }
217
applyVolumeShaper(const VolumeShaperConfiguration & configuration __unused,const VolumeShaperOperation & operation __unused)218 binder::Status PlayerBase::applyVolumeShaper(
219 const VolumeShaperConfiguration& configuration __unused,
220 const VolumeShaperOperation& operation __unused) {
221 ALOGW("applyVolumeShaper() is not supported");
222 return binder::Status::ok();
223 }
224
225 } // namespace android
226