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/PlayerBase.h>
19 
20 #define max(a, b) ((a) > (b) ? (a) : (b))
21 #define min(a, b) ((a) < (b) ? (a) : (b))
22 
23 namespace android {
24 
25 using media::VolumeShaper;
26 
27 //--------------------------------------------------------------------------------------------------
PlayerBase()28 PlayerBase::PlayerBase() : BnPlayer(),
29         mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
30         mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
31         mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
32 {
33     ALOGD("PlayerBase::PlayerBase()");
34     // use checkService() to avoid blocking if audio service is not up yet
35     sp<IBinder> binder = defaultServiceManager()->checkService(String16("audio"));
36     if (binder == 0) {
37         ALOGE("PlayerBase(): binding to audio service failed, service up?");
38     } else {
39         mAudioManager = interface_cast<IAudioManager>(binder);
40     }
41 }
42 
43 
~PlayerBase()44 PlayerBase::~PlayerBase() {
45     ALOGD("PlayerBase::~PlayerBase()");
46     baseDestroy();
47 }
48 
init(player_type_t playerType,audio_usage_t usage)49 void PlayerBase::init(player_type_t playerType, audio_usage_t usage) {
50     if (mAudioManager == 0) {
51                 ALOGE("AudioPlayer realize: no audio service, player will not be registered");
52     } else {
53         mPIId = mAudioManager->trackPlayer(playerType, usage, AUDIO_CONTENT_TYPE_UNKNOWN, this);
54     }
55 }
56 
baseDestroy()57 void PlayerBase::baseDestroy() {
58     serviceReleasePlayer();
59     if (mAudioManager != 0) {
60         mAudioManager.clear();
61     }
62 }
63 
64 //------------------------------------------------------------------------------
servicePlayerEvent(player_state_t event)65 void PlayerBase::servicePlayerEvent(player_state_t event) {
66     if (mAudioManager != 0) {
67         // only report state change
68         Mutex::Autolock _l(mPlayerStateLock);
69         if (event != mLastReportedEvent
70                 && mPIId != PLAYER_PIID_INVALID) {
71             mLastReportedEvent = event;
72             mAudioManager->playerEvent(mPIId, event);
73         }
74     }
75 }
76 
serviceReleasePlayer()77 void PlayerBase::serviceReleasePlayer() {
78     if (mAudioManager != 0
79             && mPIId != PLAYER_PIID_INVALID) {
80         mAudioManager->releasePlayer(mPIId);
81     }
82 }
83 
84 //FIXME temporary method while some player state is outside of this class
reportEvent(player_state_t event)85 void PlayerBase::reportEvent(player_state_t event) {
86     servicePlayerEvent(event);
87 }
88 
startWithStatus()89 status_t PlayerBase::startWithStatus() {
90     status_t status = playerStart();
91     if (status == NO_ERROR) {
92         servicePlayerEvent(PLAYER_STATE_STARTED);
93     } else {
94         ALOGW("PlayerBase::start() error %d", status);
95     }
96     return status;
97 }
98 
pauseWithStatus()99 status_t PlayerBase::pauseWithStatus() {
100     status_t status = playerPause();
101     if (status == NO_ERROR) {
102         servicePlayerEvent(PLAYER_STATE_PAUSED);
103     } else {
104         ALOGW("PlayerBase::pause() error %d", status);
105     }
106     return status;
107 }
108 
109 
stopWithStatus()110 status_t PlayerBase::stopWithStatus() {
111     status_t status = playerStop();
112     if (status == NO_ERROR) {
113         servicePlayerEvent(PLAYER_STATE_STOPPED);
114     } else {
115         ALOGW("PlayerBase::stop() error %d", status);
116     }
117     return status;
118 }
119 
120 //------------------------------------------------------------------------------
121 // Implementation of IPlayer
start()122 binder::Status PlayerBase::start() {
123     ALOGD("PlayerBase::start() from IPlayer");
124     (void)startWithStatus();
125     return binder::Status::ok();
126 }
127 
pause()128 binder::Status PlayerBase::pause() {
129     ALOGD("PlayerBase::pause() from IPlayer");
130     (void)pauseWithStatus();
131     return binder::Status::ok();
132 }
133 
134 
stop()135 binder::Status PlayerBase::stop() {
136     ALOGD("PlayerBase::stop() from IPlayer");
137     (void)stopWithStatus();
138     return binder::Status::ok();
139 }
140 
setVolume(float vol)141 binder::Status PlayerBase::setVolume(float vol) {
142     ALOGD("PlayerBase::setVolume() from IPlayer");
143     {
144         Mutex::Autolock _l(mSettingsLock);
145         mVolumeMultiplierL = vol;
146         mVolumeMultiplierR = vol;
147     }
148     status_t status = playerSetVolume();
149     if (status != NO_ERROR) {
150         ALOGW("PlayerBase::setVolume() error %d", status);
151     }
152     return binder::Status::fromStatusT(status);
153 }
154 
setPan(float pan)155 binder::Status PlayerBase::setPan(float pan) {
156     ALOGD("PlayerBase::setPan() from IPlayer");
157     {
158         Mutex::Autolock _l(mSettingsLock);
159         pan = min(max(-1.0f, pan), 1.0f);
160         if (pan >= 0.0f) {
161             mPanMultiplierL = 1.0f - pan;
162             mPanMultiplierR = 1.0f;
163         } else {
164             mPanMultiplierL = 1.0f;
165             mPanMultiplierR = 1.0f + pan;
166         }
167     }
168     status_t status = playerSetVolume();
169     if (status != NO_ERROR) {
170         ALOGW("PlayerBase::setPan() error %d", status);
171     }
172     return binder::Status::fromStatusT(status);
173 }
174 
setStartDelayMs(int32_t delayMs __unused)175 binder::Status PlayerBase::setStartDelayMs(int32_t delayMs __unused) {
176     ALOGW("setStartDelay() is not supported");
177     return binder::Status::ok();
178 }
179 
applyVolumeShaper(const VolumeShaper::Configuration & configuration __unused,const VolumeShaper::Operation & operation __unused)180 binder::Status PlayerBase::applyVolumeShaper(
181             const VolumeShaper::Configuration& configuration __unused,
182             const VolumeShaper::Operation& operation __unused) {
183     ALOGW("applyVolumeShaper() is not supported");
184     return binder::Status::ok();
185 }
186 
187 } // namespace android
188