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 mLastReportedDeviceId(AUDIO_PORT_HANDLE_NONE)
35 {
36 ALOGD("PlayerBase::PlayerBase()");
37 // use checkService() to avoid blocking if audio service is not up yet
38 sp<IBinder> binder = defaultServiceManager()->checkService(String16("audio"));
39 if (binder == 0) {
40 ALOGE("PlayerBase(): binding to audio service failed, service up?");
41 } else {
42 mAudioManager = interface_cast<IAudioManager>(binder);
43 }
44 }
45
46
~PlayerBase()47 PlayerBase::~PlayerBase() {
48 ALOGD("PlayerBase::~PlayerBase()");
49 baseDestroy();
50 }
51
init(player_type_t playerType,audio_usage_t usage,audio_session_t sessionId)52 void PlayerBase::init(player_type_t playerType, audio_usage_t usage, audio_session_t sessionId) {
53 if (mAudioManager == 0) {
54 ALOGE("AudioPlayer realize: no audio service, player will not be registered");
55 } else {
56 mPIId = mAudioManager->trackPlayer(playerType, usage, AUDIO_CONTENT_TYPE_UNKNOWN, this,
57 sessionId);
58 }
59 }
60
baseDestroy()61 void PlayerBase::baseDestroy() {
62 serviceReleasePlayer();
63 if (mAudioManager != 0) {
64 mAudioManager.clear();
65 }
66 }
67
68 //------------------------------------------------------------------------------
servicePlayerEvent(player_state_t event,audio_port_handle_t deviceId)69 void PlayerBase::servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId) {
70 if (mAudioManager != 0) {
71 bool changed = false;
72 {
73 Mutex::Autolock _l(mDeviceIdLock);
74 changed = mLastReportedDeviceId != deviceId;
75 mLastReportedDeviceId = deviceId;
76 }
77
78 {
79 Mutex::Autolock _l(mPlayerStateLock);
80 // PLAYER_UPDATE_DEVICE_ID is not saved as an actual state, instead it is used to update
81 // device ID only.
82 if ((event != PLAYER_UPDATE_DEVICE_ID) && (event != mLastReportedEvent)) {
83 mLastReportedEvent = event;
84 changed = true;
85 }
86 }
87 if (changed && (mPIId != PLAYER_PIID_INVALID)) {
88 mAudioManager->playerEvent(mPIId, event, deviceId);
89 }
90 }
91 }
92
serviceReleasePlayer()93 void PlayerBase::serviceReleasePlayer() {
94 if (mAudioManager != 0
95 && mPIId != PLAYER_PIID_INVALID) {
96 mAudioManager->releasePlayer(mPIId);
97 }
98 }
99
100 //FIXME temporary method while some player state is outside of this class
reportEvent(player_state_t event,audio_port_handle_t deviceId)101 void PlayerBase::reportEvent(player_state_t event, audio_port_handle_t deviceId) {
102 servicePlayerEvent(event, deviceId);
103 }
104
baseUpdateDeviceId(audio_port_handle_t deviceId)105 void PlayerBase::baseUpdateDeviceId(audio_port_handle_t deviceId) {
106 servicePlayerEvent(PLAYER_UPDATE_DEVICE_ID, deviceId);
107 }
108
startWithStatus(audio_port_handle_t deviceId)109 status_t PlayerBase::startWithStatus(audio_port_handle_t deviceId) {
110 status_t status = playerStart();
111 if (status == NO_ERROR) {
112 servicePlayerEvent(PLAYER_STATE_STARTED, deviceId);
113 } else {
114 ALOGW("PlayerBase::start() error %d", status);
115 }
116 return status;
117 }
118
pauseWithStatus()119 status_t PlayerBase::pauseWithStatus() {
120 status_t status = playerPause();
121 if (status == NO_ERROR) {
122 servicePlayerEvent(PLAYER_STATE_PAUSED, AUDIO_PORT_HANDLE_NONE);
123 } else {
124 ALOGW("PlayerBase::pause() error %d", status);
125 }
126 return status;
127 }
128
stopWithStatus()129 status_t PlayerBase::stopWithStatus() {
130 status_t status = playerStop();
131
132 if (status == NO_ERROR) {
133 servicePlayerEvent(PLAYER_STATE_STOPPED, AUDIO_PORT_HANDLE_NONE);
134 } else {
135 ALOGW("PlayerBase::stop() error %d", status);
136 }
137 return status;
138 }
139
140 //------------------------------------------------------------------------------
141 // Implementation of IPlayer
start()142 binder::Status PlayerBase::start() {
143 ALOGD("PlayerBase::start() from IPlayer");
144 audio_port_handle_t deviceId;
145 {
146 Mutex::Autolock _l(mDeviceIdLock);
147 deviceId = mLastReportedDeviceId;
148 }
149 (void)startWithStatus(deviceId);
150 return binder::Status::ok();
151 }
152
pause()153 binder::Status PlayerBase::pause() {
154 ALOGD("PlayerBase::pause() from IPlayer");
155 (void)pauseWithStatus();
156 return binder::Status::ok();
157 }
158
159
stop()160 binder::Status PlayerBase::stop() {
161 ALOGD("PlayerBase::stop() from IPlayer");
162 (void)stopWithStatus();
163 return binder::Status::ok();
164 }
165
setVolume(float vol)166 binder::Status PlayerBase::setVolume(float vol) {
167 ALOGD("PlayerBase::setVolume() from IPlayer");
168 {
169 Mutex::Autolock _l(mSettingsLock);
170 mVolumeMultiplierL = vol;
171 mVolumeMultiplierR = vol;
172 }
173 status_t status = playerSetVolume();
174 if (status != NO_ERROR) {
175 ALOGW("PlayerBase::setVolume() error %d", status);
176 }
177 return binderStatusFromStatusT(status);
178 }
179
setPan(float pan)180 binder::Status PlayerBase::setPan(float pan) {
181 ALOGD("PlayerBase::setPan() from IPlayer");
182 {
183 Mutex::Autolock _l(mSettingsLock);
184 pan = min(max(-1.0f, pan), 1.0f);
185 if (pan >= 0.0f) {
186 mPanMultiplierL = 1.0f - pan;
187 mPanMultiplierR = 1.0f;
188 } else {
189 mPanMultiplierL = 1.0f;
190 mPanMultiplierR = 1.0f + pan;
191 }
192 }
193 status_t status = playerSetVolume();
194 if (status != NO_ERROR) {
195 ALOGW("PlayerBase::setPan() error %d", status);
196 }
197 return binderStatusFromStatusT(status);
198 }
199
setStartDelayMs(int32_t delayMs __unused)200 binder::Status PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
201 ALOGW("setStartDelay() is not supported");
202 return binder::Status::ok();
203 }
204
applyVolumeShaper(const VolumeShaperConfiguration & configuration __unused,const VolumeShaperOperation & operation __unused)205 binder::Status PlayerBase::applyVolumeShaper(
206 const VolumeShaperConfiguration& configuration __unused,
207 const VolumeShaperOperation& operation __unused) {
208 ALOGW("applyVolumeShaper() is not supported");
209 return binder::Status::ok();
210 }
211
212 } // namespace android
213