xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2008, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker **     http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker 
18*ec779b8eSAndroid Build Coastguard Worker // Proxy for media player implementations
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
21*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MediaPlayerService"
22*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include <chrono>
25*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <sys/stat.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <sys/time.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <dirent.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <unistd.h>
30*ec779b8eSAndroid Build Coastguard Worker 
31*ec779b8eSAndroid Build Coastguard Worker #include <string.h>
32*ec779b8eSAndroid Build Coastguard Worker 
33*ec779b8eSAndroid Build Coastguard Worker #include <cutils/atomic.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h> // for property_get
35*ec779b8eSAndroid Build Coastguard Worker 
36*ec779b8eSAndroid Build Coastguard Worker #include <utils/misc.h>
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker #include <android/hardware/media/omx/1.0/IOmx.h>
39*ec779b8eSAndroid Build Coastguard Worker #include <android/hardware/media/c2/1.0/IComponentStore.h>
40*ec779b8eSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
42*ec779b8eSAndroid Build Coastguard Worker #include <binder/MemoryHeapBase.h>
43*ec779b8eSAndroid Build Coastguard Worker #include <binder/MemoryBase.h>
44*ec779b8eSAndroid Build Coastguard Worker #include <gui/Surface.h>
45*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>  // for status_t
46*ec779b8eSAndroid Build Coastguard Worker #include <utils/String8.h>
47*ec779b8eSAndroid Build Coastguard Worker #include <utils/SystemClock.h>
48*ec779b8eSAndroid Build Coastguard Worker #include <utils/Timers.h>
49*ec779b8eSAndroid Build Coastguard Worker #include <utils/Vector.h>
50*ec779b8eSAndroid Build Coastguard Worker 
51*ec779b8eSAndroid Build Coastguard Worker #include <codec2/hidl/client.h>
52*ec779b8eSAndroid Build Coastguard Worker #include <datasource/HTTPBase.h>
53*ec779b8eSAndroid Build Coastguard Worker #include <media/AidlConversion.h>
54*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaHTTPService.h>
55*ec779b8eSAndroid Build Coastguard Worker #include <media/IRemoteDisplay.h>
56*ec779b8eSAndroid Build Coastguard Worker #include <media/IRemoteDisplayClient.h>
57*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaPlayerInterface.h>
58*ec779b8eSAndroid Build Coastguard Worker #include <media/mediarecorder.h>
59*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaMetadataRetrieverInterface.h>
60*ec779b8eSAndroid Build Coastguard Worker #include <media/Metadata.h>
61*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioTrack.h>
62*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/InterfaceUtils.h>
63*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaCodecConstants.h>
64*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaCodecList.h>
65*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaErrors.h>
66*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
67*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
68*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
69*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ALooperRoster.h>
70*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/SurfaceUtils.h>
71*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/BatteryNotifier.h>
72*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/MemoryLeakTrackUtil.h>
73*ec779b8eSAndroid Build Coastguard Worker #include <memunreachable/memunreachable.h>
74*ec779b8eSAndroid Build Coastguard Worker #include <system/audio.h>
75*ec779b8eSAndroid Build Coastguard Worker 
76*ec779b8eSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
77*ec779b8eSAndroid Build Coastguard Worker 
78*ec779b8eSAndroid Build Coastguard Worker #include "ActivityManager.h"
79*ec779b8eSAndroid Build Coastguard Worker #include "MediaRecorderClient.h"
80*ec779b8eSAndroid Build Coastguard Worker #include "MediaPlayerService.h"
81*ec779b8eSAndroid Build Coastguard Worker #include "MetadataRetrieverClient.h"
82*ec779b8eSAndroid Build Coastguard Worker #include "MediaPlayerFactory.h"
83*ec779b8eSAndroid Build Coastguard Worker 
84*ec779b8eSAndroid Build Coastguard Worker #include "TestPlayerStub.h"
85*ec779b8eSAndroid Build Coastguard Worker #include <nuplayer/NuPlayerDriver.h>
86*ec779b8eSAndroid Build Coastguard Worker 
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker static const int kDumpLockRetries = 50;
89*ec779b8eSAndroid Build Coastguard Worker static const int kDumpLockSleepUs = 20000;
90*ec779b8eSAndroid Build Coastguard Worker 
91*ec779b8eSAndroid Build Coastguard Worker namespace {
92*ec779b8eSAndroid Build Coastguard Worker using android::media::Metadata;
93*ec779b8eSAndroid Build Coastguard Worker using android::status_t;
94*ec779b8eSAndroid Build Coastguard Worker using android::OK;
95*ec779b8eSAndroid Build Coastguard Worker using android::BAD_VALUE;
96*ec779b8eSAndroid Build Coastguard Worker using android::NOT_ENOUGH_DATA;
97*ec779b8eSAndroid Build Coastguard Worker using android::Parcel;
98*ec779b8eSAndroid Build Coastguard Worker using android::media::VolumeShaper;
99*ec779b8eSAndroid Build Coastguard Worker using android::content::AttributionSourceState;
100*ec779b8eSAndroid Build Coastguard Worker 
101*ec779b8eSAndroid Build Coastguard Worker // Max number of entries in the filter.
102*ec779b8eSAndroid Build Coastguard Worker const int kMaxFilterSize = 64;  // I pulled that out of thin air.
103*ec779b8eSAndroid Build Coastguard Worker 
104*ec779b8eSAndroid Build Coastguard Worker const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
105*ec779b8eSAndroid Build Coastguard Worker 
106*ec779b8eSAndroid Build Coastguard Worker // FIXME: Move all the metadata related function in the Metadata.cpp
107*ec779b8eSAndroid Build Coastguard Worker 
108*ec779b8eSAndroid Build Coastguard Worker 
109*ec779b8eSAndroid Build Coastguard Worker // Unmarshall a filter from a Parcel.
110*ec779b8eSAndroid Build Coastguard Worker // Filter format in a parcel:
111*ec779b8eSAndroid Build Coastguard Worker //
112*ec779b8eSAndroid Build Coastguard Worker //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
113*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114*ec779b8eSAndroid Build Coastguard Worker // |                       number of entries (n)                   |
115*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116*ec779b8eSAndroid Build Coastguard Worker // |                       metadata type 1                         |
117*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118*ec779b8eSAndroid Build Coastguard Worker // |                       metadata type 2                         |
119*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120*ec779b8eSAndroid Build Coastguard Worker //  ....
121*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122*ec779b8eSAndroid Build Coastguard Worker // |                       metadata type n                         |
123*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124*ec779b8eSAndroid Build Coastguard Worker //
125*ec779b8eSAndroid Build Coastguard Worker // @param p Parcel that should start with a filter.
126*ec779b8eSAndroid Build Coastguard Worker // @param[out] filter On exit contains the list of metadata type to be
127*ec779b8eSAndroid Build Coastguard Worker //                    filtered.
128*ec779b8eSAndroid Build Coastguard Worker // @param[out] status On exit contains the status code to be returned.
129*ec779b8eSAndroid Build Coastguard Worker // @return true if the parcel starts with a valid filter.
unmarshallFilter(const Parcel & p,Metadata::Filter * filter,status_t * status)130*ec779b8eSAndroid Build Coastguard Worker bool unmarshallFilter(const Parcel& p,
131*ec779b8eSAndroid Build Coastguard Worker                       Metadata::Filter *filter,
132*ec779b8eSAndroid Build Coastguard Worker                       status_t *status)
133*ec779b8eSAndroid Build Coastguard Worker {
134*ec779b8eSAndroid Build Coastguard Worker     int32_t val;
135*ec779b8eSAndroid Build Coastguard Worker     if (p.readInt32(&val) != OK)
136*ec779b8eSAndroid Build Coastguard Worker     {
137*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to read filter's length");
138*ec779b8eSAndroid Build Coastguard Worker         *status = NOT_ENOUGH_DATA;
139*ec779b8eSAndroid Build Coastguard Worker         return false;
140*ec779b8eSAndroid Build Coastguard Worker     }
141*ec779b8eSAndroid Build Coastguard Worker 
142*ec779b8eSAndroid Build Coastguard Worker     if( val > kMaxFilterSize || val < 0)
143*ec779b8eSAndroid Build Coastguard Worker     {
144*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Invalid filter len %d", val);
145*ec779b8eSAndroid Build Coastguard Worker         *status = BAD_VALUE;
146*ec779b8eSAndroid Build Coastguard Worker         return false;
147*ec779b8eSAndroid Build Coastguard Worker     }
148*ec779b8eSAndroid Build Coastguard Worker 
149*ec779b8eSAndroid Build Coastguard Worker     const size_t num = val;
150*ec779b8eSAndroid Build Coastguard Worker 
151*ec779b8eSAndroid Build Coastguard Worker     filter->clear();
152*ec779b8eSAndroid Build Coastguard Worker     filter->setCapacity(num);
153*ec779b8eSAndroid Build Coastguard Worker 
154*ec779b8eSAndroid Build Coastguard Worker     size_t size = num * sizeof(Metadata::Type);
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker 
157*ec779b8eSAndroid Build Coastguard Worker     if (p.dataAvail() < size)
158*ec779b8eSAndroid Build Coastguard Worker     {
159*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Filter too short expected %zu but got %zu", size, p.dataAvail());
160*ec779b8eSAndroid Build Coastguard Worker         *status = NOT_ENOUGH_DATA;
161*ec779b8eSAndroid Build Coastguard Worker         return false;
162*ec779b8eSAndroid Build Coastguard Worker     }
163*ec779b8eSAndroid Build Coastguard Worker 
164*ec779b8eSAndroid Build Coastguard Worker     const Metadata::Type *data =
165*ec779b8eSAndroid Build Coastguard Worker             static_cast<const Metadata::Type*>(p.readInplace(size));
166*ec779b8eSAndroid Build Coastguard Worker 
167*ec779b8eSAndroid Build Coastguard Worker     if (NULL == data)
168*ec779b8eSAndroid Build Coastguard Worker     {
169*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Filter had no data");
170*ec779b8eSAndroid Build Coastguard Worker         *status = BAD_VALUE;
171*ec779b8eSAndroid Build Coastguard Worker         return false;
172*ec779b8eSAndroid Build Coastguard Worker     }
173*ec779b8eSAndroid Build Coastguard Worker 
174*ec779b8eSAndroid Build Coastguard Worker     // TODO: The stl impl of vector would be more efficient here
175*ec779b8eSAndroid Build Coastguard Worker     // because it degenerates into a memcpy on pod types. Try to
176*ec779b8eSAndroid Build Coastguard Worker     // replace later or use stl::set.
177*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < num; ++i)
178*ec779b8eSAndroid Build Coastguard Worker     {
179*ec779b8eSAndroid Build Coastguard Worker         filter->add(*data);
180*ec779b8eSAndroid Build Coastguard Worker         ++data;
181*ec779b8eSAndroid Build Coastguard Worker     }
182*ec779b8eSAndroid Build Coastguard Worker     *status = OK;
183*ec779b8eSAndroid Build Coastguard Worker     return true;
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker 
186*ec779b8eSAndroid Build Coastguard Worker // @param filter Of metadata type.
187*ec779b8eSAndroid Build Coastguard Worker // @param val To be searched.
188*ec779b8eSAndroid Build Coastguard Worker // @return true if a match was found.
findMetadata(const Metadata::Filter & filter,const int32_t val)189*ec779b8eSAndroid Build Coastguard Worker bool findMetadata(const Metadata::Filter& filter, const int32_t val)
190*ec779b8eSAndroid Build Coastguard Worker {
191*ec779b8eSAndroid Build Coastguard Worker     // Deal with empty and ANY right away
192*ec779b8eSAndroid Build Coastguard Worker     if (filter.isEmpty()) return false;
193*ec779b8eSAndroid Build Coastguard Worker     if (filter[0] == Metadata::kAny) return true;
194*ec779b8eSAndroid Build Coastguard Worker 
195*ec779b8eSAndroid Build Coastguard Worker     return filter.indexOf(val) >= 0;
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker 
198*ec779b8eSAndroid Build Coastguard Worker }  // anonymous namespace
199*ec779b8eSAndroid Build Coastguard Worker 
200*ec779b8eSAndroid Build Coastguard Worker 
201*ec779b8eSAndroid Build Coastguard Worker namespace {
202*ec779b8eSAndroid Build Coastguard Worker using android::Parcel;
203*ec779b8eSAndroid Build Coastguard Worker using android::String16;
204*ec779b8eSAndroid Build Coastguard Worker 
205*ec779b8eSAndroid Build Coastguard Worker // marshalling tag indicating flattened utf16 tags
206*ec779b8eSAndroid Build Coastguard Worker // keep in sync with frameworks/base/media/java/android/media/AudioAttributes.java
207*ec779b8eSAndroid Build Coastguard Worker const int32_t kAudioAttributesMarshallTagFlattenTags = 1;
208*ec779b8eSAndroid Build Coastguard Worker 
209*ec779b8eSAndroid Build Coastguard Worker // Audio attributes format in a parcel:
210*ec779b8eSAndroid Build Coastguard Worker //
211*ec779b8eSAndroid Build Coastguard Worker //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
212*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213*ec779b8eSAndroid Build Coastguard Worker // |                       usage                                   |
214*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215*ec779b8eSAndroid Build Coastguard Worker // |                       content_type                            |
216*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217*ec779b8eSAndroid Build Coastguard Worker // |                       source                                  |
218*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219*ec779b8eSAndroid Build Coastguard Worker // |                       flags                                   |
220*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
221*ec779b8eSAndroid Build Coastguard Worker // |                       kAudioAttributesMarshallTagFlattenTags  | // ignore tags if not found
222*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223*ec779b8eSAndroid Build Coastguard Worker // |                       flattened tags in UTF16                 |
224*ec779b8eSAndroid Build Coastguard Worker // |                         ...                                   |
225*ec779b8eSAndroid Build Coastguard Worker // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
226*ec779b8eSAndroid Build Coastguard Worker //
227*ec779b8eSAndroid Build Coastguard Worker // @param p Parcel that contains audio attributes.
228*ec779b8eSAndroid Build Coastguard Worker // @param[out] attributes On exit points to an initialized audio_attributes_t structure
229*ec779b8eSAndroid Build Coastguard Worker // @param[out] status On exit contains the status code to be returned.
unmarshallAudioAttributes(const Parcel & parcel,audio_attributes_t * attributes)230*ec779b8eSAndroid Build Coastguard Worker void unmarshallAudioAttributes(const Parcel& parcel, audio_attributes_t *attributes)
231*ec779b8eSAndroid Build Coastguard Worker {
232*ec779b8eSAndroid Build Coastguard Worker     attributes->usage = (audio_usage_t) parcel.readInt32();
233*ec779b8eSAndroid Build Coastguard Worker     attributes->content_type = (audio_content_type_t) parcel.readInt32();
234*ec779b8eSAndroid Build Coastguard Worker     attributes->source = (audio_source_t) parcel.readInt32();
235*ec779b8eSAndroid Build Coastguard Worker     attributes->flags = (audio_flags_mask_t) parcel.readInt32();
236*ec779b8eSAndroid Build Coastguard Worker     const bool hasFlattenedTag = (parcel.readInt32() == kAudioAttributesMarshallTagFlattenTags);
237*ec779b8eSAndroid Build Coastguard Worker     if (hasFlattenedTag) {
238*ec779b8eSAndroid Build Coastguard Worker         // the tags are UTF16, convert to UTF8
239*ec779b8eSAndroid Build Coastguard Worker         String16 tags = parcel.readString16();
240*ec779b8eSAndroid Build Coastguard Worker         ssize_t realTagSize = utf16_to_utf8_length(tags.c_str(), tags.size());
241*ec779b8eSAndroid Build Coastguard Worker         if (realTagSize <= 0) {
242*ec779b8eSAndroid Build Coastguard Worker             strcpy(attributes->tags, "");
243*ec779b8eSAndroid Build Coastguard Worker         } else {
244*ec779b8eSAndroid Build Coastguard Worker             // copy the flattened string into the attributes as the destination for the conversion:
245*ec779b8eSAndroid Build Coastguard Worker             // copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
246*ec779b8eSAndroid Build Coastguard Worker             size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
247*ec779b8eSAndroid Build Coastguard Worker                     AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
248*ec779b8eSAndroid Build Coastguard Worker             utf16_to_utf8(tags.c_str(), tagSize, attributes->tags,
249*ec779b8eSAndroid Build Coastguard Worker                     sizeof(attributes->tags) / sizeof(attributes->tags[0]));
250*ec779b8eSAndroid Build Coastguard Worker         }
251*ec779b8eSAndroid Build Coastguard Worker     } else {
252*ec779b8eSAndroid Build Coastguard Worker         ALOGE("unmarshallAudioAttributes() received unflattened tags, ignoring tag values");
253*ec779b8eSAndroid Build Coastguard Worker         strcpy(attributes->tags, "");
254*ec779b8eSAndroid Build Coastguard Worker     }
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker } // anonymous namespace
257*ec779b8eSAndroid Build Coastguard Worker 
258*ec779b8eSAndroid Build Coastguard Worker 
259*ec779b8eSAndroid Build Coastguard Worker namespace android {
260*ec779b8eSAndroid Build Coastguard Worker 
261*ec779b8eSAndroid Build Coastguard Worker extern ALooperRoster gLooperRoster;
262*ec779b8eSAndroid Build Coastguard Worker 
263*ec779b8eSAndroid Build Coastguard Worker 
checkPermission(const char * permissionString)264*ec779b8eSAndroid Build Coastguard Worker static bool checkPermission(const char* permissionString) {
265*ec779b8eSAndroid Build Coastguard Worker     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
266*ec779b8eSAndroid Build Coastguard Worker     bool ok = checkCallingPermission(String16(permissionString));
267*ec779b8eSAndroid Build Coastguard Worker     if (!ok) ALOGE("Request requires %s", permissionString);
268*ec779b8eSAndroid Build Coastguard Worker     return ok;
269*ec779b8eSAndroid Build Coastguard Worker }
270*ec779b8eSAndroid Build Coastguard Worker 
dumpCodecDetails(int fd,const sp<IMediaCodecList> & codecList,bool queryDecoders)271*ec779b8eSAndroid Build Coastguard Worker static void dumpCodecDetails(int fd, const sp<IMediaCodecList> &codecList, bool queryDecoders) {
272*ec779b8eSAndroid Build Coastguard Worker     const size_t SIZE = 256;
273*ec779b8eSAndroid Build Coastguard Worker     char buffer[SIZE];
274*ec779b8eSAndroid Build Coastguard Worker     String8 result;
275*ec779b8eSAndroid Build Coastguard Worker 
276*ec779b8eSAndroid Build Coastguard Worker     const char *codecType = queryDecoders? "Decoder" : "Encoder";
277*ec779b8eSAndroid Build Coastguard Worker     snprintf(buffer, SIZE - 1, "\n%s infos by media types:\n"
278*ec779b8eSAndroid Build Coastguard Worker              "=============================\n", codecType);
279*ec779b8eSAndroid Build Coastguard Worker     result.append(buffer);
280*ec779b8eSAndroid Build Coastguard Worker 
281*ec779b8eSAndroid Build Coastguard Worker     size_t numCodecs = codecList->countCodecs();
282*ec779b8eSAndroid Build Coastguard Worker 
283*ec779b8eSAndroid Build Coastguard Worker     // gather all media types supported by codec class, and link to codecs that support them
284*ec779b8eSAndroid Build Coastguard Worker     KeyedVector<AString, Vector<sp<MediaCodecInfo>>> allMediaTypes;
285*ec779b8eSAndroid Build Coastguard Worker     for (size_t codec_ix = 0; codec_ix < numCodecs; ++codec_ix) {
286*ec779b8eSAndroid Build Coastguard Worker         sp<MediaCodecInfo> info = codecList->getCodecInfo(codec_ix);
287*ec779b8eSAndroid Build Coastguard Worker         if (info->isEncoder() == !queryDecoders) {
288*ec779b8eSAndroid Build Coastguard Worker             Vector<AString> supportedMediaTypes;
289*ec779b8eSAndroid Build Coastguard Worker             info->getSupportedMediaTypes(&supportedMediaTypes);
290*ec779b8eSAndroid Build Coastguard Worker             if (!supportedMediaTypes.size()) {
291*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buffer, SIZE - 1, "warning: %s does not support any media types\n",
292*ec779b8eSAndroid Build Coastguard Worker                         info->getCodecName());
293*ec779b8eSAndroid Build Coastguard Worker                 result.append(buffer);
294*ec779b8eSAndroid Build Coastguard Worker             } else {
295*ec779b8eSAndroid Build Coastguard Worker                 for (const AString &mediaType : supportedMediaTypes) {
296*ec779b8eSAndroid Build Coastguard Worker                     if (allMediaTypes.indexOfKey(mediaType) < 0) {
297*ec779b8eSAndroid Build Coastguard Worker                         allMediaTypes.add(mediaType, Vector<sp<MediaCodecInfo>>());
298*ec779b8eSAndroid Build Coastguard Worker                     }
299*ec779b8eSAndroid Build Coastguard Worker                     allMediaTypes.editValueFor(mediaType).add(info);
300*ec779b8eSAndroid Build Coastguard Worker                 }
301*ec779b8eSAndroid Build Coastguard Worker             }
302*ec779b8eSAndroid Build Coastguard Worker         }
303*ec779b8eSAndroid Build Coastguard Worker     }
304*ec779b8eSAndroid Build Coastguard Worker 
305*ec779b8eSAndroid Build Coastguard Worker     KeyedVector<AString, bool> visitedCodecs;
306*ec779b8eSAndroid Build Coastguard Worker     for (size_t type_ix = 0; type_ix < allMediaTypes.size(); ++type_ix) {
307*ec779b8eSAndroid Build Coastguard Worker         const AString &mediaType = allMediaTypes.keyAt(type_ix);
308*ec779b8eSAndroid Build Coastguard Worker         snprintf(buffer, SIZE - 1, "\nMedia type '%s':\n", mediaType.c_str());
309*ec779b8eSAndroid Build Coastguard Worker         result.append(buffer);
310*ec779b8eSAndroid Build Coastguard Worker 
311*ec779b8eSAndroid Build Coastguard Worker         for (const sp<MediaCodecInfo> &info : allMediaTypes.valueAt(type_ix)) {
312*ec779b8eSAndroid Build Coastguard Worker             sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(mediaType.c_str());
313*ec779b8eSAndroid Build Coastguard Worker             if (caps == NULL) {
314*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buffer, SIZE - 1, "warning: %s does not have capabilities for type %s\n",
315*ec779b8eSAndroid Build Coastguard Worker                         info->getCodecName(), mediaType.c_str());
316*ec779b8eSAndroid Build Coastguard Worker                 result.append(buffer);
317*ec779b8eSAndroid Build Coastguard Worker                 continue;
318*ec779b8eSAndroid Build Coastguard Worker             }
319*ec779b8eSAndroid Build Coastguard Worker             snprintf(buffer, SIZE - 1, "  %s \"%s\" supports\n",
320*ec779b8eSAndroid Build Coastguard Worker                        codecType, info->getCodecName());
321*ec779b8eSAndroid Build Coastguard Worker             result.append(buffer);
322*ec779b8eSAndroid Build Coastguard Worker 
323*ec779b8eSAndroid Build Coastguard Worker             auto printList = [&](const char *type, const Vector<AString> &values){
324*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buffer, SIZE - 1, "    %s: [", type);
325*ec779b8eSAndroid Build Coastguard Worker                 result.append(buffer);
326*ec779b8eSAndroid Build Coastguard Worker                 for (size_t j = 0; j < values.size(); ++j) {
327*ec779b8eSAndroid Build Coastguard Worker                     snprintf(buffer, SIZE - 1, "\n      %s%s", values[j].c_str(),
328*ec779b8eSAndroid Build Coastguard Worker                             j == values.size() - 1 ? " " : ",");
329*ec779b8eSAndroid Build Coastguard Worker                     result.append(buffer);
330*ec779b8eSAndroid Build Coastguard Worker                 }
331*ec779b8eSAndroid Build Coastguard Worker                 result.append("]\n");
332*ec779b8eSAndroid Build Coastguard Worker             };
333*ec779b8eSAndroid Build Coastguard Worker 
334*ec779b8eSAndroid Build Coastguard Worker             if (visitedCodecs.indexOfKey(info->getCodecName()) < 0) {
335*ec779b8eSAndroid Build Coastguard Worker                 visitedCodecs.add(info->getCodecName(), true);
336*ec779b8eSAndroid Build Coastguard Worker                 {
337*ec779b8eSAndroid Build Coastguard Worker                     Vector<AString> aliases;
338*ec779b8eSAndroid Build Coastguard Worker                     info->getAliases(&aliases);
339*ec779b8eSAndroid Build Coastguard Worker                     // quote alias
340*ec779b8eSAndroid Build Coastguard Worker                     for (AString &alias : aliases) {
341*ec779b8eSAndroid Build Coastguard Worker                         alias.insert("\"", 1, 0);
342*ec779b8eSAndroid Build Coastguard Worker                         alias.append('"');
343*ec779b8eSAndroid Build Coastguard Worker                     }
344*ec779b8eSAndroid Build Coastguard Worker                     printList("aliases", aliases);
345*ec779b8eSAndroid Build Coastguard Worker                 }
346*ec779b8eSAndroid Build Coastguard Worker                 {
347*ec779b8eSAndroid Build Coastguard Worker                     uint32_t attrs = info->getAttributes();
348*ec779b8eSAndroid Build Coastguard Worker                     Vector<AString> list;
349*ec779b8eSAndroid Build Coastguard Worker                     list.add(AStringPrintf("encoder: %d",
350*ec779b8eSAndroid Build Coastguard Worker                                            !!(attrs & MediaCodecInfo::kFlagIsEncoder)));
351*ec779b8eSAndroid Build Coastguard Worker                     list.add(AStringPrintf("vendor: %d",
352*ec779b8eSAndroid Build Coastguard Worker                                            !!(attrs & MediaCodecInfo::kFlagIsVendor)));
353*ec779b8eSAndroid Build Coastguard Worker                     list.add(AStringPrintf("software-only: %d",
354*ec779b8eSAndroid Build Coastguard Worker                                            !!(attrs & MediaCodecInfo::kFlagIsSoftwareOnly)));
355*ec779b8eSAndroid Build Coastguard Worker                     list.add(AStringPrintf("hw-accelerated: %d",
356*ec779b8eSAndroid Build Coastguard Worker                                            !!(attrs & MediaCodecInfo::kFlagIsHardwareAccelerated)));
357*ec779b8eSAndroid Build Coastguard Worker                     printList(AStringPrintf("attributes: %#x", attrs).c_str(), list);
358*ec779b8eSAndroid Build Coastguard Worker                 }
359*ec779b8eSAndroid Build Coastguard Worker 
360*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buffer, SIZE - 1, "    owner: \"%s\"\n", info->getOwnerName());
361*ec779b8eSAndroid Build Coastguard Worker                 result.append(buffer);
362*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buffer, SIZE - 1, "    rank: %u\n", info->getRank());
363*ec779b8eSAndroid Build Coastguard Worker                 result.append(buffer);
364*ec779b8eSAndroid Build Coastguard Worker             } else {
365*ec779b8eSAndroid Build Coastguard Worker                 result.append("    aliases, attributes, owner, rank: see above\n");
366*ec779b8eSAndroid Build Coastguard Worker             }
367*ec779b8eSAndroid Build Coastguard Worker 
368*ec779b8eSAndroid Build Coastguard Worker             {
369*ec779b8eSAndroid Build Coastguard Worker                 Vector<AString> list;
370*ec779b8eSAndroid Build Coastguard Worker                 Vector<MediaCodecInfo::ProfileLevel> profileLevels;
371*ec779b8eSAndroid Build Coastguard Worker                 caps->getSupportedProfileLevels(&profileLevels);
372*ec779b8eSAndroid Build Coastguard Worker                 for (const MediaCodecInfo::ProfileLevel &pl : profileLevels) {
373*ec779b8eSAndroid Build Coastguard Worker                     const char *niceProfile =
374*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_AUDIO_AAC)
375*ec779b8eSAndroid Build Coastguard Worker                             ? asString_AACObject(pl.mProfile) :
376*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
377*ec779b8eSAndroid Build Coastguard Worker                             ? asString_MPEG2Profile(pl.mProfile) :
378*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)
379*ec779b8eSAndroid Build Coastguard Worker                             ? asString_H263Profile(pl.mProfile) :
380*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG4)
381*ec779b8eSAndroid Build Coastguard Worker                             ? asString_MPEG4Profile(pl.mProfile) :
382*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AVC)
383*ec779b8eSAndroid Build Coastguard Worker                             ? asString_AVCProfile(pl.mProfile) :
384*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)
385*ec779b8eSAndroid Build Coastguard Worker                             ? asString_VP8Profile(pl.mProfile) :
386*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)
387*ec779b8eSAndroid Build Coastguard Worker                             ? asString_HEVCProfile(pl.mProfile) :
388*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
389*ec779b8eSAndroid Build Coastguard Worker                             ? asString_VP9Profile(pl.mProfile) :
390*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
391*ec779b8eSAndroid Build Coastguard Worker                             ? asString_AV1Profile(pl.mProfile) :
392*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)
393*ec779b8eSAndroid Build Coastguard Worker                             ? asString_DolbyVisionProfile(pl.mProfile) : "??";
394*ec779b8eSAndroid Build Coastguard Worker                     const char *niceLevel =
395*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
396*ec779b8eSAndroid Build Coastguard Worker                             ? asString_MPEG2Level(pl.mLevel) :
397*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)
398*ec779b8eSAndroid Build Coastguard Worker                             ? asString_H263Level(pl.mLevel) :
399*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG4)
400*ec779b8eSAndroid Build Coastguard Worker                             ? asString_MPEG4Level(pl.mLevel) :
401*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AVC)
402*ec779b8eSAndroid Build Coastguard Worker                             ? asString_AVCLevel(pl.mLevel) :
403*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)
404*ec779b8eSAndroid Build Coastguard Worker                             ? asString_VP8Level(pl.mLevel) :
405*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)
406*ec779b8eSAndroid Build Coastguard Worker                             ? asString_HEVCTierLevel(pl.mLevel) :
407*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
408*ec779b8eSAndroid Build Coastguard Worker                             ? asString_VP9Level(pl.mLevel) :
409*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
410*ec779b8eSAndroid Build Coastguard Worker                             ? asString_AV1Level(pl.mLevel) :
411*ec779b8eSAndroid Build Coastguard Worker                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)
412*ec779b8eSAndroid Build Coastguard Worker                             ? asString_DolbyVisionLevel(pl.mLevel) : "??";
413*ec779b8eSAndroid Build Coastguard Worker 
414*ec779b8eSAndroid Build Coastguard Worker                     list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
415*ec779b8eSAndroid Build Coastguard Worker                             pl.mProfile, pl.mLevel, niceProfile, niceLevel));
416*ec779b8eSAndroid Build Coastguard Worker                 }
417*ec779b8eSAndroid Build Coastguard Worker                 printList("profile/levels", list);
418*ec779b8eSAndroid Build Coastguard Worker             }
419*ec779b8eSAndroid Build Coastguard Worker 
420*ec779b8eSAndroid Build Coastguard Worker             {
421*ec779b8eSAndroid Build Coastguard Worker                 Vector<AString> list;
422*ec779b8eSAndroid Build Coastguard Worker                 Vector<uint32_t> colors;
423*ec779b8eSAndroid Build Coastguard Worker                 caps->getSupportedColorFormats(&colors);
424*ec779b8eSAndroid Build Coastguard Worker                 for (uint32_t color : colors) {
425*ec779b8eSAndroid Build Coastguard Worker                     list.add(AStringPrintf("%#x (%s)", color,
426*ec779b8eSAndroid Build Coastguard Worker                             asString_ColorFormat((int32_t)color)));
427*ec779b8eSAndroid Build Coastguard Worker                 }
428*ec779b8eSAndroid Build Coastguard Worker                 printList("colors", list);
429*ec779b8eSAndroid Build Coastguard Worker             }
430*ec779b8eSAndroid Build Coastguard Worker 
431*ec779b8eSAndroid Build Coastguard Worker             result.append("    details: ");
432*ec779b8eSAndroid Build Coastguard Worker             result.append(caps->getDetails()->debugString(6).c_str());
433*ec779b8eSAndroid Build Coastguard Worker             result.append("\n");
434*ec779b8eSAndroid Build Coastguard Worker         }
435*ec779b8eSAndroid Build Coastguard Worker     }
436*ec779b8eSAndroid Build Coastguard Worker     result.append("\n");
437*ec779b8eSAndroid Build Coastguard Worker     ::write(fd, result.c_str(), result.size());
438*ec779b8eSAndroid Build Coastguard Worker }
439*ec779b8eSAndroid Build Coastguard Worker 
440*ec779b8eSAndroid Build Coastguard Worker 
441*ec779b8eSAndroid Build Coastguard Worker // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
442*ec779b8eSAndroid Build Coastguard Worker /* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
443*ec779b8eSAndroid Build Coastguard Worker /* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
444*ec779b8eSAndroid Build Coastguard Worker 
instantiate()445*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::instantiate() {
446*ec779b8eSAndroid Build Coastguard Worker     defaultServiceManager()->addService(
447*ec779b8eSAndroid Build Coastguard Worker             String16("media.player"), new MediaPlayerService());
448*ec779b8eSAndroid Build Coastguard Worker }
449*ec779b8eSAndroid Build Coastguard Worker 
MediaPlayerService()450*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::MediaPlayerService()
451*ec779b8eSAndroid Build Coastguard Worker {
452*ec779b8eSAndroid Build Coastguard Worker     ALOGV("MediaPlayerService created");
453*ec779b8eSAndroid Build Coastguard Worker     mNextConnId = 1;
454*ec779b8eSAndroid Build Coastguard Worker 
455*ec779b8eSAndroid Build Coastguard Worker     MediaPlayerFactory::registerBuiltinFactories();
456*ec779b8eSAndroid Build Coastguard Worker }
457*ec779b8eSAndroid Build Coastguard Worker 
~MediaPlayerService()458*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::~MediaPlayerService()
459*ec779b8eSAndroid Build Coastguard Worker {
460*ec779b8eSAndroid Build Coastguard Worker     ALOGV("MediaPlayerService destroyed");
461*ec779b8eSAndroid Build Coastguard Worker }
462*ec779b8eSAndroid Build Coastguard Worker 
createMediaRecorder(const AttributionSourceState & attributionSource)463*ec779b8eSAndroid Build Coastguard Worker sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(
464*ec779b8eSAndroid Build Coastguard Worker         const AttributionSourceState& attributionSource)
465*ec779b8eSAndroid Build Coastguard Worker {
466*ec779b8eSAndroid Build Coastguard Worker     // TODO b/182392769: use attribution source util
467*ec779b8eSAndroid Build Coastguard Worker     AttributionSourceState verifiedAttributionSource = attributionSource;
468*ec779b8eSAndroid Build Coastguard Worker     verifiedAttributionSource.uid = VALUE_OR_FATAL(
469*ec779b8eSAndroid Build Coastguard Worker       legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
470*ec779b8eSAndroid Build Coastguard Worker     verifiedAttributionSource.pid = VALUE_OR_FATAL(
471*ec779b8eSAndroid Build Coastguard Worker         legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
472*ec779b8eSAndroid Build Coastguard Worker     sp<MediaRecorderClient> recorder =
473*ec779b8eSAndroid Build Coastguard Worker         new MediaRecorderClient(this, verifiedAttributionSource);
474*ec779b8eSAndroid Build Coastguard Worker     wp<MediaRecorderClient> w = recorder;
475*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
476*ec779b8eSAndroid Build Coastguard Worker     mMediaRecorderClients.add(w);
477*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Create new media recorder client from pid %s",
478*ec779b8eSAndroid Build Coastguard Worker         verifiedAttributionSource.toString().c_str());
479*ec779b8eSAndroid Build Coastguard Worker     return recorder;
480*ec779b8eSAndroid Build Coastguard Worker }
481*ec779b8eSAndroid Build Coastguard Worker 
removeMediaRecorderClient(const wp<MediaRecorderClient> & client)482*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::removeMediaRecorderClient(const wp<MediaRecorderClient>& client)
483*ec779b8eSAndroid Build Coastguard Worker {
484*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
485*ec779b8eSAndroid Build Coastguard Worker     mMediaRecorderClients.remove(client);
486*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Delete media recorder client");
487*ec779b8eSAndroid Build Coastguard Worker }
488*ec779b8eSAndroid Build Coastguard Worker 
createMetadataRetriever()489*ec779b8eSAndroid Build Coastguard Worker sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever()
490*ec779b8eSAndroid Build Coastguard Worker {
491*ec779b8eSAndroid Build Coastguard Worker     pid_t pid = IPCThreadState::self()->getCallingPid();
492*ec779b8eSAndroid Build Coastguard Worker     sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
493*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Create new media retriever from pid %d", pid);
494*ec779b8eSAndroid Build Coastguard Worker     return retriever;
495*ec779b8eSAndroid Build Coastguard Worker }
496*ec779b8eSAndroid Build Coastguard Worker 
create(const sp<IMediaPlayerClient> & client,audio_session_t audioSessionId,const AttributionSourceState & attributionSource)497*ec779b8eSAndroid Build Coastguard Worker sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
498*ec779b8eSAndroid Build Coastguard Worker         audio_session_t audioSessionId, const AttributionSourceState& attributionSource)
499*ec779b8eSAndroid Build Coastguard Worker {
500*ec779b8eSAndroid Build Coastguard Worker     int32_t connId = android_atomic_inc(&mNextConnId);
501*ec779b8eSAndroid Build Coastguard Worker     // TODO b/182392769: use attribution source util
502*ec779b8eSAndroid Build Coastguard Worker     AttributionSourceState verifiedAttributionSource = attributionSource;
503*ec779b8eSAndroid Build Coastguard Worker     verifiedAttributionSource.pid = VALUE_OR_FATAL(
504*ec779b8eSAndroid Build Coastguard Worker         legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
505*ec779b8eSAndroid Build Coastguard Worker     verifiedAttributionSource.uid = VALUE_OR_FATAL(
506*ec779b8eSAndroid Build Coastguard Worker         legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));
507*ec779b8eSAndroid Build Coastguard Worker 
508*ec779b8eSAndroid Build Coastguard Worker     sp<Client> c = new Client(
509*ec779b8eSAndroid Build Coastguard Worker             this, verifiedAttributionSource, connId, client, audioSessionId);
510*ec779b8eSAndroid Build Coastguard Worker 
511*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Create new client(%d) from %s, ", connId,
512*ec779b8eSAndroid Build Coastguard Worker         verifiedAttributionSource.toString().c_str());
513*ec779b8eSAndroid Build Coastguard Worker 
514*ec779b8eSAndroid Build Coastguard Worker     wp<Client> w = c;
515*ec779b8eSAndroid Build Coastguard Worker     {
516*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
517*ec779b8eSAndroid Build Coastguard Worker         mClients.add(w);
518*ec779b8eSAndroid Build Coastguard Worker     }
519*ec779b8eSAndroid Build Coastguard Worker     return c;
520*ec779b8eSAndroid Build Coastguard Worker }
521*ec779b8eSAndroid Build Coastguard Worker 
getCodecList() const522*ec779b8eSAndroid Build Coastguard Worker sp<IMediaCodecList> MediaPlayerService::getCodecList() const {
523*ec779b8eSAndroid Build Coastguard Worker     return MediaCodecList::getLocalInstance();
524*ec779b8eSAndroid Build Coastguard Worker }
525*ec779b8eSAndroid Build Coastguard Worker 
listenForRemoteDisplay(const String16 &,const sp<IRemoteDisplayClient> &,const String8 &)526*ec779b8eSAndroid Build Coastguard Worker sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
527*ec779b8eSAndroid Build Coastguard Worker         const String16 &/*opPackageName*/,
528*ec779b8eSAndroid Build Coastguard Worker         const sp<IRemoteDisplayClient>& /*client*/,
529*ec779b8eSAndroid Build Coastguard Worker         const String8& /*iface*/) {
530*ec779b8eSAndroid Build Coastguard Worker     ALOGE("listenForRemoteDisplay is no longer supported!");
531*ec779b8eSAndroid Build Coastguard Worker 
532*ec779b8eSAndroid Build Coastguard Worker     return NULL;
533*ec779b8eSAndroid Build Coastguard Worker }
534*ec779b8eSAndroid Build Coastguard Worker 
dump(int fd,const Vector<String16> & args) const535*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
536*ec779b8eSAndroid Build Coastguard Worker {
537*ec779b8eSAndroid Build Coastguard Worker     const size_t SIZE = 256;
538*ec779b8eSAndroid Build Coastguard Worker     char buffer[SIZE];
539*ec779b8eSAndroid Build Coastguard Worker     String8 result;
540*ec779b8eSAndroid Build Coastguard Worker 
541*ec779b8eSAndroid Build Coastguard Worker     result.append(" AudioOutput\n");
542*ec779b8eSAndroid Build Coastguard Worker     snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n",
543*ec779b8eSAndroid Build Coastguard Worker             mStreamType, mLeftVolume, mRightVolume);
544*ec779b8eSAndroid Build Coastguard Worker     result.append(buffer);
545*ec779b8eSAndroid Build Coastguard Worker     snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
546*ec779b8eSAndroid Build Coastguard Worker             mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
547*ec779b8eSAndroid Build Coastguard Worker     result.append(buffer);
548*ec779b8eSAndroid Build Coastguard Worker     snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
549*ec779b8eSAndroid Build Coastguard Worker             mAuxEffectId, mSendLevel);
550*ec779b8eSAndroid Build Coastguard Worker     result.append(buffer);
551*ec779b8eSAndroid Build Coastguard Worker 
552*ec779b8eSAndroid Build Coastguard Worker     ::write(fd, result.c_str(), result.size());
553*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
554*ec779b8eSAndroid Build Coastguard Worker         mTrack->dump(fd, args);
555*ec779b8eSAndroid Build Coastguard Worker     }
556*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
557*ec779b8eSAndroid Build Coastguard Worker }
558*ec779b8eSAndroid Build Coastguard Worker 
dump(int fd,const Vector<String16> & args)559*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args)
560*ec779b8eSAndroid Build Coastguard Worker {
561*ec779b8eSAndroid Build Coastguard Worker     const size_t SIZE = 256;
562*ec779b8eSAndroid Build Coastguard Worker     char buffer[SIZE];
563*ec779b8eSAndroid Build Coastguard Worker     String8 result;
564*ec779b8eSAndroid Build Coastguard Worker     result.append(" Client\n");
565*ec779b8eSAndroid Build Coastguard Worker     snprintf(buffer, 255, "  AttributionSource(%s), connId(%d), status(%d), looping(%s)\n",
566*ec779b8eSAndroid Build Coastguard Worker         mAttributionSource.toString().c_str(), mConnId, mStatus, mLoop?"true": "false");
567*ec779b8eSAndroid Build Coastguard Worker     result.append(buffer);
568*ec779b8eSAndroid Build Coastguard Worker 
569*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p;
570*ec779b8eSAndroid Build Coastguard Worker     sp<AudioOutput> audioOutput;
571*ec779b8eSAndroid Build Coastguard Worker     bool locked = false;
572*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < kDumpLockRetries; ++i) {
573*ec779b8eSAndroid Build Coastguard Worker         if (mLock.tryLock() == NO_ERROR) {
574*ec779b8eSAndroid Build Coastguard Worker             locked = true;
575*ec779b8eSAndroid Build Coastguard Worker             break;
576*ec779b8eSAndroid Build Coastguard Worker         }
577*ec779b8eSAndroid Build Coastguard Worker         usleep(kDumpLockSleepUs);
578*ec779b8eSAndroid Build Coastguard Worker     }
579*ec779b8eSAndroid Build Coastguard Worker 
580*ec779b8eSAndroid Build Coastguard Worker     if (locked) {
581*ec779b8eSAndroid Build Coastguard Worker         p = mPlayer;
582*ec779b8eSAndroid Build Coastguard Worker         audioOutput = mAudioOutput;
583*ec779b8eSAndroid Build Coastguard Worker         mLock.unlock();
584*ec779b8eSAndroid Build Coastguard Worker     } else {
585*ec779b8eSAndroid Build Coastguard Worker         result.append("  lock is taken, no dump from player and audio output\n");
586*ec779b8eSAndroid Build Coastguard Worker     }
587*ec779b8eSAndroid Build Coastguard Worker     write(fd, result.c_str(), result.size());
588*ec779b8eSAndroid Build Coastguard Worker 
589*ec779b8eSAndroid Build Coastguard Worker     if (p != NULL) {
590*ec779b8eSAndroid Build Coastguard Worker         p->dump(fd, args);
591*ec779b8eSAndroid Build Coastguard Worker     }
592*ec779b8eSAndroid Build Coastguard Worker     if (audioOutput != 0) {
593*ec779b8eSAndroid Build Coastguard Worker         audioOutput->dump(fd, args);
594*ec779b8eSAndroid Build Coastguard Worker     }
595*ec779b8eSAndroid Build Coastguard Worker     write(fd, "\n", 1);
596*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
597*ec779b8eSAndroid Build Coastguard Worker }
598*ec779b8eSAndroid Build Coastguard Worker 
599*ec779b8eSAndroid Build Coastguard Worker /**
600*ec779b8eSAndroid Build Coastguard Worker  * The only arguments this understands right now are -c, -von and -voff,
601*ec779b8eSAndroid Build Coastguard Worker  * which are parsed by ALooperRoster::dump()
602*ec779b8eSAndroid Build Coastguard Worker  */
dump(int fd,const Vector<String16> & args)603*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
604*ec779b8eSAndroid Build Coastguard Worker {
605*ec779b8eSAndroid Build Coastguard Worker     const size_t SIZE = 256;
606*ec779b8eSAndroid Build Coastguard Worker     char buffer[SIZE];
607*ec779b8eSAndroid Build Coastguard Worker     String8 result;
608*ec779b8eSAndroid Build Coastguard Worker     SortedVector< sp<Client> > clients; //to serialise the mutex unlock & client destruction.
609*ec779b8eSAndroid Build Coastguard Worker     SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
610*ec779b8eSAndroid Build Coastguard Worker 
611*ec779b8eSAndroid Build Coastguard Worker     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
612*ec779b8eSAndroid Build Coastguard Worker         snprintf(buffer, SIZE - 1, "Permission Denial: "
613*ec779b8eSAndroid Build Coastguard Worker                 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
614*ec779b8eSAndroid Build Coastguard Worker                 IPCThreadState::self()->getCallingPid(),
615*ec779b8eSAndroid Build Coastguard Worker                 IPCThreadState::self()->getCallingUid());
616*ec779b8eSAndroid Build Coastguard Worker         result.append(buffer);
617*ec779b8eSAndroid Build Coastguard Worker     } else {
618*ec779b8eSAndroid Build Coastguard Worker         {
619*ec779b8eSAndroid Build Coastguard Worker             // capture clients under lock
620*ec779b8eSAndroid Build Coastguard Worker             Mutex::Autolock lock(mLock);
621*ec779b8eSAndroid Build Coastguard Worker             for (int i = 0, n = mClients.size(); i < n; ++i) {
622*ec779b8eSAndroid Build Coastguard Worker                 sp<Client> c = mClients[i].promote();
623*ec779b8eSAndroid Build Coastguard Worker                 if (c != nullptr) {
624*ec779b8eSAndroid Build Coastguard Worker                     clients.add(c);
625*ec779b8eSAndroid Build Coastguard Worker                 }
626*ec779b8eSAndroid Build Coastguard Worker             }
627*ec779b8eSAndroid Build Coastguard Worker 
628*ec779b8eSAndroid Build Coastguard Worker             for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
629*ec779b8eSAndroid Build Coastguard Worker                 sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
630*ec779b8eSAndroid Build Coastguard Worker                 if (c != nullptr) {
631*ec779b8eSAndroid Build Coastguard Worker                     mediaRecorderClients.add(c);
632*ec779b8eSAndroid Build Coastguard Worker                 }
633*ec779b8eSAndroid Build Coastguard Worker             }
634*ec779b8eSAndroid Build Coastguard Worker         }
635*ec779b8eSAndroid Build Coastguard Worker 
636*ec779b8eSAndroid Build Coastguard Worker         // dump clients outside of lock
637*ec779b8eSAndroid Build Coastguard Worker         for (const sp<Client> &c : clients) {
638*ec779b8eSAndroid Build Coastguard Worker             c->dump(fd, args);
639*ec779b8eSAndroid Build Coastguard Worker         }
640*ec779b8eSAndroid Build Coastguard Worker         if (mediaRecorderClients.size() == 0) {
641*ec779b8eSAndroid Build Coastguard Worker             result.append(" No media recorder client\n\n");
642*ec779b8eSAndroid Build Coastguard Worker         } else {
643*ec779b8eSAndroid Build Coastguard Worker             for (const sp<MediaRecorderClient> &c : mediaRecorderClients) {
644*ec779b8eSAndroid Build Coastguard Worker                 snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n",
645*ec779b8eSAndroid Build Coastguard Worker                         c->mAttributionSource.pid);
646*ec779b8eSAndroid Build Coastguard Worker                 result.append(buffer);
647*ec779b8eSAndroid Build Coastguard Worker                 write(fd, result.c_str(), result.size());
648*ec779b8eSAndroid Build Coastguard Worker                 result = "\n";
649*ec779b8eSAndroid Build Coastguard Worker                 c->dump(fd, args);
650*ec779b8eSAndroid Build Coastguard Worker 
651*ec779b8eSAndroid Build Coastguard Worker             }
652*ec779b8eSAndroid Build Coastguard Worker         }
653*ec779b8eSAndroid Build Coastguard Worker 
654*ec779b8eSAndroid Build Coastguard Worker         result.append(" Files opened and/or mapped:\n");
655*ec779b8eSAndroid Build Coastguard Worker         snprintf(buffer, SIZE - 1, "/proc/%d/maps", getpid());
656*ec779b8eSAndroid Build Coastguard Worker         FILE *f = fopen(buffer, "r");
657*ec779b8eSAndroid Build Coastguard Worker         if (f) {
658*ec779b8eSAndroid Build Coastguard Worker             while (!feof(f)) {
659*ec779b8eSAndroid Build Coastguard Worker                 fgets(buffer, SIZE - 1, f);
660*ec779b8eSAndroid Build Coastguard Worker                 if (strstr(buffer, " /storage/") ||
661*ec779b8eSAndroid Build Coastguard Worker                     strstr(buffer, " /system/sounds/") ||
662*ec779b8eSAndroid Build Coastguard Worker                     strstr(buffer, " /data/") ||
663*ec779b8eSAndroid Build Coastguard Worker                     strstr(buffer, " /system/media/")) {
664*ec779b8eSAndroid Build Coastguard Worker                     result.append("  ");
665*ec779b8eSAndroid Build Coastguard Worker                     result.append(buffer);
666*ec779b8eSAndroid Build Coastguard Worker                 }
667*ec779b8eSAndroid Build Coastguard Worker             }
668*ec779b8eSAndroid Build Coastguard Worker             fclose(f);
669*ec779b8eSAndroid Build Coastguard Worker         } else {
670*ec779b8eSAndroid Build Coastguard Worker             result.append("couldn't open ");
671*ec779b8eSAndroid Build Coastguard Worker             result.append(buffer);
672*ec779b8eSAndroid Build Coastguard Worker             result.append("\n");
673*ec779b8eSAndroid Build Coastguard Worker         }
674*ec779b8eSAndroid Build Coastguard Worker 
675*ec779b8eSAndroid Build Coastguard Worker         snprintf(buffer, SIZE - 1, "/proc/%d/fd", getpid());
676*ec779b8eSAndroid Build Coastguard Worker         DIR *d = opendir(buffer);
677*ec779b8eSAndroid Build Coastguard Worker         if (d) {
678*ec779b8eSAndroid Build Coastguard Worker             struct dirent *ent;
679*ec779b8eSAndroid Build Coastguard Worker             while((ent = readdir(d)) != NULL) {
680*ec779b8eSAndroid Build Coastguard Worker                 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
681*ec779b8eSAndroid Build Coastguard Worker                     snprintf(buffer, SIZE - 1, "/proc/%d/fd/%s", getpid(), ent->d_name);
682*ec779b8eSAndroid Build Coastguard Worker                     struct stat s;
683*ec779b8eSAndroid Build Coastguard Worker                     if (lstat(buffer, &s) == 0) {
684*ec779b8eSAndroid Build Coastguard Worker                         if ((s.st_mode & S_IFMT) == S_IFLNK) {
685*ec779b8eSAndroid Build Coastguard Worker                             char linkto[256];
686*ec779b8eSAndroid Build Coastguard Worker                             int len = readlink(buffer, linkto, sizeof(linkto));
687*ec779b8eSAndroid Build Coastguard Worker                             if(len > 0) {
688*ec779b8eSAndroid Build Coastguard Worker                                 if(len > 255) {
689*ec779b8eSAndroid Build Coastguard Worker                                     linkto[252] = '.';
690*ec779b8eSAndroid Build Coastguard Worker                                     linkto[253] = '.';
691*ec779b8eSAndroid Build Coastguard Worker                                     linkto[254] = '.';
692*ec779b8eSAndroid Build Coastguard Worker                                     linkto[255] = 0;
693*ec779b8eSAndroid Build Coastguard Worker                                 } else {
694*ec779b8eSAndroid Build Coastguard Worker                                     linkto[len] = 0;
695*ec779b8eSAndroid Build Coastguard Worker                                 }
696*ec779b8eSAndroid Build Coastguard Worker                                 if (strstr(linkto, "/storage/") == linkto ||
697*ec779b8eSAndroid Build Coastguard Worker                                     strstr(linkto, "/system/sounds/") == linkto ||
698*ec779b8eSAndroid Build Coastguard Worker                                     strstr(linkto, "/data/") == linkto ||
699*ec779b8eSAndroid Build Coastguard Worker                                     strstr(linkto, "/system/media/") == linkto) {
700*ec779b8eSAndroid Build Coastguard Worker                                     result.append("  ");
701*ec779b8eSAndroid Build Coastguard Worker                                     result.append(buffer);
702*ec779b8eSAndroid Build Coastguard Worker                                     result.append(" -> ");
703*ec779b8eSAndroid Build Coastguard Worker                                     result.append(linkto);
704*ec779b8eSAndroid Build Coastguard Worker                                     result.append("\n");
705*ec779b8eSAndroid Build Coastguard Worker                                 }
706*ec779b8eSAndroid Build Coastguard Worker                             }
707*ec779b8eSAndroid Build Coastguard Worker                         } else {
708*ec779b8eSAndroid Build Coastguard Worker                             result.append("  unexpected type for ");
709*ec779b8eSAndroid Build Coastguard Worker                             result.append(buffer);
710*ec779b8eSAndroid Build Coastguard Worker                             result.append("\n");
711*ec779b8eSAndroid Build Coastguard Worker                         }
712*ec779b8eSAndroid Build Coastguard Worker                     }
713*ec779b8eSAndroid Build Coastguard Worker                 }
714*ec779b8eSAndroid Build Coastguard Worker             }
715*ec779b8eSAndroid Build Coastguard Worker             closedir(d);
716*ec779b8eSAndroid Build Coastguard Worker         } else {
717*ec779b8eSAndroid Build Coastguard Worker             result.append("couldn't open ");
718*ec779b8eSAndroid Build Coastguard Worker             result.append(buffer);
719*ec779b8eSAndroid Build Coastguard Worker             result.append("\n");
720*ec779b8eSAndroid Build Coastguard Worker         }
721*ec779b8eSAndroid Build Coastguard Worker 
722*ec779b8eSAndroid Build Coastguard Worker         gLooperRoster.dump(fd, args);
723*ec779b8eSAndroid Build Coastguard Worker 
724*ec779b8eSAndroid Build Coastguard Worker         sp<IMediaCodecList> codecList = getCodecList();
725*ec779b8eSAndroid Build Coastguard Worker         dumpCodecDetails(fd, codecList, true /* decoders */);
726*ec779b8eSAndroid Build Coastguard Worker         dumpCodecDetails(fd, codecList, false /* !decoders */);
727*ec779b8eSAndroid Build Coastguard Worker 
728*ec779b8eSAndroid Build Coastguard Worker         bool dumpMem = false;
729*ec779b8eSAndroid Build Coastguard Worker         bool unreachableMemory = false;
730*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < args.size(); i++) {
731*ec779b8eSAndroid Build Coastguard Worker             if (args[i] == String16("-m")) {
732*ec779b8eSAndroid Build Coastguard Worker                 dumpMem = true;
733*ec779b8eSAndroid Build Coastguard Worker             } else if (args[i] == String16("--unreachable")) {
734*ec779b8eSAndroid Build Coastguard Worker                 unreachableMemory = true;
735*ec779b8eSAndroid Build Coastguard Worker             }
736*ec779b8eSAndroid Build Coastguard Worker         }
737*ec779b8eSAndroid Build Coastguard Worker         if (dumpMem) {
738*ec779b8eSAndroid Build Coastguard Worker             result.append("\nDumping memory:\n");
739*ec779b8eSAndroid Build Coastguard Worker             std::string s = dumpMemoryAddresses(100 /* limit */);
740*ec779b8eSAndroid Build Coastguard Worker             result.append(s.c_str(), s.size());
741*ec779b8eSAndroid Build Coastguard Worker         }
742*ec779b8eSAndroid Build Coastguard Worker         if (unreachableMemory) {
743*ec779b8eSAndroid Build Coastguard Worker             result.append("\nDumping unreachable memory:\n");
744*ec779b8eSAndroid Build Coastguard Worker             // TODO - should limit be an argument parameter?
745*ec779b8eSAndroid Build Coastguard Worker             std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
746*ec779b8eSAndroid Build Coastguard Worker             result.append(s.c_str(), s.size());
747*ec779b8eSAndroid Build Coastguard Worker         }
748*ec779b8eSAndroid Build Coastguard Worker     }
749*ec779b8eSAndroid Build Coastguard Worker     write(fd, result.c_str(), result.size());
750*ec779b8eSAndroid Build Coastguard Worker 
751*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
752*ec779b8eSAndroid Build Coastguard Worker }
753*ec779b8eSAndroid Build Coastguard Worker 
removeClient(const wp<Client> & client)754*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::removeClient(const wp<Client>& client)
755*ec779b8eSAndroid Build Coastguard Worker {
756*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
757*ec779b8eSAndroid Build Coastguard Worker     mClients.remove(client);
758*ec779b8eSAndroid Build Coastguard Worker }
759*ec779b8eSAndroid Build Coastguard Worker 
hasClient(wp<Client> client)760*ec779b8eSAndroid Build Coastguard Worker bool MediaPlayerService::hasClient(wp<Client> client)
761*ec779b8eSAndroid Build Coastguard Worker {
762*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
763*ec779b8eSAndroid Build Coastguard Worker     return mClients.indexOf(client) != NAME_NOT_FOUND;
764*ec779b8eSAndroid Build Coastguard Worker }
765*ec779b8eSAndroid Build Coastguard Worker 
Client(const sp<MediaPlayerService> & service,const AttributionSourceState & attributionSource,int32_t connId,const sp<IMediaPlayerClient> & client,audio_session_t audioSessionId)766*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::Client::Client(
767*ec779b8eSAndroid Build Coastguard Worker         const sp<MediaPlayerService>& service, const AttributionSourceState& attributionSource,
768*ec779b8eSAndroid Build Coastguard Worker         int32_t connId, const sp<IMediaPlayerClient>& client,
769*ec779b8eSAndroid Build Coastguard Worker         audio_session_t audioSessionId)
770*ec779b8eSAndroid Build Coastguard Worker         : mAttributionSource(attributionSource)
771*ec779b8eSAndroid Build Coastguard Worker {
772*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Client(%d) constructor", connId);
773*ec779b8eSAndroid Build Coastguard Worker     mConnId = connId;
774*ec779b8eSAndroid Build Coastguard Worker     mService = service;
775*ec779b8eSAndroid Build Coastguard Worker     mClient = client;
776*ec779b8eSAndroid Build Coastguard Worker     mLoop = false;
777*ec779b8eSAndroid Build Coastguard Worker     mStatus = NO_INIT;
778*ec779b8eSAndroid Build Coastguard Worker     mAudioSessionId = audioSessionId;
779*ec779b8eSAndroid Build Coastguard Worker     mRetransmitEndpointValid = false;
780*ec779b8eSAndroid Build Coastguard Worker     mAudioAttributes = NULL;
781*ec779b8eSAndroid Build Coastguard Worker     mListener = new Listener(this);
782*ec779b8eSAndroid Build Coastguard Worker 
783*ec779b8eSAndroid Build Coastguard Worker #if CALLBACK_ANTAGONIZER
784*ec779b8eSAndroid Build Coastguard Worker     ALOGD("create Antagonizer");
785*ec779b8eSAndroid Build Coastguard Worker     mAntagonizer = new Antagonizer(mListener);
786*ec779b8eSAndroid Build Coastguard Worker #endif
787*ec779b8eSAndroid Build Coastguard Worker }
788*ec779b8eSAndroid Build Coastguard Worker 
~Client()789*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::Client::~Client()
790*ec779b8eSAndroid Build Coastguard Worker {
791*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Client(%d) destructor AttributionSource = %s", mConnId,
792*ec779b8eSAndroid Build Coastguard Worker             mAttributionSource.toString().c_str());
793*ec779b8eSAndroid Build Coastguard Worker     mAudioOutput.clear();
794*ec779b8eSAndroid Build Coastguard Worker     wp<Client> client(this);
795*ec779b8eSAndroid Build Coastguard Worker     disconnect();
796*ec779b8eSAndroid Build Coastguard Worker     mService->removeClient(client);
797*ec779b8eSAndroid Build Coastguard Worker     if (mAudioAttributes != NULL) {
798*ec779b8eSAndroid Build Coastguard Worker         free(mAudioAttributes);
799*ec779b8eSAndroid Build Coastguard Worker     }
800*ec779b8eSAndroid Build Coastguard Worker     mAudioDeviceUpdatedListener.clear();
801*ec779b8eSAndroid Build Coastguard Worker }
802*ec779b8eSAndroid Build Coastguard Worker 
disconnect()803*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::Client::disconnect()
804*ec779b8eSAndroid Build Coastguard Worker {
805*ec779b8eSAndroid Build Coastguard Worker     ALOGV("disconnect(%d) from AttributionSource %s", mConnId,
806*ec779b8eSAndroid Build Coastguard Worker             mAttributionSource.toString().c_str());
807*ec779b8eSAndroid Build Coastguard Worker     // grab local reference and clear main reference to prevent future
808*ec779b8eSAndroid Build Coastguard Worker     // access to object
809*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p;
810*ec779b8eSAndroid Build Coastguard Worker     {
811*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
812*ec779b8eSAndroid Build Coastguard Worker         p = mPlayer;
813*ec779b8eSAndroid Build Coastguard Worker         mClient.clear();
814*ec779b8eSAndroid Build Coastguard Worker         mPlayer.clear();
815*ec779b8eSAndroid Build Coastguard Worker     }
816*ec779b8eSAndroid Build Coastguard Worker 
817*ec779b8eSAndroid Build Coastguard Worker     // clear the notification to prevent callbacks to dead client
818*ec779b8eSAndroid Build Coastguard Worker     // and reset the player. We assume the player will serialize
819*ec779b8eSAndroid Build Coastguard Worker     // access to itself if necessary.
820*ec779b8eSAndroid Build Coastguard Worker     if (p != 0) {
821*ec779b8eSAndroid Build Coastguard Worker         p->setNotifyCallback(0);
822*ec779b8eSAndroid Build Coastguard Worker #if CALLBACK_ANTAGONIZER
823*ec779b8eSAndroid Build Coastguard Worker         ALOGD("kill Antagonizer");
824*ec779b8eSAndroid Build Coastguard Worker         mAntagonizer->kill();
825*ec779b8eSAndroid Build Coastguard Worker #endif
826*ec779b8eSAndroid Build Coastguard Worker         p->reset();
827*ec779b8eSAndroid Build Coastguard Worker     }
828*ec779b8eSAndroid Build Coastguard Worker 
829*ec779b8eSAndroid Build Coastguard Worker     {
830*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
831*ec779b8eSAndroid Build Coastguard Worker         disconnectNativeWindow_l();
832*ec779b8eSAndroid Build Coastguard Worker     }
833*ec779b8eSAndroid Build Coastguard Worker 
834*ec779b8eSAndroid Build Coastguard Worker     IPCThreadState::self()->flushCommands();
835*ec779b8eSAndroid Build Coastguard Worker }
836*ec779b8eSAndroid Build Coastguard Worker 
createPlayer(player_type playerType)837*ec779b8eSAndroid Build Coastguard Worker sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
838*ec779b8eSAndroid Build Coastguard Worker {
839*ec779b8eSAndroid Build Coastguard Worker     // determine if we have the right player type
840*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
841*ec779b8eSAndroid Build Coastguard Worker     if ((p != NULL) && (p->playerType() != playerType)) {
842*ec779b8eSAndroid Build Coastguard Worker         ALOGV("delete player");
843*ec779b8eSAndroid Build Coastguard Worker         p.clear();
844*ec779b8eSAndroid Build Coastguard Worker     }
845*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
846*ec779b8eSAndroid Build Coastguard Worker         p = MediaPlayerFactory::createPlayer(playerType, mListener,
847*ec779b8eSAndroid Build Coastguard Worker             VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mAttributionSource.pid)));
848*ec779b8eSAndroid Build Coastguard Worker     }
849*ec779b8eSAndroid Build Coastguard Worker 
850*ec779b8eSAndroid Build Coastguard Worker     if (p != NULL) {
851*ec779b8eSAndroid Build Coastguard Worker         p->setUID(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mAttributionSource.uid)));
852*ec779b8eSAndroid Build Coastguard Worker     }
853*ec779b8eSAndroid Build Coastguard Worker 
854*ec779b8eSAndroid Build Coastguard Worker     return p;
855*ec779b8eSAndroid Build Coastguard Worker }
856*ec779b8eSAndroid Build Coastguard Worker 
onAudioDeviceUpdate(audio_io_handle_t audioIo,const DeviceIdVector & deviceIds)857*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
858*ec779b8eSAndroid Build Coastguard Worker         audio_io_handle_t audioIo,
859*ec779b8eSAndroid Build Coastguard Worker         const DeviceIdVector& deviceIds) {
860*ec779b8eSAndroid Build Coastguard Worker     ALOGD("onAudioDeviceUpdate deviceIds: %s", toString(deviceIds).c_str());
861*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> listener = mListener.promote();
862*ec779b8eSAndroid Build Coastguard Worker     if (listener != NULL) {
863*ec779b8eSAndroid Build Coastguard Worker         // Java should query the new device ids once it gets the event.
864*ec779b8eSAndroid Build Coastguard Worker         // TODO(b/378505346): Pass the deviceIds to Java to avoid race conditions.
865*ec779b8eSAndroid Build Coastguard Worker         listener->sendEvent(MEDIA_AUDIO_ROUTING_CHANGED, audioIo);
866*ec779b8eSAndroid Build Coastguard Worker     } else {
867*ec779b8eSAndroid Build Coastguard Worker         ALOGW("listener for process %d death is gone", MEDIA_AUDIO_ROUTING_CHANGED);
868*ec779b8eSAndroid Build Coastguard Worker     }
869*ec779b8eSAndroid Build Coastguard Worker }
870*ec779b8eSAndroid Build Coastguard Worker 
setDataSource_pre(player_type playerType)871*ec779b8eSAndroid Build Coastguard Worker sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
872*ec779b8eSAndroid Build Coastguard Worker         player_type playerType)
873*ec779b8eSAndroid Build Coastguard Worker {
874*ec779b8eSAndroid Build Coastguard Worker     ALOGV("player type = %d", playerType);
875*ec779b8eSAndroid Build Coastguard Worker 
876*ec779b8eSAndroid Build Coastguard Worker     // create the right type of player
877*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = createPlayer(playerType);
878*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
879*ec779b8eSAndroid Build Coastguard Worker         return p;
880*ec779b8eSAndroid Build Coastguard Worker     }
881*ec779b8eSAndroid Build Coastguard Worker 
882*ec779b8eSAndroid Build Coastguard Worker     std::vector<DeathNotifier> deathNotifiers;
883*ec779b8eSAndroid Build Coastguard Worker 
884*ec779b8eSAndroid Build Coastguard Worker     // Listen to death of media.extractor service
885*ec779b8eSAndroid Build Coastguard Worker     sp<IServiceManager> sm = defaultServiceManager();
886*ec779b8eSAndroid Build Coastguard Worker     sp<IBinder> binder = sm->getService(String16("media.extractor"));
887*ec779b8eSAndroid Build Coastguard Worker     if (binder == NULL) {
888*ec779b8eSAndroid Build Coastguard Worker         ALOGE("extractor service not available");
889*ec779b8eSAndroid Build Coastguard Worker         return NULL;
890*ec779b8eSAndroid Build Coastguard Worker     }
891*ec779b8eSAndroid Build Coastguard Worker     deathNotifiers.emplace_back(
892*ec779b8eSAndroid Build Coastguard Worker             binder, [l = wp<MediaPlayerBase>(p)]() {
893*ec779b8eSAndroid Build Coastguard Worker         sp<MediaPlayerBase> listener = l.promote();
894*ec779b8eSAndroid Build Coastguard Worker         if (listener) {
895*ec779b8eSAndroid Build Coastguard Worker             ALOGI("media.extractor died. Sending death notification.");
896*ec779b8eSAndroid Build Coastguard Worker             listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
897*ec779b8eSAndroid Build Coastguard Worker                                 MEDIAEXTRACTOR_PROCESS_DEATH);
898*ec779b8eSAndroid Build Coastguard Worker         } else {
899*ec779b8eSAndroid Build Coastguard Worker             ALOGW("media.extractor died without a death handler.");
900*ec779b8eSAndroid Build Coastguard Worker         }
901*ec779b8eSAndroid Build Coastguard Worker     });
902*ec779b8eSAndroid Build Coastguard Worker 
903*ec779b8eSAndroid Build Coastguard Worker     {
904*ec779b8eSAndroid Build Coastguard Worker         using ::android::hidl::base::V1_0::IBase;
905*ec779b8eSAndroid Build Coastguard Worker 
906*ec779b8eSAndroid Build Coastguard Worker         // Listen to death of OMX service
907*ec779b8eSAndroid Build Coastguard Worker         {
908*ec779b8eSAndroid Build Coastguard Worker             sp<IBase> base = ::android::hardware::media::omx::V1_0::
909*ec779b8eSAndroid Build Coastguard Worker                     IOmx::getService();
910*ec779b8eSAndroid Build Coastguard Worker             if (base == nullptr) {
911*ec779b8eSAndroid Build Coastguard Worker                 ALOGD("OMX service is not available");
912*ec779b8eSAndroid Build Coastguard Worker             } else {
913*ec779b8eSAndroid Build Coastguard Worker                 deathNotifiers.emplace_back(
914*ec779b8eSAndroid Build Coastguard Worker                         base, [l = wp<MediaPlayerBase>(p)]() {
915*ec779b8eSAndroid Build Coastguard Worker                     sp<MediaPlayerBase> listener = l.promote();
916*ec779b8eSAndroid Build Coastguard Worker                     if (listener) {
917*ec779b8eSAndroid Build Coastguard Worker                         ALOGI("OMX service died. "
918*ec779b8eSAndroid Build Coastguard Worker                               "Sending death notification.");
919*ec779b8eSAndroid Build Coastguard Worker                         listener->sendEvent(
920*ec779b8eSAndroid Build Coastguard Worker                                 MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
921*ec779b8eSAndroid Build Coastguard Worker                                 MEDIACODEC_PROCESS_DEATH);
922*ec779b8eSAndroid Build Coastguard Worker                     } else {
923*ec779b8eSAndroid Build Coastguard Worker                         ALOGW("OMX service died without a death handler.");
924*ec779b8eSAndroid Build Coastguard Worker                     }
925*ec779b8eSAndroid Build Coastguard Worker                 });
926*ec779b8eSAndroid Build Coastguard Worker             }
927*ec779b8eSAndroid Build Coastguard Worker         }
928*ec779b8eSAndroid Build Coastguard Worker 
929*ec779b8eSAndroid Build Coastguard Worker         // Listen to death of Codec2 services
930*ec779b8eSAndroid Build Coastguard Worker         {
931*ec779b8eSAndroid Build Coastguard Worker             for (std::shared_ptr<Codec2Client> const& client :
932*ec779b8eSAndroid Build Coastguard Worker                     Codec2Client::CreateFromAllServices()) {
933*ec779b8eSAndroid Build Coastguard Worker                 sp<IBase> hidlBase = client->getHidlBase();
934*ec779b8eSAndroid Build Coastguard Worker                 ::ndk::SpAIBinder aidlBase = client->getAidlBase();
935*ec779b8eSAndroid Build Coastguard Worker                 auto onBinderDied = [l = wp<MediaPlayerBase>(p),
936*ec779b8eSAndroid Build Coastguard Worker                                      name = std::string(client->getServiceName())]() {
937*ec779b8eSAndroid Build Coastguard Worker                     sp<MediaPlayerBase> listener = l.promote();
938*ec779b8eSAndroid Build Coastguard Worker                     if (listener) {
939*ec779b8eSAndroid Build Coastguard Worker                         ALOGI("Codec2 service \"%s\" died. "
940*ec779b8eSAndroid Build Coastguard Worker                               "Sending death notification.",
941*ec779b8eSAndroid Build Coastguard Worker                               name.c_str());
942*ec779b8eSAndroid Build Coastguard Worker                         listener->sendEvent(
943*ec779b8eSAndroid Build Coastguard Worker                                 MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
944*ec779b8eSAndroid Build Coastguard Worker                                 MEDIACODEC_PROCESS_DEATH);
945*ec779b8eSAndroid Build Coastguard Worker                     } else {
946*ec779b8eSAndroid Build Coastguard Worker                         ALOGW("Codec2 service \"%s\" died "
947*ec779b8eSAndroid Build Coastguard Worker                               "without a death handler.",
948*ec779b8eSAndroid Build Coastguard Worker                               name.c_str());
949*ec779b8eSAndroid Build Coastguard Worker                     }
950*ec779b8eSAndroid Build Coastguard Worker                 };
951*ec779b8eSAndroid Build Coastguard Worker                 if (hidlBase) {
952*ec779b8eSAndroid Build Coastguard Worker                     deathNotifiers.emplace_back(hidlBase, onBinderDied);
953*ec779b8eSAndroid Build Coastguard Worker                 } else if (aidlBase.get() != nullptr) {
954*ec779b8eSAndroid Build Coastguard Worker                     deathNotifiers.emplace_back(aidlBase, onBinderDied);
955*ec779b8eSAndroid Build Coastguard Worker                 }
956*ec779b8eSAndroid Build Coastguard Worker             }
957*ec779b8eSAndroid Build Coastguard Worker         }
958*ec779b8eSAndroid Build Coastguard Worker     }
959*ec779b8eSAndroid Build Coastguard Worker 
960*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
961*ec779b8eSAndroid Build Coastguard Worker 
962*ec779b8eSAndroid Build Coastguard Worker     mDeathNotifiers.clear();
963*ec779b8eSAndroid Build Coastguard Worker     mDeathNotifiers.swap(deathNotifiers);
964*ec779b8eSAndroid Build Coastguard Worker     mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
965*ec779b8eSAndroid Build Coastguard Worker 
966*ec779b8eSAndroid Build Coastguard Worker     if (!p->hardwareOutput()) {
967*ec779b8eSAndroid Build Coastguard Worker         mAudioOutput = new AudioOutput(mAudioSessionId, mAttributionSource,
968*ec779b8eSAndroid Build Coastguard Worker                 mAudioAttributes, mAudioDeviceUpdatedListener);
969*ec779b8eSAndroid Build Coastguard Worker         static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
970*ec779b8eSAndroid Build Coastguard Worker     }
971*ec779b8eSAndroid Build Coastguard Worker 
972*ec779b8eSAndroid Build Coastguard Worker     return p;
973*ec779b8eSAndroid Build Coastguard Worker }
974*ec779b8eSAndroid Build Coastguard Worker 
setDataSource_post(const sp<MediaPlayerBase> & p,status_t status)975*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setDataSource_post(
976*ec779b8eSAndroid Build Coastguard Worker         const sp<MediaPlayerBase>& p,
977*ec779b8eSAndroid Build Coastguard Worker         status_t status)
978*ec779b8eSAndroid Build Coastguard Worker {
979*ec779b8eSAndroid Build Coastguard Worker     ALOGV(" setDataSource");
980*ec779b8eSAndroid Build Coastguard Worker     if (status != OK) {
981*ec779b8eSAndroid Build Coastguard Worker         ALOGE("  error: %d", status);
982*ec779b8eSAndroid Build Coastguard Worker         return status;
983*ec779b8eSAndroid Build Coastguard Worker     }
984*ec779b8eSAndroid Build Coastguard Worker 
985*ec779b8eSAndroid Build Coastguard Worker     // Set the re-transmission endpoint if one was chosen.
986*ec779b8eSAndroid Build Coastguard Worker     if (mRetransmitEndpointValid) {
987*ec779b8eSAndroid Build Coastguard Worker         status = p->setRetransmitEndpoint(&mRetransmitEndpoint);
988*ec779b8eSAndroid Build Coastguard Worker         if (status != NO_ERROR) {
989*ec779b8eSAndroid Build Coastguard Worker             ALOGE("setRetransmitEndpoint error: %d", status);
990*ec779b8eSAndroid Build Coastguard Worker         }
991*ec779b8eSAndroid Build Coastguard Worker     }
992*ec779b8eSAndroid Build Coastguard Worker 
993*ec779b8eSAndroid Build Coastguard Worker     if (status == OK) {
994*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
995*ec779b8eSAndroid Build Coastguard Worker         mPlayer = p;
996*ec779b8eSAndroid Build Coastguard Worker     }
997*ec779b8eSAndroid Build Coastguard Worker     return status;
998*ec779b8eSAndroid Build Coastguard Worker }
999*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)1000*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setDataSource(
1001*ec779b8eSAndroid Build Coastguard Worker         const sp<IMediaHTTPService> &httpService,
1002*ec779b8eSAndroid Build Coastguard Worker         const char *url,
1003*ec779b8eSAndroid Build Coastguard Worker         const KeyedVector<String8, String8> *headers)
1004*ec779b8eSAndroid Build Coastguard Worker {
1005*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource(%s)", url);
1006*ec779b8eSAndroid Build Coastguard Worker     if (url == NULL)
1007*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1008*ec779b8eSAndroid Build Coastguard Worker 
1009*ec779b8eSAndroid Build Coastguard Worker     if ((strncmp(url, "http://", 7) == 0) ||
1010*ec779b8eSAndroid Build Coastguard Worker         (strncmp(url, "https://", 8) == 0) ||
1011*ec779b8eSAndroid Build Coastguard Worker         (strncmp(url, "rtsp://", 7) == 0)) {
1012*ec779b8eSAndroid Build Coastguard Worker         if (!checkPermission("android.permission.INTERNET")) {
1013*ec779b8eSAndroid Build Coastguard Worker             return PERMISSION_DENIED;
1014*ec779b8eSAndroid Build Coastguard Worker         }
1015*ec779b8eSAndroid Build Coastguard Worker     }
1016*ec779b8eSAndroid Build Coastguard Worker 
1017*ec779b8eSAndroid Build Coastguard Worker     if (strncmp(url, "content://", 10) == 0) {
1018*ec779b8eSAndroid Build Coastguard Worker         // get a filedescriptor for the content Uri and
1019*ec779b8eSAndroid Build Coastguard Worker         // pass it to the setDataSource(fd) method
1020*ec779b8eSAndroid Build Coastguard Worker 
1021*ec779b8eSAndroid Build Coastguard Worker         String16 url16(url);
1022*ec779b8eSAndroid Build Coastguard Worker         int fd = android::openContentProviderFile(url16);
1023*ec779b8eSAndroid Build Coastguard Worker         if (fd < 0)
1024*ec779b8eSAndroid Build Coastguard Worker         {
1025*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Couldn't open fd for %s", url);
1026*ec779b8eSAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
1027*ec779b8eSAndroid Build Coastguard Worker         }
1028*ec779b8eSAndroid Build Coastguard Worker         status_t status = setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
1029*ec779b8eSAndroid Build Coastguard Worker         close(fd);
1030*ec779b8eSAndroid Build Coastguard Worker         return mStatus = status;
1031*ec779b8eSAndroid Build Coastguard Worker     } else {
1032*ec779b8eSAndroid Build Coastguard Worker         player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
1033*ec779b8eSAndroid Build Coastguard Worker         sp<MediaPlayerBase> p = setDataSource_pre(playerType);
1034*ec779b8eSAndroid Build Coastguard Worker         if (p == NULL) {
1035*ec779b8eSAndroid Build Coastguard Worker             return NO_INIT;
1036*ec779b8eSAndroid Build Coastguard Worker         }
1037*ec779b8eSAndroid Build Coastguard Worker 
1038*ec779b8eSAndroid Build Coastguard Worker         return mStatus =
1039*ec779b8eSAndroid Build Coastguard Worker                 setDataSource_post(
1040*ec779b8eSAndroid Build Coastguard Worker                 p, p->setDataSource(httpService, url, headers));
1041*ec779b8eSAndroid Build Coastguard Worker     }
1042*ec779b8eSAndroid Build Coastguard Worker }
1043*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(int fd,int64_t offset,int64_t length)1044*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
1045*ec779b8eSAndroid Build Coastguard Worker {
1046*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
1047*ec779b8eSAndroid Build Coastguard Worker             fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
1048*ec779b8eSAndroid Build Coastguard Worker     struct stat sb;
1049*ec779b8eSAndroid Build Coastguard Worker     int ret = fstat(fd, &sb);
1050*ec779b8eSAndroid Build Coastguard Worker     if (ret != 0) {
1051*ec779b8eSAndroid Build Coastguard Worker         ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
1052*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1053*ec779b8eSAndroid Build Coastguard Worker     }
1054*ec779b8eSAndroid Build Coastguard Worker 
1055*ec779b8eSAndroid Build Coastguard Worker     ALOGV("st_dev  = %llu", static_cast<unsigned long long>(sb.st_dev));
1056*ec779b8eSAndroid Build Coastguard Worker     ALOGV("st_mode = %u", sb.st_mode);
1057*ec779b8eSAndroid Build Coastguard Worker     ALOGV("st_uid  = %lu", static_cast<unsigned long>(sb.st_uid));
1058*ec779b8eSAndroid Build Coastguard Worker     ALOGV("st_gid  = %lu", static_cast<unsigned long>(sb.st_gid));
1059*ec779b8eSAndroid Build Coastguard Worker     ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
1060*ec779b8eSAndroid Build Coastguard Worker 
1061*ec779b8eSAndroid Build Coastguard Worker     if (offset >= sb.st_size) {
1062*ec779b8eSAndroid Build Coastguard Worker         ALOGE("offset error");
1063*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1064*ec779b8eSAndroid Build Coastguard Worker     }
1065*ec779b8eSAndroid Build Coastguard Worker     if (offset + length > sb.st_size) {
1066*ec779b8eSAndroid Build Coastguard Worker         length = sb.st_size - offset;
1067*ec779b8eSAndroid Build Coastguard Worker         ALOGV("calculated length = %lld", (long long)length);
1068*ec779b8eSAndroid Build Coastguard Worker     }
1069*ec779b8eSAndroid Build Coastguard Worker 
1070*ec779b8eSAndroid Build Coastguard Worker     player_type playerType = MediaPlayerFactory::getPlayerType(this,
1071*ec779b8eSAndroid Build Coastguard Worker                                                                fd,
1072*ec779b8eSAndroid Build Coastguard Worker                                                                offset,
1073*ec779b8eSAndroid Build Coastguard Worker                                                                length);
1074*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = setDataSource_pre(playerType);
1075*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
1076*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
1077*ec779b8eSAndroid Build Coastguard Worker     }
1078*ec779b8eSAndroid Build Coastguard Worker 
1079*ec779b8eSAndroid Build Coastguard Worker     // now set data source
1080*ec779b8eSAndroid Build Coastguard Worker     return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
1081*ec779b8eSAndroid Build Coastguard Worker }
1082*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IStreamSource> & source)1083*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setDataSource(
1084*ec779b8eSAndroid Build Coastguard Worker         const sp<IStreamSource> &source) {
1085*ec779b8eSAndroid Build Coastguard Worker     // create the right type of player
1086*ec779b8eSAndroid Build Coastguard Worker     player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
1087*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = setDataSource_pre(playerType);
1088*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
1089*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
1090*ec779b8eSAndroid Build Coastguard Worker     }
1091*ec779b8eSAndroid Build Coastguard Worker 
1092*ec779b8eSAndroid Build Coastguard Worker     // now set data source
1093*ec779b8eSAndroid Build Coastguard Worker     return mStatus = setDataSource_post(p, p->setDataSource(source));
1094*ec779b8eSAndroid Build Coastguard Worker }
1095*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IDataSource> & source)1096*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setDataSource(
1097*ec779b8eSAndroid Build Coastguard Worker         const sp<IDataSource> &source) {
1098*ec779b8eSAndroid Build Coastguard Worker     sp<DataSource> dataSource = CreateDataSourceFromIDataSource(source);
1099*ec779b8eSAndroid Build Coastguard Worker     player_type playerType = MediaPlayerFactory::getPlayerType(this, dataSource);
1100*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = setDataSource_pre(playerType);
1101*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
1102*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
1103*ec779b8eSAndroid Build Coastguard Worker     }
1104*ec779b8eSAndroid Build Coastguard Worker     // now set data source
1105*ec779b8eSAndroid Build Coastguard Worker     return mStatus = setDataSource_post(p, p->setDataSource(dataSource));
1106*ec779b8eSAndroid Build Coastguard Worker }
1107*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const String8 & rtpParams)1108*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setDataSource(
1109*ec779b8eSAndroid Build Coastguard Worker         const String8& rtpParams) {
1110*ec779b8eSAndroid Build Coastguard Worker     player_type playerType = NU_PLAYER;
1111*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = setDataSource_pre(playerType);
1112*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
1113*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
1114*ec779b8eSAndroid Build Coastguard Worker     }
1115*ec779b8eSAndroid Build Coastguard Worker     // now set data source
1116*ec779b8eSAndroid Build Coastguard Worker     return mStatus = setDataSource_post(p, p->setDataSource(rtpParams));
1117*ec779b8eSAndroid Build Coastguard Worker }
1118*ec779b8eSAndroid Build Coastguard Worker 
disconnectNativeWindow_l()1119*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::Client::disconnectNativeWindow_l() {
1120*ec779b8eSAndroid Build Coastguard Worker     if (mConnectedWindow != NULL) {
1121*ec779b8eSAndroid Build Coastguard Worker         status_t err = nativeWindowDisconnect(
1122*ec779b8eSAndroid Build Coastguard Worker                 mConnectedWindow.get(), "disconnectNativeWindow");
1123*ec779b8eSAndroid Build Coastguard Worker 
1124*ec779b8eSAndroid Build Coastguard Worker         if (err != OK) {
1125*ec779b8eSAndroid Build Coastguard Worker             ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
1126*ec779b8eSAndroid Build Coastguard Worker                     strerror(-err), err);
1127*ec779b8eSAndroid Build Coastguard Worker         }
1128*ec779b8eSAndroid Build Coastguard Worker     }
1129*ec779b8eSAndroid Build Coastguard Worker     mConnectedWindow.clear();
1130*ec779b8eSAndroid Build Coastguard Worker }
1131*ec779b8eSAndroid Build Coastguard Worker 
setVideoSurfaceTexture(const sp<IGraphicBufferProducer> & bufferProducer)1132*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setVideoSurfaceTexture(
1133*ec779b8eSAndroid Build Coastguard Worker         const sp<IGraphicBufferProducer>& bufferProducer)
1134*ec779b8eSAndroid Build Coastguard Worker {
1135*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
1136*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1137*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1138*ec779b8eSAndroid Build Coastguard Worker 
1139*ec779b8eSAndroid Build Coastguard Worker     sp<IBinder> binder(IInterface::asBinder(bufferProducer));
1140*ec779b8eSAndroid Build Coastguard Worker     if (mConnectedWindowBinder == binder) {
1141*ec779b8eSAndroid Build Coastguard Worker         return OK;
1142*ec779b8eSAndroid Build Coastguard Worker     }
1143*ec779b8eSAndroid Build Coastguard Worker 
1144*ec779b8eSAndroid Build Coastguard Worker     sp<ANativeWindow> anw;
1145*ec779b8eSAndroid Build Coastguard Worker     if (bufferProducer != NULL) {
1146*ec779b8eSAndroid Build Coastguard Worker         anw = new Surface(bufferProducer, true /* controlledByApp */);
1147*ec779b8eSAndroid Build Coastguard Worker         status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
1148*ec779b8eSAndroid Build Coastguard Worker 
1149*ec779b8eSAndroid Build Coastguard Worker         if (err != OK) {
1150*ec779b8eSAndroid Build Coastguard Worker             ALOGE("setVideoSurfaceTexture failed: %d", err);
1151*ec779b8eSAndroid Build Coastguard Worker             // Note that we must do the reset before disconnecting from the ANW.
1152*ec779b8eSAndroid Build Coastguard Worker             // Otherwise queue/dequeue calls could be made on the disconnected
1153*ec779b8eSAndroid Build Coastguard Worker             // ANW, which may result in errors.
1154*ec779b8eSAndroid Build Coastguard Worker             reset();
1155*ec779b8eSAndroid Build Coastguard Worker 
1156*ec779b8eSAndroid Build Coastguard Worker             Mutex::Autolock lock(mLock);
1157*ec779b8eSAndroid Build Coastguard Worker             disconnectNativeWindow_l();
1158*ec779b8eSAndroid Build Coastguard Worker 
1159*ec779b8eSAndroid Build Coastguard Worker             return err;
1160*ec779b8eSAndroid Build Coastguard Worker         }
1161*ec779b8eSAndroid Build Coastguard Worker     }
1162*ec779b8eSAndroid Build Coastguard Worker 
1163*ec779b8eSAndroid Build Coastguard Worker     // Note that we must set the player's new GraphicBufferProducer before
1164*ec779b8eSAndroid Build Coastguard Worker     // disconnecting the old one.  Otherwise queue/dequeue calls could be made
1165*ec779b8eSAndroid Build Coastguard Worker     // on the disconnected ANW, which may result in errors.
1166*ec779b8eSAndroid Build Coastguard Worker     status_t err = p->setVideoSurfaceTexture(bufferProducer);
1167*ec779b8eSAndroid Build Coastguard Worker 
1168*ec779b8eSAndroid Build Coastguard Worker     mLock.lock();
1169*ec779b8eSAndroid Build Coastguard Worker     disconnectNativeWindow_l();
1170*ec779b8eSAndroid Build Coastguard Worker 
1171*ec779b8eSAndroid Build Coastguard Worker     if (err == OK) {
1172*ec779b8eSAndroid Build Coastguard Worker         mConnectedWindow = anw;
1173*ec779b8eSAndroid Build Coastguard Worker         mConnectedWindowBinder = binder;
1174*ec779b8eSAndroid Build Coastguard Worker         mLock.unlock();
1175*ec779b8eSAndroid Build Coastguard Worker     } else {
1176*ec779b8eSAndroid Build Coastguard Worker         mLock.unlock();
1177*ec779b8eSAndroid Build Coastguard Worker         status_t err = nativeWindowDisconnect(
1178*ec779b8eSAndroid Build Coastguard Worker                 anw.get(), "disconnectNativeWindow");
1179*ec779b8eSAndroid Build Coastguard Worker 
1180*ec779b8eSAndroid Build Coastguard Worker         if (err != OK) {
1181*ec779b8eSAndroid Build Coastguard Worker             ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
1182*ec779b8eSAndroid Build Coastguard Worker                     strerror(-err), err);
1183*ec779b8eSAndroid Build Coastguard Worker         }
1184*ec779b8eSAndroid Build Coastguard Worker     }
1185*ec779b8eSAndroid Build Coastguard Worker 
1186*ec779b8eSAndroid Build Coastguard Worker     return err;
1187*ec779b8eSAndroid Build Coastguard Worker }
1188*ec779b8eSAndroid Build Coastguard Worker 
invoke(const Parcel & request,Parcel * reply)1189*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::invoke(const Parcel& request,
1190*ec779b8eSAndroid Build Coastguard Worker                                             Parcel *reply)
1191*ec779b8eSAndroid Build Coastguard Worker {
1192*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1193*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) return UNKNOWN_ERROR;
1194*ec779b8eSAndroid Build Coastguard Worker     return p->invoke(request, reply);
1195*ec779b8eSAndroid Build Coastguard Worker }
1196*ec779b8eSAndroid Build Coastguard Worker 
1197*ec779b8eSAndroid Build Coastguard Worker // This call doesn't need to access the native player.
setMetadataFilter(const Parcel & filter)1198*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
1199*ec779b8eSAndroid Build Coastguard Worker {
1200*ec779b8eSAndroid Build Coastguard Worker     status_t status;
1201*ec779b8eSAndroid Build Coastguard Worker     media::Metadata::Filter allow, drop;
1202*ec779b8eSAndroid Build Coastguard Worker 
1203*ec779b8eSAndroid Build Coastguard Worker     if (unmarshallFilter(filter, &allow, &status) &&
1204*ec779b8eSAndroid Build Coastguard Worker         unmarshallFilter(filter, &drop, &status)) {
1205*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
1206*ec779b8eSAndroid Build Coastguard Worker 
1207*ec779b8eSAndroid Build Coastguard Worker         mMetadataAllow = allow;
1208*ec779b8eSAndroid Build Coastguard Worker         mMetadataDrop = drop;
1209*ec779b8eSAndroid Build Coastguard Worker     }
1210*ec779b8eSAndroid Build Coastguard Worker     return status;
1211*ec779b8eSAndroid Build Coastguard Worker }
1212*ec779b8eSAndroid Build Coastguard Worker 
getMetadata(bool update_only,bool,Parcel * reply)1213*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getMetadata(
1214*ec779b8eSAndroid Build Coastguard Worker         bool update_only, bool /*apply_filter*/, Parcel *reply)
1215*ec779b8eSAndroid Build Coastguard Worker {
1216*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> player = getPlayer();
1217*ec779b8eSAndroid Build Coastguard Worker     if (player == 0) return UNKNOWN_ERROR;
1218*ec779b8eSAndroid Build Coastguard Worker 
1219*ec779b8eSAndroid Build Coastguard Worker     status_t status;
1220*ec779b8eSAndroid Build Coastguard Worker     // Placeholder for the return code, updated by the caller.
1221*ec779b8eSAndroid Build Coastguard Worker     reply->writeInt32(-1);
1222*ec779b8eSAndroid Build Coastguard Worker 
1223*ec779b8eSAndroid Build Coastguard Worker     media::Metadata::Filter ids;
1224*ec779b8eSAndroid Build Coastguard Worker 
1225*ec779b8eSAndroid Build Coastguard Worker     // We don't block notifications while we fetch the data. We clear
1226*ec779b8eSAndroid Build Coastguard Worker     // mMetadataUpdated first so we don't lose notifications happening
1227*ec779b8eSAndroid Build Coastguard Worker     // during the rest of this call.
1228*ec779b8eSAndroid Build Coastguard Worker     {
1229*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
1230*ec779b8eSAndroid Build Coastguard Worker         if (update_only) {
1231*ec779b8eSAndroid Build Coastguard Worker             ids = mMetadataUpdated;
1232*ec779b8eSAndroid Build Coastguard Worker         }
1233*ec779b8eSAndroid Build Coastguard Worker         mMetadataUpdated.clear();
1234*ec779b8eSAndroid Build Coastguard Worker     }
1235*ec779b8eSAndroid Build Coastguard Worker 
1236*ec779b8eSAndroid Build Coastguard Worker     media::Metadata metadata(reply);
1237*ec779b8eSAndroid Build Coastguard Worker 
1238*ec779b8eSAndroid Build Coastguard Worker     metadata.appendHeader();
1239*ec779b8eSAndroid Build Coastguard Worker     status = player->getMetadata(ids, reply);
1240*ec779b8eSAndroid Build Coastguard Worker 
1241*ec779b8eSAndroid Build Coastguard Worker     if (status != OK) {
1242*ec779b8eSAndroid Build Coastguard Worker         metadata.resetParcel();
1243*ec779b8eSAndroid Build Coastguard Worker         ALOGE("getMetadata failed %d", status);
1244*ec779b8eSAndroid Build Coastguard Worker         return status;
1245*ec779b8eSAndroid Build Coastguard Worker     }
1246*ec779b8eSAndroid Build Coastguard Worker 
1247*ec779b8eSAndroid Build Coastguard Worker     // FIXME: Implement filtering on the result. Not critical since
1248*ec779b8eSAndroid Build Coastguard Worker     // filtering takes place on the update notifications already. This
1249*ec779b8eSAndroid Build Coastguard Worker     // would be when all the metadata are fetch and a filter is set.
1250*ec779b8eSAndroid Build Coastguard Worker 
1251*ec779b8eSAndroid Build Coastguard Worker     // Everything is fine, update the metadata length.
1252*ec779b8eSAndroid Build Coastguard Worker     metadata.updateLength();
1253*ec779b8eSAndroid Build Coastguard Worker     return OK;
1254*ec779b8eSAndroid Build Coastguard Worker }
1255*ec779b8eSAndroid Build Coastguard Worker 
setBufferingSettings(const BufferingSettings & buffering)1256*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setBufferingSettings(
1257*ec779b8eSAndroid Build Coastguard Worker         const BufferingSettings& buffering)
1258*ec779b8eSAndroid Build Coastguard Worker {
1259*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setBufferingSettings{%s}",
1260*ec779b8eSAndroid Build Coastguard Worker             mConnId, buffering.toString().c_str());
1261*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1262*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1263*ec779b8eSAndroid Build Coastguard Worker     return p->setBufferingSettings(buffering);
1264*ec779b8eSAndroid Build Coastguard Worker }
1265*ec779b8eSAndroid Build Coastguard Worker 
getBufferingSettings(BufferingSettings * buffering)1266*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getBufferingSettings(
1267*ec779b8eSAndroid Build Coastguard Worker         BufferingSettings* buffering /* nonnull */)
1268*ec779b8eSAndroid Build Coastguard Worker {
1269*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1270*ec779b8eSAndroid Build Coastguard Worker     // TODO: create mPlayer on demand.
1271*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1272*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->getBufferingSettings(buffering);
1273*ec779b8eSAndroid Build Coastguard Worker     if (ret == NO_ERROR) {
1274*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getBufferingSettings{%s}",
1275*ec779b8eSAndroid Build Coastguard Worker                 mConnId, buffering->toString().c_str());
1276*ec779b8eSAndroid Build Coastguard Worker     } else {
1277*ec779b8eSAndroid Build Coastguard Worker         ALOGE("[%d] getBufferingSettings returned %d", mConnId, ret);
1278*ec779b8eSAndroid Build Coastguard Worker     }
1279*ec779b8eSAndroid Build Coastguard Worker     return ret;
1280*ec779b8eSAndroid Build Coastguard Worker }
1281*ec779b8eSAndroid Build Coastguard Worker 
prepareAsync()1282*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::prepareAsync()
1283*ec779b8eSAndroid Build Coastguard Worker {
1284*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] prepareAsync", mConnId);
1285*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1286*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1287*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->prepareAsync();
1288*ec779b8eSAndroid Build Coastguard Worker #if CALLBACK_ANTAGONIZER
1289*ec779b8eSAndroid Build Coastguard Worker     ALOGD("start Antagonizer");
1290*ec779b8eSAndroid Build Coastguard Worker     if (ret == NO_ERROR) mAntagonizer->start();
1291*ec779b8eSAndroid Build Coastguard Worker #endif
1292*ec779b8eSAndroid Build Coastguard Worker     return ret;
1293*ec779b8eSAndroid Build Coastguard Worker }
1294*ec779b8eSAndroid Build Coastguard Worker 
start()1295*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::start()
1296*ec779b8eSAndroid Build Coastguard Worker {
1297*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] start", mConnId);
1298*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1299*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1300*ec779b8eSAndroid Build Coastguard Worker     p->setLooping(mLoop);
1301*ec779b8eSAndroid Build Coastguard Worker     return p->start();
1302*ec779b8eSAndroid Build Coastguard Worker }
1303*ec779b8eSAndroid Build Coastguard Worker 
stop()1304*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::stop()
1305*ec779b8eSAndroid Build Coastguard Worker {
1306*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] stop", mConnId);
1307*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1308*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1309*ec779b8eSAndroid Build Coastguard Worker     return p->stop();
1310*ec779b8eSAndroid Build Coastguard Worker }
1311*ec779b8eSAndroid Build Coastguard Worker 
pause()1312*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::pause()
1313*ec779b8eSAndroid Build Coastguard Worker {
1314*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] pause", mConnId);
1315*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1316*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1317*ec779b8eSAndroid Build Coastguard Worker     return p->pause();
1318*ec779b8eSAndroid Build Coastguard Worker }
1319*ec779b8eSAndroid Build Coastguard Worker 
isPlaying(bool * state)1320*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::isPlaying(bool* state)
1321*ec779b8eSAndroid Build Coastguard Worker {
1322*ec779b8eSAndroid Build Coastguard Worker     *state = false;
1323*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1324*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1325*ec779b8eSAndroid Build Coastguard Worker     *state = p->isPlaying();
1326*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] isPlaying: %d", mConnId, *state);
1327*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1328*ec779b8eSAndroid Build Coastguard Worker }
1329*ec779b8eSAndroid Build Coastguard Worker 
setPlaybackSettings(const AudioPlaybackRate & rate)1330*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setPlaybackSettings(const AudioPlaybackRate& rate)
1331*ec779b8eSAndroid Build Coastguard Worker {
1332*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setPlaybackSettings(%f, %f, %d, %d)",
1333*ec779b8eSAndroid Build Coastguard Worker             mConnId, rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
1334*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1335*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1336*ec779b8eSAndroid Build Coastguard Worker     return p->setPlaybackSettings(rate);
1337*ec779b8eSAndroid Build Coastguard Worker }
1338*ec779b8eSAndroid Build Coastguard Worker 
getPlaybackSettings(AudioPlaybackRate * rate)1339*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
1340*ec779b8eSAndroid Build Coastguard Worker {
1341*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1342*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1343*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->getPlaybackSettings(rate);
1344*ec779b8eSAndroid Build Coastguard Worker     if (ret == NO_ERROR) {
1345*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getPlaybackSettings(%f, %f, %d, %d)",
1346*ec779b8eSAndroid Build Coastguard Worker                 mConnId, rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
1347*ec779b8eSAndroid Build Coastguard Worker     } else {
1348*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getPlaybackSettings returned %d", mConnId, ret);
1349*ec779b8eSAndroid Build Coastguard Worker     }
1350*ec779b8eSAndroid Build Coastguard Worker     return ret;
1351*ec779b8eSAndroid Build Coastguard Worker }
1352*ec779b8eSAndroid Build Coastguard Worker 
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)1353*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setSyncSettings(
1354*ec779b8eSAndroid Build Coastguard Worker         const AVSyncSettings& sync, float videoFpsHint)
1355*ec779b8eSAndroid Build Coastguard Worker {
1356*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setSyncSettings(%u, %u, %f, %f)",
1357*ec779b8eSAndroid Build Coastguard Worker             mConnId, sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
1358*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1359*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1360*ec779b8eSAndroid Build Coastguard Worker     return p->setSyncSettings(sync, videoFpsHint);
1361*ec779b8eSAndroid Build Coastguard Worker }
1362*ec779b8eSAndroid Build Coastguard Worker 
getSyncSettings(AVSyncSettings * sync,float * videoFps)1363*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getSyncSettings(
1364*ec779b8eSAndroid Build Coastguard Worker         AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
1365*ec779b8eSAndroid Build Coastguard Worker {
1366*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1367*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1368*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->getSyncSettings(sync, videoFps);
1369*ec779b8eSAndroid Build Coastguard Worker     if (ret == NO_ERROR) {
1370*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getSyncSettings(%u, %u, %f, %f)",
1371*ec779b8eSAndroid Build Coastguard Worker                 mConnId, sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
1372*ec779b8eSAndroid Build Coastguard Worker     } else {
1373*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getSyncSettings returned %d", mConnId, ret);
1374*ec779b8eSAndroid Build Coastguard Worker     }
1375*ec779b8eSAndroid Build Coastguard Worker     return ret;
1376*ec779b8eSAndroid Build Coastguard Worker }
1377*ec779b8eSAndroid Build Coastguard Worker 
getCurrentPosition(int * msec)1378*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
1379*ec779b8eSAndroid Build Coastguard Worker {
1380*ec779b8eSAndroid Build Coastguard Worker     ALOGV("getCurrentPosition");
1381*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1382*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1383*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->getCurrentPosition(msec);
1384*ec779b8eSAndroid Build Coastguard Worker     if (ret == NO_ERROR) {
1385*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
1386*ec779b8eSAndroid Build Coastguard Worker     } else {
1387*ec779b8eSAndroid Build Coastguard Worker         ALOGE("getCurrentPosition returned %d", ret);
1388*ec779b8eSAndroid Build Coastguard Worker     }
1389*ec779b8eSAndroid Build Coastguard Worker     return ret;
1390*ec779b8eSAndroid Build Coastguard Worker }
1391*ec779b8eSAndroid Build Coastguard Worker 
getDuration(int * msec)1392*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getDuration(int *msec)
1393*ec779b8eSAndroid Build Coastguard Worker {
1394*ec779b8eSAndroid Build Coastguard Worker     ALOGV("getDuration");
1395*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1396*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1397*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->getDuration(msec);
1398*ec779b8eSAndroid Build Coastguard Worker     if (ret == NO_ERROR) {
1399*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] getDuration = %d", mConnId, *msec);
1400*ec779b8eSAndroid Build Coastguard Worker     } else {
1401*ec779b8eSAndroid Build Coastguard Worker         ALOGE("getDuration returned %d", ret);
1402*ec779b8eSAndroid Build Coastguard Worker     }
1403*ec779b8eSAndroid Build Coastguard Worker     return ret;
1404*ec779b8eSAndroid Build Coastguard Worker }
1405*ec779b8eSAndroid Build Coastguard Worker 
setNextPlayer(const sp<IMediaPlayer> & player)1406*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
1407*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setNextPlayer");
1408*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock l(mLock);
1409*ec779b8eSAndroid Build Coastguard Worker     sp<Client> c = static_cast<Client*>(player.get());
1410*ec779b8eSAndroid Build Coastguard Worker     if (c != NULL && !mService->hasClient(c)) {
1411*ec779b8eSAndroid Build Coastguard Worker       return BAD_VALUE;
1412*ec779b8eSAndroid Build Coastguard Worker     }
1413*ec779b8eSAndroid Build Coastguard Worker 
1414*ec779b8eSAndroid Build Coastguard Worker     mNextClient = c;
1415*ec779b8eSAndroid Build Coastguard Worker 
1416*ec779b8eSAndroid Build Coastguard Worker     if (c != NULL) {
1417*ec779b8eSAndroid Build Coastguard Worker         if (mAudioOutput != NULL) {
1418*ec779b8eSAndroid Build Coastguard Worker             mAudioOutput->setNextOutput(c->mAudioOutput);
1419*ec779b8eSAndroid Build Coastguard Worker         } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
1420*ec779b8eSAndroid Build Coastguard Worker             ALOGE("no current audio output");
1421*ec779b8eSAndroid Build Coastguard Worker         }
1422*ec779b8eSAndroid Build Coastguard Worker 
1423*ec779b8eSAndroid Build Coastguard Worker         if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
1424*ec779b8eSAndroid Build Coastguard Worker             mPlayer->setNextPlayer(mNextClient->getPlayer());
1425*ec779b8eSAndroid Build Coastguard Worker         }
1426*ec779b8eSAndroid Build Coastguard Worker     }
1427*ec779b8eSAndroid Build Coastguard Worker 
1428*ec779b8eSAndroid Build Coastguard Worker     return OK;
1429*ec779b8eSAndroid Build Coastguard Worker }
1430*ec779b8eSAndroid Build Coastguard Worker 
applyVolumeShaper(const sp<VolumeShaper::Configuration> & configuration,const sp<VolumeShaper::Operation> & operation)1431*ec779b8eSAndroid Build Coastguard Worker VolumeShaper::Status MediaPlayerService::Client::applyVolumeShaper(
1432*ec779b8eSAndroid Build Coastguard Worker         const sp<VolumeShaper::Configuration>& configuration,
1433*ec779b8eSAndroid Build Coastguard Worker         const sp<VolumeShaper::Operation>& operation) {
1434*ec779b8eSAndroid Build Coastguard Worker     // for hardware output, call player instead
1435*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Client::applyVolumeShaper(%p)", this);
1436*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1437*ec779b8eSAndroid Build Coastguard Worker     {
1438*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1439*ec779b8eSAndroid Build Coastguard Worker         if (p != 0 && p->hardwareOutput()) {
1440*ec779b8eSAndroid Build Coastguard Worker             // TODO: investigate internal implementation
1441*ec779b8eSAndroid Build Coastguard Worker             return VolumeShaper::Status(INVALID_OPERATION);
1442*ec779b8eSAndroid Build Coastguard Worker         }
1443*ec779b8eSAndroid Build Coastguard Worker         if (mAudioOutput.get() != nullptr) {
1444*ec779b8eSAndroid Build Coastguard Worker             return mAudioOutput->applyVolumeShaper(configuration, operation);
1445*ec779b8eSAndroid Build Coastguard Worker         }
1446*ec779b8eSAndroid Build Coastguard Worker     }
1447*ec779b8eSAndroid Build Coastguard Worker     return VolumeShaper::Status(INVALID_OPERATION);
1448*ec779b8eSAndroid Build Coastguard Worker }
1449*ec779b8eSAndroid Build Coastguard Worker 
getVolumeShaperState(int id)1450*ec779b8eSAndroid Build Coastguard Worker sp<VolumeShaper::State> MediaPlayerService::Client::getVolumeShaperState(int id) {
1451*ec779b8eSAndroid Build Coastguard Worker     // for hardware output, call player instead
1452*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Client::getVolumeShaperState(%p)", this);
1453*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1454*ec779b8eSAndroid Build Coastguard Worker     {
1455*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1456*ec779b8eSAndroid Build Coastguard Worker         if (p != 0 && p->hardwareOutput()) {
1457*ec779b8eSAndroid Build Coastguard Worker             // TODO: investigate internal implementation.
1458*ec779b8eSAndroid Build Coastguard Worker             return nullptr;
1459*ec779b8eSAndroid Build Coastguard Worker         }
1460*ec779b8eSAndroid Build Coastguard Worker         if (mAudioOutput.get() != nullptr) {
1461*ec779b8eSAndroid Build Coastguard Worker             return mAudioOutput->getVolumeShaperState(id);
1462*ec779b8eSAndroid Build Coastguard Worker         }
1463*ec779b8eSAndroid Build Coastguard Worker     }
1464*ec779b8eSAndroid Build Coastguard Worker     return nullptr;
1465*ec779b8eSAndroid Build Coastguard Worker }
1466*ec779b8eSAndroid Build Coastguard Worker 
seekTo(int msec,MediaPlayerSeekMode mode)1467*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::seekTo(int msec, MediaPlayerSeekMode mode)
1468*ec779b8eSAndroid Build Coastguard Worker {
1469*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] seekTo(%d, %d)", mConnId, msec, mode);
1470*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1471*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1472*ec779b8eSAndroid Build Coastguard Worker     return p->seekTo(msec, mode);
1473*ec779b8eSAndroid Build Coastguard Worker }
1474*ec779b8eSAndroid Build Coastguard Worker 
reset()1475*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::reset()
1476*ec779b8eSAndroid Build Coastguard Worker {
1477*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] reset", mConnId);
1478*ec779b8eSAndroid Build Coastguard Worker     mRetransmitEndpointValid = false;
1479*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1480*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1481*ec779b8eSAndroid Build Coastguard Worker     return p->reset();
1482*ec779b8eSAndroid Build Coastguard Worker }
1483*ec779b8eSAndroid Build Coastguard Worker 
notifyAt(int64_t mediaTimeUs)1484*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::notifyAt(int64_t mediaTimeUs)
1485*ec779b8eSAndroid Build Coastguard Worker {
1486*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] notifyAt(%lld)", mConnId, (long long)mediaTimeUs);
1487*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1488*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1489*ec779b8eSAndroid Build Coastguard Worker     return p->notifyAt(mediaTimeUs);
1490*ec779b8eSAndroid Build Coastguard Worker }
1491*ec779b8eSAndroid Build Coastguard Worker 
setAudioStreamType(audio_stream_type_t type)1492*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
1493*ec779b8eSAndroid Build Coastguard Worker {
1494*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
1495*ec779b8eSAndroid Build Coastguard Worker     // TODO: for hardware output, call player instead
1496*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock l(mLock);
1497*ec779b8eSAndroid Build Coastguard Worker     if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1498*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1499*ec779b8eSAndroid Build Coastguard Worker }
1500*ec779b8eSAndroid Build Coastguard Worker 
setAudioAttributes_l(const Parcel & parcel)1501*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setAudioAttributes_l(const Parcel &parcel)
1502*ec779b8eSAndroid Build Coastguard Worker {
1503*ec779b8eSAndroid Build Coastguard Worker     if (mAudioAttributes != NULL) { free(mAudioAttributes); }
1504*ec779b8eSAndroid Build Coastguard Worker     mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1505*ec779b8eSAndroid Build Coastguard Worker     if (mAudioAttributes == NULL) {
1506*ec779b8eSAndroid Build Coastguard Worker         return NO_MEMORY;
1507*ec779b8eSAndroid Build Coastguard Worker     }
1508*ec779b8eSAndroid Build Coastguard Worker     unmarshallAudioAttributes(parcel, mAudioAttributes);
1509*ec779b8eSAndroid Build Coastguard Worker 
1510*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
1511*ec779b8eSAndroid Build Coastguard Worker             mAudioAttributes->usage, mAudioAttributes->content_type, mAudioAttributes->flags,
1512*ec779b8eSAndroid Build Coastguard Worker             mAudioAttributes->tags);
1513*ec779b8eSAndroid Build Coastguard Worker 
1514*ec779b8eSAndroid Build Coastguard Worker     if (mAudioOutput != 0) {
1515*ec779b8eSAndroid Build Coastguard Worker         mAudioOutput->setAudioAttributes(mAudioAttributes);
1516*ec779b8eSAndroid Build Coastguard Worker     }
1517*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1518*ec779b8eSAndroid Build Coastguard Worker }
1519*ec779b8eSAndroid Build Coastguard Worker 
setLooping(int loop)1520*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setLooping(int loop)
1521*ec779b8eSAndroid Build Coastguard Worker {
1522*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setLooping(%d)", mConnId, loop);
1523*ec779b8eSAndroid Build Coastguard Worker     mLoop = loop;
1524*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1525*ec779b8eSAndroid Build Coastguard Worker     if (p != 0) return p->setLooping(loop);
1526*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1527*ec779b8eSAndroid Build Coastguard Worker }
1528*ec779b8eSAndroid Build Coastguard Worker 
setVolume(float leftVolume,float rightVolume)1529*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1530*ec779b8eSAndroid Build Coastguard Worker {
1531*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
1532*ec779b8eSAndroid Build Coastguard Worker 
1533*ec779b8eSAndroid Build Coastguard Worker     // for hardware output, call player instead
1534*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1535*ec779b8eSAndroid Build Coastguard Worker     {
1536*ec779b8eSAndroid Build Coastguard Worker       Mutex::Autolock l(mLock);
1537*ec779b8eSAndroid Build Coastguard Worker       if (p != 0 && p->hardwareOutput()) {
1538*ec779b8eSAndroid Build Coastguard Worker           MediaPlayerHWInterface* hwp =
1539*ec779b8eSAndroid Build Coastguard Worker                   reinterpret_cast<MediaPlayerHWInterface*>(p.get());
1540*ec779b8eSAndroid Build Coastguard Worker           return hwp->setVolume(leftVolume, rightVolume);
1541*ec779b8eSAndroid Build Coastguard Worker       } else {
1542*ec779b8eSAndroid Build Coastguard Worker           if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1543*ec779b8eSAndroid Build Coastguard Worker           return NO_ERROR;
1544*ec779b8eSAndroid Build Coastguard Worker       }
1545*ec779b8eSAndroid Build Coastguard Worker     }
1546*ec779b8eSAndroid Build Coastguard Worker 
1547*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1548*ec779b8eSAndroid Build Coastguard Worker }
1549*ec779b8eSAndroid Build Coastguard Worker 
setAuxEffectSendLevel(float level)1550*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
1551*ec779b8eSAndroid Build Coastguard Worker {
1552*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
1553*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock l(mLock);
1554*ec779b8eSAndroid Build Coastguard Worker     if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
1555*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1556*ec779b8eSAndroid Build Coastguard Worker }
1557*ec779b8eSAndroid Build Coastguard Worker 
attachAuxEffect(int effectId)1558*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
1559*ec779b8eSAndroid Build Coastguard Worker {
1560*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
1561*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock l(mLock);
1562*ec779b8eSAndroid Build Coastguard Worker     if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
1563*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1564*ec779b8eSAndroid Build Coastguard Worker }
1565*ec779b8eSAndroid Build Coastguard Worker 
setParameter(int key,const Parcel & request)1566*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
1567*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setParameter(%d)", mConnId, key);
1568*ec779b8eSAndroid Build Coastguard Worker     switch (key) {
1569*ec779b8eSAndroid Build Coastguard Worker     case KEY_PARAMETER_AUDIO_ATTRIBUTES:
1570*ec779b8eSAndroid Build Coastguard Worker     {
1571*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1572*ec779b8eSAndroid Build Coastguard Worker         return setAudioAttributes_l(request);
1573*ec779b8eSAndroid Build Coastguard Worker     }
1574*ec779b8eSAndroid Build Coastguard Worker     default:
1575*ec779b8eSAndroid Build Coastguard Worker         sp<MediaPlayerBase> p = getPlayer();
1576*ec779b8eSAndroid Build Coastguard Worker         if (p == 0) { return UNKNOWN_ERROR; }
1577*ec779b8eSAndroid Build Coastguard Worker         return p->setParameter(key, request);
1578*ec779b8eSAndroid Build Coastguard Worker     }
1579*ec779b8eSAndroid Build Coastguard Worker }
1580*ec779b8eSAndroid Build Coastguard Worker 
getParameter(int key,Parcel * reply)1581*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
1582*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] getParameter(%d)", mConnId, key);
1583*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1584*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1585*ec779b8eSAndroid Build Coastguard Worker     return p->getParameter(key, reply);
1586*ec779b8eSAndroid Build Coastguard Worker }
1587*ec779b8eSAndroid Build Coastguard Worker 
setRetransmitEndpoint(const struct sockaddr_in * endpoint)1588*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setRetransmitEndpoint(
1589*ec779b8eSAndroid Build Coastguard Worker         const struct sockaddr_in* endpoint) {
1590*ec779b8eSAndroid Build Coastguard Worker 
1591*ec779b8eSAndroid Build Coastguard Worker     if (NULL != endpoint) {
1592*ec779b8eSAndroid Build Coastguard Worker         uint32_t a = ntohl(endpoint->sin_addr.s_addr);
1593*ec779b8eSAndroid Build Coastguard Worker         uint16_t p = ntohs(endpoint->sin_port);
1594*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
1595*ec779b8eSAndroid Build Coastguard Worker                 (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
1596*ec779b8eSAndroid Build Coastguard Worker     } else {
1597*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
1598*ec779b8eSAndroid Build Coastguard Worker     }
1599*ec779b8eSAndroid Build Coastguard Worker 
1600*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1601*ec779b8eSAndroid Build Coastguard Worker 
1602*ec779b8eSAndroid Build Coastguard Worker     // Right now, the only valid time to set a retransmit endpoint is before
1603*ec779b8eSAndroid Build Coastguard Worker     // player selection has been made (since the presence or absence of a
1604*ec779b8eSAndroid Build Coastguard Worker     // retransmit endpoint is going to determine which player is selected during
1605*ec779b8eSAndroid Build Coastguard Worker     // setDataSource).
1606*ec779b8eSAndroid Build Coastguard Worker     if (p != 0) return INVALID_OPERATION;
1607*ec779b8eSAndroid Build Coastguard Worker 
1608*ec779b8eSAndroid Build Coastguard Worker     if (NULL != endpoint) {
1609*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
1610*ec779b8eSAndroid Build Coastguard Worker         mRetransmitEndpoint = *endpoint;
1611*ec779b8eSAndroid Build Coastguard Worker         mRetransmitEndpointValid = true;
1612*ec779b8eSAndroid Build Coastguard Worker     } else {
1613*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
1614*ec779b8eSAndroid Build Coastguard Worker         mRetransmitEndpointValid = false;
1615*ec779b8eSAndroid Build Coastguard Worker     }
1616*ec779b8eSAndroid Build Coastguard Worker 
1617*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1618*ec779b8eSAndroid Build Coastguard Worker }
1619*ec779b8eSAndroid Build Coastguard Worker 
getRetransmitEndpoint(struct sockaddr_in * endpoint)1620*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getRetransmitEndpoint(
1621*ec779b8eSAndroid Build Coastguard Worker         struct sockaddr_in* endpoint)
1622*ec779b8eSAndroid Build Coastguard Worker {
1623*ec779b8eSAndroid Build Coastguard Worker     if (NULL == endpoint)
1624*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
1625*ec779b8eSAndroid Build Coastguard Worker 
1626*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1627*ec779b8eSAndroid Build Coastguard Worker 
1628*ec779b8eSAndroid Build Coastguard Worker     if (p != NULL)
1629*ec779b8eSAndroid Build Coastguard Worker         return p->getRetransmitEndpoint(endpoint);
1630*ec779b8eSAndroid Build Coastguard Worker 
1631*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1632*ec779b8eSAndroid Build Coastguard Worker     if (!mRetransmitEndpointValid)
1633*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
1634*ec779b8eSAndroid Build Coastguard Worker 
1635*ec779b8eSAndroid Build Coastguard Worker     *endpoint = mRetransmitEndpoint;
1636*ec779b8eSAndroid Build Coastguard Worker 
1637*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
1638*ec779b8eSAndroid Build Coastguard Worker }
1639*ec779b8eSAndroid Build Coastguard Worker 
notify(int msg,int ext1,int ext2,const Parcel * obj)1640*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::Client::notify(
1641*ec779b8eSAndroid Build Coastguard Worker         int msg, int ext1, int ext2, const Parcel *obj)
1642*ec779b8eSAndroid Build Coastguard Worker {
1643*ec779b8eSAndroid Build Coastguard Worker     sp<IMediaPlayerClient> c;
1644*ec779b8eSAndroid Build Coastguard Worker     sp<Client> nextClient;
1645*ec779b8eSAndroid Build Coastguard Worker     status_t errStartNext = NO_ERROR;
1646*ec779b8eSAndroid Build Coastguard Worker     {
1647*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1648*ec779b8eSAndroid Build Coastguard Worker         c = mClient;
1649*ec779b8eSAndroid Build Coastguard Worker         if (msg == MEDIA_PLAYBACK_COMPLETE && mNextClient != NULL) {
1650*ec779b8eSAndroid Build Coastguard Worker             nextClient = mNextClient;
1651*ec779b8eSAndroid Build Coastguard Worker 
1652*ec779b8eSAndroid Build Coastguard Worker             if (mAudioOutput != NULL)
1653*ec779b8eSAndroid Build Coastguard Worker                 mAudioOutput->switchToNextOutput();
1654*ec779b8eSAndroid Build Coastguard Worker 
1655*ec779b8eSAndroid Build Coastguard Worker             errStartNext = nextClient->start();
1656*ec779b8eSAndroid Build Coastguard Worker         }
1657*ec779b8eSAndroid Build Coastguard Worker     }
1658*ec779b8eSAndroid Build Coastguard Worker 
1659*ec779b8eSAndroid Build Coastguard Worker     if (nextClient != NULL) {
1660*ec779b8eSAndroid Build Coastguard Worker         sp<IMediaPlayerClient> nc;
1661*ec779b8eSAndroid Build Coastguard Worker         {
1662*ec779b8eSAndroid Build Coastguard Worker             Mutex::Autolock l(nextClient->mLock);
1663*ec779b8eSAndroid Build Coastguard Worker             nc = nextClient->mClient;
1664*ec779b8eSAndroid Build Coastguard Worker         }
1665*ec779b8eSAndroid Build Coastguard Worker         if (nc != NULL) {
1666*ec779b8eSAndroid Build Coastguard Worker             if (errStartNext == NO_ERROR) {
1667*ec779b8eSAndroid Build Coastguard Worker                 nc->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1668*ec779b8eSAndroid Build Coastguard Worker             } else {
1669*ec779b8eSAndroid Build Coastguard Worker                 nc->notify(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN , 0, obj);
1670*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("gapless:start playback for next track failed, err(%d)", errStartNext);
1671*ec779b8eSAndroid Build Coastguard Worker             }
1672*ec779b8eSAndroid Build Coastguard Worker         }
1673*ec779b8eSAndroid Build Coastguard Worker     }
1674*ec779b8eSAndroid Build Coastguard Worker 
1675*ec779b8eSAndroid Build Coastguard Worker     if (MEDIA_INFO == msg &&
1676*ec779b8eSAndroid Build Coastguard Worker         MEDIA_INFO_METADATA_UPDATE == ext1) {
1677*ec779b8eSAndroid Build Coastguard Worker         const media::Metadata::Type metadata_type = ext2;
1678*ec779b8eSAndroid Build Coastguard Worker 
1679*ec779b8eSAndroid Build Coastguard Worker         if(shouldDropMetadata(metadata_type)) {
1680*ec779b8eSAndroid Build Coastguard Worker             return;
1681*ec779b8eSAndroid Build Coastguard Worker         }
1682*ec779b8eSAndroid Build Coastguard Worker 
1683*ec779b8eSAndroid Build Coastguard Worker         // Update the list of metadata that have changed. getMetadata
1684*ec779b8eSAndroid Build Coastguard Worker         // also access mMetadataUpdated and clears it.
1685*ec779b8eSAndroid Build Coastguard Worker         addNewMetadataUpdate(metadata_type);
1686*ec779b8eSAndroid Build Coastguard Worker     }
1687*ec779b8eSAndroid Build Coastguard Worker 
1688*ec779b8eSAndroid Build Coastguard Worker     if (c != NULL) {
1689*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[%d] notify (%d, %d, %d)", mConnId, msg, ext1, ext2);
1690*ec779b8eSAndroid Build Coastguard Worker         c->notify(msg, ext1, ext2, obj);
1691*ec779b8eSAndroid Build Coastguard Worker     }
1692*ec779b8eSAndroid Build Coastguard Worker }
1693*ec779b8eSAndroid Build Coastguard Worker 
1694*ec779b8eSAndroid Build Coastguard Worker 
shouldDropMetadata(media::Metadata::Type code) const1695*ec779b8eSAndroid Build Coastguard Worker bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
1696*ec779b8eSAndroid Build Coastguard Worker {
1697*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1698*ec779b8eSAndroid Build Coastguard Worker 
1699*ec779b8eSAndroid Build Coastguard Worker     if (findMetadata(mMetadataDrop, code)) {
1700*ec779b8eSAndroid Build Coastguard Worker         return true;
1701*ec779b8eSAndroid Build Coastguard Worker     }
1702*ec779b8eSAndroid Build Coastguard Worker 
1703*ec779b8eSAndroid Build Coastguard Worker     if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
1704*ec779b8eSAndroid Build Coastguard Worker         return false;
1705*ec779b8eSAndroid Build Coastguard Worker     } else {
1706*ec779b8eSAndroid Build Coastguard Worker         return true;
1707*ec779b8eSAndroid Build Coastguard Worker     }
1708*ec779b8eSAndroid Build Coastguard Worker }
1709*ec779b8eSAndroid Build Coastguard Worker 
1710*ec779b8eSAndroid Build Coastguard Worker 
addNewMetadataUpdate(media::Metadata::Type metadata_type)1711*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
1712*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1713*ec779b8eSAndroid Build Coastguard Worker     if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1714*ec779b8eSAndroid Build Coastguard Worker         mMetadataUpdated.add(metadata_type);
1715*ec779b8eSAndroid Build Coastguard Worker     }
1716*ec779b8eSAndroid Build Coastguard Worker }
1717*ec779b8eSAndroid Build Coastguard Worker 
1718*ec779b8eSAndroid Build Coastguard Worker // Modular DRM
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId)1719*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::prepareDrm(const uint8_t uuid[16],
1720*ec779b8eSAndroid Build Coastguard Worker         const Vector<uint8_t>& drmSessionId)
1721*ec779b8eSAndroid Build Coastguard Worker {
1722*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] prepareDrm", mConnId);
1723*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1724*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1725*ec779b8eSAndroid Build Coastguard Worker 
1726*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->prepareDrm(uuid, drmSessionId);
1727*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepareDrm ret: %d", ret);
1728*ec779b8eSAndroid Build Coastguard Worker 
1729*ec779b8eSAndroid Build Coastguard Worker     return ret;
1730*ec779b8eSAndroid Build Coastguard Worker }
1731*ec779b8eSAndroid Build Coastguard Worker 
releaseDrm()1732*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::releaseDrm()
1733*ec779b8eSAndroid Build Coastguard Worker {
1734*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] releaseDrm", mConnId);
1735*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p = getPlayer();
1736*ec779b8eSAndroid Build Coastguard Worker     if (p == 0) return UNKNOWN_ERROR;
1737*ec779b8eSAndroid Build Coastguard Worker 
1738*ec779b8eSAndroid Build Coastguard Worker     status_t ret = p->releaseDrm();
1739*ec779b8eSAndroid Build Coastguard Worker     ALOGV("releaseDrm ret: %d", ret);
1740*ec779b8eSAndroid Build Coastguard Worker 
1741*ec779b8eSAndroid Build Coastguard Worker     return ret;
1742*ec779b8eSAndroid Build Coastguard Worker }
1743*ec779b8eSAndroid Build Coastguard Worker 
setOutputDevice(audio_port_handle_t deviceId)1744*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::setOutputDevice(audio_port_handle_t deviceId)
1745*ec779b8eSAndroid Build Coastguard Worker {
1746*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] setOutputDevice", mConnId);
1747*ec779b8eSAndroid Build Coastguard Worker     {
1748*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1749*ec779b8eSAndroid Build Coastguard Worker         if (mAudioOutput.get() != nullptr) {
1750*ec779b8eSAndroid Build Coastguard Worker             return mAudioOutput->setOutputDevice(deviceId);
1751*ec779b8eSAndroid Build Coastguard Worker         }
1752*ec779b8eSAndroid Build Coastguard Worker     }
1753*ec779b8eSAndroid Build Coastguard Worker     return NO_INIT;
1754*ec779b8eSAndroid Build Coastguard Worker }
1755*ec779b8eSAndroid Build Coastguard Worker 
getRoutedDeviceIds(DeviceIdVector & deviceIds)1756*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::getRoutedDeviceIds(DeviceIdVector& deviceIds)
1757*ec779b8eSAndroid Build Coastguard Worker {
1758*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] getRoutedDeviceIds", mConnId);
1759*ec779b8eSAndroid Build Coastguard Worker     {
1760*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1761*ec779b8eSAndroid Build Coastguard Worker         if (mAudioOutput.get() != nullptr) {
1762*ec779b8eSAndroid Build Coastguard Worker             return mAudioOutput->getRoutedDeviceIds(deviceIds);
1763*ec779b8eSAndroid Build Coastguard Worker         }
1764*ec779b8eSAndroid Build Coastguard Worker     }
1765*ec779b8eSAndroid Build Coastguard Worker     return NO_INIT;
1766*ec779b8eSAndroid Build Coastguard Worker }
1767*ec779b8eSAndroid Build Coastguard Worker 
enableAudioDeviceCallback(bool enabled)1768*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::Client::enableAudioDeviceCallback(bool enabled)
1769*ec779b8eSAndroid Build Coastguard Worker {
1770*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%d] enableAudioDeviceCallback, %d", mConnId, enabled);
1771*ec779b8eSAndroid Build Coastguard Worker     {
1772*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock l(mLock);
1773*ec779b8eSAndroid Build Coastguard Worker         if (mAudioOutput.get() != nullptr) {
1774*ec779b8eSAndroid Build Coastguard Worker             return mAudioOutput->enableAudioDeviceCallback(enabled);
1775*ec779b8eSAndroid Build Coastguard Worker         }
1776*ec779b8eSAndroid Build Coastguard Worker     }
1777*ec779b8eSAndroid Build Coastguard Worker     return NO_INIT;
1778*ec779b8eSAndroid Build Coastguard Worker }
1779*ec779b8eSAndroid Build Coastguard Worker 
1780*ec779b8eSAndroid Build Coastguard Worker #if CALLBACK_ANTAGONIZER
1781*ec779b8eSAndroid Build Coastguard Worker const int Antagonizer::interval = 10000; // 10 msecs
1782*ec779b8eSAndroid Build Coastguard Worker 
Antagonizer(const sp<MediaPlayerBase::Listener> & listener)1783*ec779b8eSAndroid Build Coastguard Worker Antagonizer::Antagonizer(const sp<MediaPlayerBase::Listener> &listener) :
1784*ec779b8eSAndroid Build Coastguard Worker     mExit(false), mActive(false), mListener(listener)
1785*ec779b8eSAndroid Build Coastguard Worker {
1786*ec779b8eSAndroid Build Coastguard Worker     createThread(callbackThread, this);
1787*ec779b8eSAndroid Build Coastguard Worker }
1788*ec779b8eSAndroid Build Coastguard Worker 
kill()1789*ec779b8eSAndroid Build Coastguard Worker void Antagonizer::kill()
1790*ec779b8eSAndroid Build Coastguard Worker {
1791*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock _l(mLock);
1792*ec779b8eSAndroid Build Coastguard Worker     mActive = false;
1793*ec779b8eSAndroid Build Coastguard Worker     mExit = true;
1794*ec779b8eSAndroid Build Coastguard Worker     mCondition.wait(mLock);
1795*ec779b8eSAndroid Build Coastguard Worker }
1796*ec779b8eSAndroid Build Coastguard Worker 
callbackThread(void * user)1797*ec779b8eSAndroid Build Coastguard Worker int Antagonizer::callbackThread(void* user)
1798*ec779b8eSAndroid Build Coastguard Worker {
1799*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Antagonizer started");
1800*ec779b8eSAndroid Build Coastguard Worker     Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1801*ec779b8eSAndroid Build Coastguard Worker     while (!p->mExit) {
1802*ec779b8eSAndroid Build Coastguard Worker         if (p->mActive) {
1803*ec779b8eSAndroid Build Coastguard Worker             ALOGV("send event");
1804*ec779b8eSAndroid Build Coastguard Worker             p->mListener->notify(0, 0, 0, 0);
1805*ec779b8eSAndroid Build Coastguard Worker         }
1806*ec779b8eSAndroid Build Coastguard Worker         usleep(interval);
1807*ec779b8eSAndroid Build Coastguard Worker     }
1808*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock _l(p->mLock);
1809*ec779b8eSAndroid Build Coastguard Worker     p->mCondition.signal();
1810*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Antagonizer stopped");
1811*ec779b8eSAndroid Build Coastguard Worker     return 0;
1812*ec779b8eSAndroid Build Coastguard Worker }
1813*ec779b8eSAndroid Build Coastguard Worker #endif
1814*ec779b8eSAndroid Build Coastguard Worker 
1815*ec779b8eSAndroid Build Coastguard Worker #undef LOG_TAG
1816*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioSink"
AudioOutput(audio_session_t sessionId,const AttributionSourceState & attributionSource,const audio_attributes_t * attr,const sp<AudioSystem::AudioDeviceCallback> & deviceCallback)1817*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId,
1818*ec779b8eSAndroid Build Coastguard Worker         const AttributionSourceState& attributionSource, const audio_attributes_t* attr,
1819*ec779b8eSAndroid Build Coastguard Worker         const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
1820*ec779b8eSAndroid Build Coastguard Worker     : mCachedPlayerIId(PLAYER_PIID_INVALID),
1821*ec779b8eSAndroid Build Coastguard Worker       mCallback(NULL),
1822*ec779b8eSAndroid Build Coastguard Worker       mStreamType(AUDIO_STREAM_MUSIC),
1823*ec779b8eSAndroid Build Coastguard Worker       mLeftVolume(1.0),
1824*ec779b8eSAndroid Build Coastguard Worker       mRightVolume(1.0),
1825*ec779b8eSAndroid Build Coastguard Worker       mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
1826*ec779b8eSAndroid Build Coastguard Worker       mSampleRateHz(0),
1827*ec779b8eSAndroid Build Coastguard Worker       mMsecsPerFrame(0),
1828*ec779b8eSAndroid Build Coastguard Worker       mFrameSize(0),
1829*ec779b8eSAndroid Build Coastguard Worker       mSessionId(sessionId),
1830*ec779b8eSAndroid Build Coastguard Worker       mAttributionSource(attributionSource),
1831*ec779b8eSAndroid Build Coastguard Worker       mSendLevel(0.0),
1832*ec779b8eSAndroid Build Coastguard Worker       mAuxEffectId(0),
1833*ec779b8eSAndroid Build Coastguard Worker       mFlags(AUDIO_OUTPUT_FLAG_NONE),
1834*ec779b8eSAndroid Build Coastguard Worker       mVolumeHandler(new media::VolumeHandler()),
1835*ec779b8eSAndroid Build Coastguard Worker       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
1836*ec779b8eSAndroid Build Coastguard Worker       mDeviceCallbackEnabled(false),
1837*ec779b8eSAndroid Build Coastguard Worker       mDeviceCallback(deviceCallback)
1838*ec779b8eSAndroid Build Coastguard Worker {
1839*ec779b8eSAndroid Build Coastguard Worker     ALOGV("AudioOutput(%d)", sessionId);
1840*ec779b8eSAndroid Build Coastguard Worker     if (attr != NULL) {
1841*ec779b8eSAndroid Build Coastguard Worker         mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
1842*ec779b8eSAndroid Build Coastguard Worker         if (mAttributes != NULL) {
1843*ec779b8eSAndroid Build Coastguard Worker             memcpy(mAttributes, attr, sizeof(audio_attributes_t));
1844*ec779b8eSAndroid Build Coastguard Worker             mStreamType = AudioSystem::attributesToStreamType(*attr);
1845*ec779b8eSAndroid Build Coastguard Worker         }
1846*ec779b8eSAndroid Build Coastguard Worker     } else {
1847*ec779b8eSAndroid Build Coastguard Worker         mAttributes = NULL;
1848*ec779b8eSAndroid Build Coastguard Worker     }
1849*ec779b8eSAndroid Build Coastguard Worker     setMinBufferCount();
1850*ec779b8eSAndroid Build Coastguard Worker }
1851*ec779b8eSAndroid Build Coastguard Worker 
~AudioOutput()1852*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::AudioOutput::~AudioOutput()
1853*ec779b8eSAndroid Build Coastguard Worker {
1854*ec779b8eSAndroid Build Coastguard Worker     close();
1855*ec779b8eSAndroid Build Coastguard Worker     free(mAttributes);
1856*ec779b8eSAndroid Build Coastguard Worker }
1857*ec779b8eSAndroid Build Coastguard Worker 
1858*ec779b8eSAndroid Build Coastguard Worker //static
setMinBufferCount()1859*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::setMinBufferCount()
1860*ec779b8eSAndroid Build Coastguard Worker {
1861*ec779b8eSAndroid Build Coastguard Worker     if (property_get_bool("ro.boot.qemu", false)) {
1862*ec779b8eSAndroid Build Coastguard Worker         mIsOnEmulator = true;
1863*ec779b8eSAndroid Build Coastguard Worker         mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
1864*ec779b8eSAndroid Build Coastguard Worker     }
1865*ec779b8eSAndroid Build Coastguard Worker }
1866*ec779b8eSAndroid Build Coastguard Worker 
1867*ec779b8eSAndroid Build Coastguard Worker // static
isOnEmulator()1868*ec779b8eSAndroid Build Coastguard Worker bool MediaPlayerService::AudioOutput::isOnEmulator()
1869*ec779b8eSAndroid Build Coastguard Worker {
1870*ec779b8eSAndroid Build Coastguard Worker     setMinBufferCount(); // benign race wrt other threads
1871*ec779b8eSAndroid Build Coastguard Worker     return mIsOnEmulator;
1872*ec779b8eSAndroid Build Coastguard Worker }
1873*ec779b8eSAndroid Build Coastguard Worker 
1874*ec779b8eSAndroid Build Coastguard Worker // static
getMinBufferCount()1875*ec779b8eSAndroid Build Coastguard Worker int MediaPlayerService::AudioOutput::getMinBufferCount()
1876*ec779b8eSAndroid Build Coastguard Worker {
1877*ec779b8eSAndroid Build Coastguard Worker     setMinBufferCount(); // benign race wrt other threads
1878*ec779b8eSAndroid Build Coastguard Worker     return mMinBufferCount;
1879*ec779b8eSAndroid Build Coastguard Worker }
1880*ec779b8eSAndroid Build Coastguard Worker 
bufferSize() const1881*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1882*ec779b8eSAndroid Build Coastguard Worker {
1883*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1884*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1885*ec779b8eSAndroid Build Coastguard Worker     return mTrack->frameCount() * mFrameSize;
1886*ec779b8eSAndroid Build Coastguard Worker }
1887*ec779b8eSAndroid Build Coastguard Worker 
frameCount() const1888*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaPlayerService::AudioOutput::frameCount() const
1889*ec779b8eSAndroid Build Coastguard Worker {
1890*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1891*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1892*ec779b8eSAndroid Build Coastguard Worker     return mTrack->frameCount();
1893*ec779b8eSAndroid Build Coastguard Worker }
1894*ec779b8eSAndroid Build Coastguard Worker 
channelCount() const1895*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaPlayerService::AudioOutput::channelCount() const
1896*ec779b8eSAndroid Build Coastguard Worker {
1897*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1898*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1899*ec779b8eSAndroid Build Coastguard Worker     return mTrack->channelCount();
1900*ec779b8eSAndroid Build Coastguard Worker }
1901*ec779b8eSAndroid Build Coastguard Worker 
frameSize() const1902*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaPlayerService::AudioOutput::frameSize() const
1903*ec779b8eSAndroid Build Coastguard Worker {
1904*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1905*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1906*ec779b8eSAndroid Build Coastguard Worker     return mFrameSize;
1907*ec779b8eSAndroid Build Coastguard Worker }
1908*ec779b8eSAndroid Build Coastguard Worker 
latency() const1909*ec779b8eSAndroid Build Coastguard Worker uint32_t MediaPlayerService::AudioOutput::latency () const
1910*ec779b8eSAndroid Build Coastguard Worker {
1911*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1912*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return 0;
1913*ec779b8eSAndroid Build Coastguard Worker     return mTrack->latency();
1914*ec779b8eSAndroid Build Coastguard Worker }
1915*ec779b8eSAndroid Build Coastguard Worker 
msecsPerFrame() const1916*ec779b8eSAndroid Build Coastguard Worker float MediaPlayerService::AudioOutput::msecsPerFrame() const
1917*ec779b8eSAndroid Build Coastguard Worker {
1918*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1919*ec779b8eSAndroid Build Coastguard Worker     return mMsecsPerFrame;
1920*ec779b8eSAndroid Build Coastguard Worker }
1921*ec779b8eSAndroid Build Coastguard Worker 
getPosition(uint32_t * position) const1922*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) const
1923*ec779b8eSAndroid Build Coastguard Worker {
1924*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1925*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1926*ec779b8eSAndroid Build Coastguard Worker     return mTrack->getPosition(position);
1927*ec779b8eSAndroid Build Coastguard Worker }
1928*ec779b8eSAndroid Build Coastguard Worker 
getTimestamp(AudioTimestamp & ts) const1929*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::getTimestamp(AudioTimestamp &ts) const
1930*ec779b8eSAndroid Build Coastguard Worker {
1931*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1932*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1933*ec779b8eSAndroid Build Coastguard Worker     return mTrack->getTimestamp(ts);
1934*ec779b8eSAndroid Build Coastguard Worker }
1935*ec779b8eSAndroid Build Coastguard Worker 
1936*ec779b8eSAndroid Build Coastguard Worker // TODO: Remove unnecessary calls to getPlayedOutDurationUs()
1937*ec779b8eSAndroid Build Coastguard Worker // as it acquires locks and may query the audio driver.
1938*ec779b8eSAndroid Build Coastguard Worker //
1939*ec779b8eSAndroid Build Coastguard Worker // Some calls could conceivably retrieve extrapolated data instead of
1940*ec779b8eSAndroid Build Coastguard Worker // accessing getTimestamp() or getPosition() every time a data buffer with
1941*ec779b8eSAndroid Build Coastguard Worker // a media time is received.
1942*ec779b8eSAndroid Build Coastguard Worker //
1943*ec779b8eSAndroid Build Coastguard Worker // Calculate duration of played samples if played at normal rate (i.e., 1.0).
getPlayedOutDurationUs(int64_t nowUs) const1944*ec779b8eSAndroid Build Coastguard Worker int64_t MediaPlayerService::AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const
1945*ec779b8eSAndroid Build Coastguard Worker {
1946*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1947*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0 || mSampleRateHz == 0) {
1948*ec779b8eSAndroid Build Coastguard Worker         return 0;
1949*ec779b8eSAndroid Build Coastguard Worker     }
1950*ec779b8eSAndroid Build Coastguard Worker 
1951*ec779b8eSAndroid Build Coastguard Worker     uint32_t numFramesPlayed;
1952*ec779b8eSAndroid Build Coastguard Worker     int64_t numFramesPlayedAtUs;
1953*ec779b8eSAndroid Build Coastguard Worker     AudioTimestamp ts;
1954*ec779b8eSAndroid Build Coastguard Worker 
1955*ec779b8eSAndroid Build Coastguard Worker     status_t res = mTrack->getTimestamp(ts);
1956*ec779b8eSAndroid Build Coastguard Worker     if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
1957*ec779b8eSAndroid Build Coastguard Worker         numFramesPlayed = ts.mPosition;
1958*ec779b8eSAndroid Build Coastguard Worker         numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
1959*ec779b8eSAndroid Build Coastguard Worker         //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
1960*ec779b8eSAndroid Build Coastguard Worker     } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
1961*ec779b8eSAndroid Build Coastguard Worker         numFramesPlayed = 0;
1962*ec779b8eSAndroid Build Coastguard Worker         numFramesPlayedAtUs = nowUs;
1963*ec779b8eSAndroid Build Coastguard Worker         //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
1964*ec779b8eSAndroid Build Coastguard Worker         //        numFramesPlayed, (long long)numFramesPlayedAtUs);
1965*ec779b8eSAndroid Build Coastguard Worker     } else {                         // case 3: transitory at new track or audio fast tracks.
1966*ec779b8eSAndroid Build Coastguard Worker         res = mTrack->getPosition(&numFramesPlayed);
1967*ec779b8eSAndroid Build Coastguard Worker         CHECK_EQ(res, (status_t)OK);
1968*ec779b8eSAndroid Build Coastguard Worker         numFramesPlayedAtUs = nowUs;
1969*ec779b8eSAndroid Build Coastguard Worker         numFramesPlayedAtUs += 1000LL * mTrack->latency() / 2; /* XXX */
1970*ec779b8eSAndroid Build Coastguard Worker         //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
1971*ec779b8eSAndroid Build Coastguard Worker     }
1972*ec779b8eSAndroid Build Coastguard Worker 
1973*ec779b8eSAndroid Build Coastguard Worker     // CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
1974*ec779b8eSAndroid Build Coastguard Worker     // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1975*ec779b8eSAndroid Build Coastguard Worker     int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
1976*ec779b8eSAndroid Build Coastguard Worker             + nowUs - numFramesPlayedAtUs;
1977*ec779b8eSAndroid Build Coastguard Worker     if (durationUs < 0) {
1978*ec779b8eSAndroid Build Coastguard Worker         // Occurs when numFramesPlayed position is very small and the following:
1979*ec779b8eSAndroid Build Coastguard Worker         // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
1980*ec779b8eSAndroid Build Coastguard Worker         //     numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
1981*ec779b8eSAndroid Build Coastguard Worker         // (2) In case 3, using getPosition and adding mAudioSink->latency() to
1982*ec779b8eSAndroid Build Coastguard Worker         //     numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
1983*ec779b8eSAndroid Build Coastguard Worker         //
1984*ec779b8eSAndroid Build Coastguard Worker         // Both of these are transitory conditions.
1985*ec779b8eSAndroid Build Coastguard Worker         ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
1986*ec779b8eSAndroid Build Coastguard Worker         durationUs = 0;
1987*ec779b8eSAndroid Build Coastguard Worker     }
1988*ec779b8eSAndroid Build Coastguard Worker     ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
1989*ec779b8eSAndroid Build Coastguard Worker             (long long)durationUs, (long long)nowUs,
1990*ec779b8eSAndroid Build Coastguard Worker             numFramesPlayed, (long long)numFramesPlayedAtUs);
1991*ec779b8eSAndroid Build Coastguard Worker     return durationUs;
1992*ec779b8eSAndroid Build Coastguard Worker }
1993*ec779b8eSAndroid Build Coastguard Worker 
getFramesWritten(uint32_t * frameswritten) const1994*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
1995*ec779b8eSAndroid Build Coastguard Worker {
1996*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
1997*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
1998*ec779b8eSAndroid Build Coastguard Worker     ExtendedTimestamp ets;
1999*ec779b8eSAndroid Build Coastguard Worker     status_t status = mTrack->getTimestamp(&ets);
2000*ec779b8eSAndroid Build Coastguard Worker     if (status == OK || status == WOULD_BLOCK) {
2001*ec779b8eSAndroid Build Coastguard Worker         *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
2002*ec779b8eSAndroid Build Coastguard Worker     }
2003*ec779b8eSAndroid Build Coastguard Worker     return status;
2004*ec779b8eSAndroid Build Coastguard Worker }
2005*ec779b8eSAndroid Build Coastguard Worker 
setParameters(const String8 & keyValuePairs)2006*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
2007*ec779b8eSAndroid Build Coastguard Worker {
2008*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2009*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return NO_INIT;
2010*ec779b8eSAndroid Build Coastguard Worker     return mTrack->setParameters(keyValuePairs);
2011*ec779b8eSAndroid Build Coastguard Worker }
2012*ec779b8eSAndroid Build Coastguard Worker 
getParameters(const String8 & keys)2013*ec779b8eSAndroid Build Coastguard Worker String8  MediaPlayerService::AudioOutput::getParameters(const String8& keys)
2014*ec779b8eSAndroid Build Coastguard Worker {
2015*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2016*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return String8();
2017*ec779b8eSAndroid Build Coastguard Worker     return mTrack->getParameters(keys);
2018*ec779b8eSAndroid Build Coastguard Worker }
2019*ec779b8eSAndroid Build Coastguard Worker 
setAudioAttributes(const audio_attributes_t * attributes)2020*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
2021*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2022*ec779b8eSAndroid Build Coastguard Worker     if (attributes == NULL) {
2023*ec779b8eSAndroid Build Coastguard Worker         free(mAttributes);
2024*ec779b8eSAndroid Build Coastguard Worker         mAttributes = NULL;
2025*ec779b8eSAndroid Build Coastguard Worker     } else {
2026*ec779b8eSAndroid Build Coastguard Worker         if (mAttributes == NULL) {
2027*ec779b8eSAndroid Build Coastguard Worker             mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
2028*ec779b8eSAndroid Build Coastguard Worker         }
2029*ec779b8eSAndroid Build Coastguard Worker         memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
2030*ec779b8eSAndroid Build Coastguard Worker         mStreamType = AudioSystem::attributesToStreamType(*attributes);
2031*ec779b8eSAndroid Build Coastguard Worker     }
2032*ec779b8eSAndroid Build Coastguard Worker }
2033*ec779b8eSAndroid Build Coastguard Worker 
setAudioStreamType(audio_stream_type_t streamType)2034*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
2035*ec779b8eSAndroid Build Coastguard Worker {
2036*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2037*ec779b8eSAndroid Build Coastguard Worker     // do not allow direct stream type modification if attributes have been set
2038*ec779b8eSAndroid Build Coastguard Worker     if (mAttributes == NULL) {
2039*ec779b8eSAndroid Build Coastguard Worker         mStreamType = streamType;
2040*ec779b8eSAndroid Build Coastguard Worker     }
2041*ec779b8eSAndroid Build Coastguard Worker }
2042*ec779b8eSAndroid Build Coastguard Worker 
deleteRecycledTrack_l()2043*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::deleteRecycledTrack_l()
2044*ec779b8eSAndroid Build Coastguard Worker {
2045*ec779b8eSAndroid Build Coastguard Worker     ALOGV("deleteRecycledTrack_l");
2046*ec779b8eSAndroid Build Coastguard Worker     if (mRecycledTrack != 0) {
2047*ec779b8eSAndroid Build Coastguard Worker 
2048*ec779b8eSAndroid Build Coastguard Worker         if (mCallbackData != NULL) {
2049*ec779b8eSAndroid Build Coastguard Worker             mCallbackData->setOutput(NULL);
2050*ec779b8eSAndroid Build Coastguard Worker             mCallbackData->endTrackSwitch();
2051*ec779b8eSAndroid Build Coastguard Worker         }
2052*ec779b8eSAndroid Build Coastguard Worker 
2053*ec779b8eSAndroid Build Coastguard Worker         if ((mRecycledTrack->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) {
2054*ec779b8eSAndroid Build Coastguard Worker             int32_t msec = 0;
2055*ec779b8eSAndroid Build Coastguard Worker             if (!mRecycledTrack->stopped()) { // check if active
2056*ec779b8eSAndroid Build Coastguard Worker                  (void)mRecycledTrack->pendingDuration(&msec);
2057*ec779b8eSAndroid Build Coastguard Worker             }
2058*ec779b8eSAndroid Build Coastguard Worker             mRecycledTrack->stop(); // ensure full data drain
2059*ec779b8eSAndroid Build Coastguard Worker             ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
2060*ec779b8eSAndroid Build Coastguard Worker             if (msec > 0) {
2061*ec779b8eSAndroid Build Coastguard Worker                 static const int32_t WAIT_LIMIT_MS = 3000;
2062*ec779b8eSAndroid Build Coastguard Worker                 if (msec > WAIT_LIMIT_MS) {
2063*ec779b8eSAndroid Build Coastguard Worker                     msec = WAIT_LIMIT_MS;
2064*ec779b8eSAndroid Build Coastguard Worker                 }
2065*ec779b8eSAndroid Build Coastguard Worker                 usleep(msec * 1000LL);
2066*ec779b8eSAndroid Build Coastguard Worker             }
2067*ec779b8eSAndroid Build Coastguard Worker         }
2068*ec779b8eSAndroid Build Coastguard Worker         // An offloaded track isn't flushed because the STREAM_END is reported
2069*ec779b8eSAndroid Build Coastguard Worker         // slightly prematurely to allow time for the gapless track switch
2070*ec779b8eSAndroid Build Coastguard Worker         // but this means that if we decide not to recycle the track there
2071*ec779b8eSAndroid Build Coastguard Worker         // could be a small amount of residual data still playing. We leave
2072*ec779b8eSAndroid Build Coastguard Worker         // AudioFlinger to drain the track.
2073*ec779b8eSAndroid Build Coastguard Worker 
2074*ec779b8eSAndroid Build Coastguard Worker         mRecycledTrack.clear();
2075*ec779b8eSAndroid Build Coastguard Worker         close_l();
2076*ec779b8eSAndroid Build Coastguard Worker         mCallbackData.clear();
2077*ec779b8eSAndroid Build Coastguard Worker     }
2078*ec779b8eSAndroid Build Coastguard Worker }
2079*ec779b8eSAndroid Build Coastguard Worker 
close_l()2080*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::close_l()
2081*ec779b8eSAndroid Build Coastguard Worker {
2082*ec779b8eSAndroid Build Coastguard Worker     mTrack.clear();
2083*ec779b8eSAndroid Build Coastguard Worker }
2084*ec779b8eSAndroid Build Coastguard Worker 
open(uint32_t sampleRate,int channelCount,audio_channel_mask_t channelMask,audio_format_t format,int bufferCount,AudioCallback cb,const wp<RefBase> & cookie,audio_output_flags_t flags,const audio_offload_info_t * offloadInfo,bool doNotReconnect,uint32_t suggestedFrameCount)2085*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::open(
2086*ec779b8eSAndroid Build Coastguard Worker         uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
2087*ec779b8eSAndroid Build Coastguard Worker         audio_format_t format, int bufferCount,
2088*ec779b8eSAndroid Build Coastguard Worker         AudioCallback cb, const wp<RefBase>& cookie,
2089*ec779b8eSAndroid Build Coastguard Worker         audio_output_flags_t flags,
2090*ec779b8eSAndroid Build Coastguard Worker         const audio_offload_info_t *offloadInfo,
2091*ec779b8eSAndroid Build Coastguard Worker         bool doNotReconnect,
2092*ec779b8eSAndroid Build Coastguard Worker         uint32_t suggestedFrameCount)
2093*ec779b8eSAndroid Build Coastguard Worker {
2094*ec779b8eSAndroid Build Coastguard Worker     ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
2095*ec779b8eSAndroid Build Coastguard Worker                 format, bufferCount, mSessionId, flags);
2096*ec779b8eSAndroid Build Coastguard Worker 
2097*ec779b8eSAndroid Build Coastguard Worker     // offloading is only supported in callback mode for now.
2098*ec779b8eSAndroid Build Coastguard Worker     // offloadInfo must be present if offload flag is set
2099*ec779b8eSAndroid Build Coastguard Worker     if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
2100*ec779b8eSAndroid Build Coastguard Worker             ((cb == NULL) || (offloadInfo == NULL))) {
2101*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
2102*ec779b8eSAndroid Build Coastguard Worker     }
2103*ec779b8eSAndroid Build Coastguard Worker 
2104*ec779b8eSAndroid Build Coastguard Worker     // compute frame count for the AudioTrack internal buffer
2105*ec779b8eSAndroid Build Coastguard Worker     size_t frameCount;
2106*ec779b8eSAndroid Build Coastguard Worker     if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
2107*ec779b8eSAndroid Build Coastguard Worker         frameCount = 0; // AudioTrack will get frame count from AudioFlinger
2108*ec779b8eSAndroid Build Coastguard Worker     } else {
2109*ec779b8eSAndroid Build Coastguard Worker         // try to estimate the buffer processing fetch size from AudioFlinger.
2110*ec779b8eSAndroid Build Coastguard Worker         // framesPerBuffer is approximate and generally correct, except when it's not :-).
2111*ec779b8eSAndroid Build Coastguard Worker         uint32_t afSampleRate;
2112*ec779b8eSAndroid Build Coastguard Worker         size_t afFrameCount;
2113*ec779b8eSAndroid Build Coastguard Worker         if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
2114*ec779b8eSAndroid Build Coastguard Worker             return NO_INIT;
2115*ec779b8eSAndroid Build Coastguard Worker         }
2116*ec779b8eSAndroid Build Coastguard Worker         if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
2117*ec779b8eSAndroid Build Coastguard Worker             return NO_INIT;
2118*ec779b8eSAndroid Build Coastguard Worker         }
2119*ec779b8eSAndroid Build Coastguard Worker         if (afSampleRate == 0) {
2120*ec779b8eSAndroid Build Coastguard Worker             return NO_INIT;
2121*ec779b8eSAndroid Build Coastguard Worker         }
2122*ec779b8eSAndroid Build Coastguard Worker         const size_t framesPerBuffer =
2123*ec779b8eSAndroid Build Coastguard Worker                 (unsigned long long)sampleRate * afFrameCount / afSampleRate;
2124*ec779b8eSAndroid Build Coastguard Worker 
2125*ec779b8eSAndroid Build Coastguard Worker         if (bufferCount == 0) {
2126*ec779b8eSAndroid Build Coastguard Worker             if (framesPerBuffer == 0) {
2127*ec779b8eSAndroid Build Coastguard Worker                 return NO_INIT;
2128*ec779b8eSAndroid Build Coastguard Worker             }
2129*ec779b8eSAndroid Build Coastguard Worker             // use suggestedFrameCount
2130*ec779b8eSAndroid Build Coastguard Worker             bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
2131*ec779b8eSAndroid Build Coastguard Worker         }
2132*ec779b8eSAndroid Build Coastguard Worker         // Check argument bufferCount against the mininum buffer count
2133*ec779b8eSAndroid Build Coastguard Worker         if (bufferCount != 0 && bufferCount < mMinBufferCount) {
2134*ec779b8eSAndroid Build Coastguard Worker             ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
2135*ec779b8eSAndroid Build Coastguard Worker             bufferCount = mMinBufferCount;
2136*ec779b8eSAndroid Build Coastguard Worker         }
2137*ec779b8eSAndroid Build Coastguard Worker         // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
2138*ec779b8eSAndroid Build Coastguard Worker         // which will be the minimum size permitted.
2139*ec779b8eSAndroid Build Coastguard Worker         frameCount = bufferCount * framesPerBuffer;
2140*ec779b8eSAndroid Build Coastguard Worker     }
2141*ec779b8eSAndroid Build Coastguard Worker 
2142*ec779b8eSAndroid Build Coastguard Worker     if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
2143*ec779b8eSAndroid Build Coastguard Worker         channelMask = audio_channel_out_mask_from_count(channelCount);
2144*ec779b8eSAndroid Build Coastguard Worker         if (0 == channelMask) {
2145*ec779b8eSAndroid Build Coastguard Worker             ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
2146*ec779b8eSAndroid Build Coastguard Worker             return NO_INIT;
2147*ec779b8eSAndroid Build Coastguard Worker         }
2148*ec779b8eSAndroid Build Coastguard Worker     }
2149*ec779b8eSAndroid Build Coastguard Worker 
2150*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2151*ec779b8eSAndroid Build Coastguard Worker     mCallback = cb;
2152*ec779b8eSAndroid Build Coastguard Worker     mCallbackCookie = cookie;
2153*ec779b8eSAndroid Build Coastguard Worker 
2154*ec779b8eSAndroid Build Coastguard Worker     // Check whether we can recycle the track
2155*ec779b8eSAndroid Build Coastguard Worker     bool reuse = false;
2156*ec779b8eSAndroid Build Coastguard Worker     bool bothOffloaded = false;
2157*ec779b8eSAndroid Build Coastguard Worker 
2158*ec779b8eSAndroid Build Coastguard Worker     if (mRecycledTrack != 0) {
2159*ec779b8eSAndroid Build Coastguard Worker         // check whether we are switching between two offloaded tracks
2160*ec779b8eSAndroid Build Coastguard Worker         bothOffloaded = (flags & mRecycledTrack->getFlags()
2161*ec779b8eSAndroid Build Coastguard Worker                                 & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0;
2162*ec779b8eSAndroid Build Coastguard Worker 
2163*ec779b8eSAndroid Build Coastguard Worker         // check if the existing track can be reused as-is, or if a new track needs to be created.
2164*ec779b8eSAndroid Build Coastguard Worker         reuse = true;
2165*ec779b8eSAndroid Build Coastguard Worker 
2166*ec779b8eSAndroid Build Coastguard Worker         if ((mCallbackData == NULL && mCallback != NULL) ||
2167*ec779b8eSAndroid Build Coastguard Worker                 (mCallbackData != NULL && mCallback == NULL)) {
2168*ec779b8eSAndroid Build Coastguard Worker             // recycled track uses callbacks but the caller wants to use writes, or vice versa
2169*ec779b8eSAndroid Build Coastguard Worker             ALOGV("can't chain callback and write");
2170*ec779b8eSAndroid Build Coastguard Worker             reuse = false;
2171*ec779b8eSAndroid Build Coastguard Worker         } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
2172*ec779b8eSAndroid Build Coastguard Worker                 (mRecycledTrack->channelCount() != (uint32_t)channelCount) ) {
2173*ec779b8eSAndroid Build Coastguard Worker             ALOGV("samplerate, channelcount differ: %u/%u Hz, %u/%d ch",
2174*ec779b8eSAndroid Build Coastguard Worker                   mRecycledTrack->getSampleRate(), sampleRate,
2175*ec779b8eSAndroid Build Coastguard Worker                   mRecycledTrack->channelCount(), channelCount);
2176*ec779b8eSAndroid Build Coastguard Worker             reuse = false;
2177*ec779b8eSAndroid Build Coastguard Worker         } else if (flags != mFlags) {
2178*ec779b8eSAndroid Build Coastguard Worker             ALOGV("output flags differ %08x/%08x", flags, mFlags);
2179*ec779b8eSAndroid Build Coastguard Worker             reuse = false;
2180*ec779b8eSAndroid Build Coastguard Worker         } else if (mRecycledTrack->format() != format) {
2181*ec779b8eSAndroid Build Coastguard Worker             reuse = false;
2182*ec779b8eSAndroid Build Coastguard Worker         }
2183*ec779b8eSAndroid Build Coastguard Worker     } else {
2184*ec779b8eSAndroid Build Coastguard Worker         ALOGV("no track available to recycle");
2185*ec779b8eSAndroid Build Coastguard Worker     }
2186*ec779b8eSAndroid Build Coastguard Worker 
2187*ec779b8eSAndroid Build Coastguard Worker     ALOGV_IF(bothOffloaded, "both tracks offloaded");
2188*ec779b8eSAndroid Build Coastguard Worker 
2189*ec779b8eSAndroid Build Coastguard Worker     // If we can't recycle and both tracks are offloaded
2190*ec779b8eSAndroid Build Coastguard Worker     // we must close the previous output before opening a new one
2191*ec779b8eSAndroid Build Coastguard Worker     if (bothOffloaded && !reuse) {
2192*ec779b8eSAndroid Build Coastguard Worker         ALOGV("both offloaded and not recycling");
2193*ec779b8eSAndroid Build Coastguard Worker         deleteRecycledTrack_l();
2194*ec779b8eSAndroid Build Coastguard Worker     }
2195*ec779b8eSAndroid Build Coastguard Worker 
2196*ec779b8eSAndroid Build Coastguard Worker     sp<AudioTrack> t;
2197*ec779b8eSAndroid Build Coastguard Worker     sp<CallbackData> newcbd;
2198*ec779b8eSAndroid Build Coastguard Worker 
2199*ec779b8eSAndroid Build Coastguard Worker     // We don't attempt to create a new track if we are recycling an
2200*ec779b8eSAndroid Build Coastguard Worker     // offloaded track. But, if we are recycling a non-offloaded or we
2201*ec779b8eSAndroid Build Coastguard Worker     // are switching where one is offloaded and one isn't then we create
2202*ec779b8eSAndroid Build Coastguard Worker     // the new track in advance so that we can read additional stream info
2203*ec779b8eSAndroid Build Coastguard Worker 
2204*ec779b8eSAndroid Build Coastguard Worker     if (!(reuse && bothOffloaded)) {
2205*ec779b8eSAndroid Build Coastguard Worker         ALOGV("creating new AudioTrack");
2206*ec779b8eSAndroid Build Coastguard Worker 
2207*ec779b8eSAndroid Build Coastguard Worker         if (mCallback != nullptr) {
2208*ec779b8eSAndroid Build Coastguard Worker             newcbd = sp<CallbackData>::make(wp<AudioOutput>::fromExisting(this));
2209*ec779b8eSAndroid Build Coastguard Worker             t = new AudioTrack(
2210*ec779b8eSAndroid Build Coastguard Worker                     mStreamType,
2211*ec779b8eSAndroid Build Coastguard Worker                     sampleRate,
2212*ec779b8eSAndroid Build Coastguard Worker                     format,
2213*ec779b8eSAndroid Build Coastguard Worker                     channelMask,
2214*ec779b8eSAndroid Build Coastguard Worker                     frameCount,
2215*ec779b8eSAndroid Build Coastguard Worker                     flags,
2216*ec779b8eSAndroid Build Coastguard Worker                     newcbd,
2217*ec779b8eSAndroid Build Coastguard Worker                     0,  // notification frames
2218*ec779b8eSAndroid Build Coastguard Worker                     mSessionId,
2219*ec779b8eSAndroid Build Coastguard Worker                     AudioTrack::TRANSFER_CALLBACK,
2220*ec779b8eSAndroid Build Coastguard Worker                     offloadInfo,
2221*ec779b8eSAndroid Build Coastguard Worker                     mAttributionSource,
2222*ec779b8eSAndroid Build Coastguard Worker                     mAttributes,
2223*ec779b8eSAndroid Build Coastguard Worker                     doNotReconnect,
2224*ec779b8eSAndroid Build Coastguard Worker                     1.0f,  // default value for maxRequiredSpeed
2225*ec779b8eSAndroid Build Coastguard Worker                     mSelectedDeviceId);
2226*ec779b8eSAndroid Build Coastguard Worker         } else {
2227*ec779b8eSAndroid Build Coastguard Worker             // TODO: Due to buffer memory concerns, we use a max target playback speed
2228*ec779b8eSAndroid Build Coastguard Worker             // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
2229*ec779b8eSAndroid Build Coastguard Worker             // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
2230*ec779b8eSAndroid Build Coastguard Worker             const float targetSpeed =
2231*ec779b8eSAndroid Build Coastguard Worker                     std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
2232*ec779b8eSAndroid Build Coastguard Worker             ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
2233*ec779b8eSAndroid Build Coastguard Worker                     "track target speed:%f clamped from playback speed:%f",
2234*ec779b8eSAndroid Build Coastguard Worker                     targetSpeed, mPlaybackRate.mSpeed);
2235*ec779b8eSAndroid Build Coastguard Worker             t = new AudioTrack(
2236*ec779b8eSAndroid Build Coastguard Worker                     mStreamType,
2237*ec779b8eSAndroid Build Coastguard Worker                     sampleRate,
2238*ec779b8eSAndroid Build Coastguard Worker                     format,
2239*ec779b8eSAndroid Build Coastguard Worker                     channelMask,
2240*ec779b8eSAndroid Build Coastguard Worker                     frameCount,
2241*ec779b8eSAndroid Build Coastguard Worker                     flags,
2242*ec779b8eSAndroid Build Coastguard Worker                     nullptr, // callback
2243*ec779b8eSAndroid Build Coastguard Worker                     0, // notification frames
2244*ec779b8eSAndroid Build Coastguard Worker                     mSessionId,
2245*ec779b8eSAndroid Build Coastguard Worker                     AudioTrack::TRANSFER_DEFAULT,
2246*ec779b8eSAndroid Build Coastguard Worker                     NULL, // offload info
2247*ec779b8eSAndroid Build Coastguard Worker                     mAttributionSource,
2248*ec779b8eSAndroid Build Coastguard Worker                     mAttributes,
2249*ec779b8eSAndroid Build Coastguard Worker                     doNotReconnect,
2250*ec779b8eSAndroid Build Coastguard Worker                     targetSpeed,
2251*ec779b8eSAndroid Build Coastguard Worker                     mSelectedDeviceId);
2252*ec779b8eSAndroid Build Coastguard Worker         }
2253*ec779b8eSAndroid Build Coastguard Worker         // Set caller name so it can be logged in destructor.
2254*ec779b8eSAndroid Build Coastguard Worker         // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
2255*ec779b8eSAndroid Build Coastguard Worker         t->setCallerName("media");
2256*ec779b8eSAndroid Build Coastguard Worker         if ((t == 0) || (t->initCheck() != NO_ERROR)) {
2257*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Unable to create audio track");
2258*ec779b8eSAndroid Build Coastguard Worker             // t, newcbd goes out of scope, so reference count drops to zero
2259*ec779b8eSAndroid Build Coastguard Worker             return NO_INIT;
2260*ec779b8eSAndroid Build Coastguard Worker         } else {
2261*ec779b8eSAndroid Build Coastguard Worker             // successful AudioTrack initialization implies a legacy stream type was generated
2262*ec779b8eSAndroid Build Coastguard Worker             // from the audio attributes
2263*ec779b8eSAndroid Build Coastguard Worker             mStreamType = t->streamType();
2264*ec779b8eSAndroid Build Coastguard Worker         }
2265*ec779b8eSAndroid Build Coastguard Worker     }
2266*ec779b8eSAndroid Build Coastguard Worker 
2267*ec779b8eSAndroid Build Coastguard Worker     if (reuse) {
2268*ec779b8eSAndroid Build Coastguard Worker         CHECK(mRecycledTrack != NULL);
2269*ec779b8eSAndroid Build Coastguard Worker 
2270*ec779b8eSAndroid Build Coastguard Worker         if (!bothOffloaded) {
2271*ec779b8eSAndroid Build Coastguard Worker             if (mRecycledTrack->frameCount() != t->frameCount()) {
2272*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("framecount differs: %zu/%zu frames",
2273*ec779b8eSAndroid Build Coastguard Worker                       mRecycledTrack->frameCount(), t->frameCount());
2274*ec779b8eSAndroid Build Coastguard Worker                 reuse = false;
2275*ec779b8eSAndroid Build Coastguard Worker             }
2276*ec779b8eSAndroid Build Coastguard Worker             // If recycled and new tracks are not on the same output,
2277*ec779b8eSAndroid Build Coastguard Worker             // don't reuse the recycled one.
2278*ec779b8eSAndroid Build Coastguard Worker             if (mRecycledTrack->getOutput() != t->getOutput()) {
2279*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("output has changed, don't reuse track");
2280*ec779b8eSAndroid Build Coastguard Worker                 reuse = false;
2281*ec779b8eSAndroid Build Coastguard Worker             }
2282*ec779b8eSAndroid Build Coastguard Worker         }
2283*ec779b8eSAndroid Build Coastguard Worker 
2284*ec779b8eSAndroid Build Coastguard Worker         if (reuse) {
2285*ec779b8eSAndroid Build Coastguard Worker             ALOGV("chaining to next output and recycling track");
2286*ec779b8eSAndroid Build Coastguard Worker             close_l();
2287*ec779b8eSAndroid Build Coastguard Worker             mTrack = mRecycledTrack;
2288*ec779b8eSAndroid Build Coastguard Worker             mRecycledTrack.clear();
2289*ec779b8eSAndroid Build Coastguard Worker             if (mCallbackData != NULL) {
2290*ec779b8eSAndroid Build Coastguard Worker                 mCallbackData->setOutput(this);
2291*ec779b8eSAndroid Build Coastguard Worker             }
2292*ec779b8eSAndroid Build Coastguard Worker             return updateTrack();
2293*ec779b8eSAndroid Build Coastguard Worker         }
2294*ec779b8eSAndroid Build Coastguard Worker     }
2295*ec779b8eSAndroid Build Coastguard Worker 
2296*ec779b8eSAndroid Build Coastguard Worker     // we're not going to reuse the track, unblock and flush it
2297*ec779b8eSAndroid Build Coastguard Worker     // this was done earlier if both tracks are offloaded
2298*ec779b8eSAndroid Build Coastguard Worker     if (!bothOffloaded) {
2299*ec779b8eSAndroid Build Coastguard Worker         deleteRecycledTrack_l();
2300*ec779b8eSAndroid Build Coastguard Worker     }
2301*ec779b8eSAndroid Build Coastguard Worker 
2302*ec779b8eSAndroid Build Coastguard Worker     CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
2303*ec779b8eSAndroid Build Coastguard Worker 
2304*ec779b8eSAndroid Build Coastguard Worker     mCallbackData = newcbd;
2305*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setVolume");
2306*ec779b8eSAndroid Build Coastguard Worker     t->setVolume(mLeftVolume, mRightVolume);
2307*ec779b8eSAndroid Build Coastguard Worker 
2308*ec779b8eSAndroid Build Coastguard Worker     // Restore VolumeShapers for the MediaPlayer in case the track was recreated
2309*ec779b8eSAndroid Build Coastguard Worker     // due to an output sink error (e.g. offload to non-offload switch).
2310*ec779b8eSAndroid Build Coastguard Worker     mVolumeHandler->forall([&t](const VolumeShaper &shaper) -> VolumeShaper::Status {
2311*ec779b8eSAndroid Build Coastguard Worker         sp<VolumeShaper::Operation> operationToEnd =
2312*ec779b8eSAndroid Build Coastguard Worker                 new VolumeShaper::Operation(shaper.mOperation);
2313*ec779b8eSAndroid Build Coastguard Worker         // TODO: Ideally we would restore to the exact xOffset position
2314*ec779b8eSAndroid Build Coastguard Worker         // as returned by getVolumeShaperState(), but we don't have that
2315*ec779b8eSAndroid Build Coastguard Worker         // information when restoring at the client unless we periodically poll
2316*ec779b8eSAndroid Build Coastguard Worker         // the server or create shared memory state.
2317*ec779b8eSAndroid Build Coastguard Worker         //
2318*ec779b8eSAndroid Build Coastguard Worker         // For now, we simply advance to the end of the VolumeShaper effect
2319*ec779b8eSAndroid Build Coastguard Worker         // if it has been started.
2320*ec779b8eSAndroid Build Coastguard Worker         if (shaper.isStarted()) {
2321*ec779b8eSAndroid Build Coastguard Worker             operationToEnd->setNormalizedTime(1.f);
2322*ec779b8eSAndroid Build Coastguard Worker         }
2323*ec779b8eSAndroid Build Coastguard Worker         return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
2324*ec779b8eSAndroid Build Coastguard Worker     });
2325*ec779b8eSAndroid Build Coastguard Worker 
2326*ec779b8eSAndroid Build Coastguard Worker     if (mCachedPlayerIId != PLAYER_PIID_INVALID) {
2327*ec779b8eSAndroid Build Coastguard Worker         t->setPlayerIId(mCachedPlayerIId);
2328*ec779b8eSAndroid Build Coastguard Worker     }
2329*ec779b8eSAndroid Build Coastguard Worker 
2330*ec779b8eSAndroid Build Coastguard Worker     mSampleRateHz = sampleRate;
2331*ec779b8eSAndroid Build Coastguard Worker     mFlags = flags;
2332*ec779b8eSAndroid Build Coastguard Worker     mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
2333*ec779b8eSAndroid Build Coastguard Worker     mFrameSize = t->frameSize();
2334*ec779b8eSAndroid Build Coastguard Worker     mTrack = t;
2335*ec779b8eSAndroid Build Coastguard Worker 
2336*ec779b8eSAndroid Build Coastguard Worker     return updateTrack();
2337*ec779b8eSAndroid Build Coastguard Worker }
2338*ec779b8eSAndroid Build Coastguard Worker 
updateTrack()2339*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::updateTrack() {
2340*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == NULL) {
2341*ec779b8eSAndroid Build Coastguard Worker         return NO_ERROR;
2342*ec779b8eSAndroid Build Coastguard Worker     }
2343*ec779b8eSAndroid Build Coastguard Worker 
2344*ec779b8eSAndroid Build Coastguard Worker     status_t res = NO_ERROR;
2345*ec779b8eSAndroid Build Coastguard Worker     // Note some output devices may give us a direct track even though we don't specify it.
2346*ec779b8eSAndroid Build Coastguard Worker     // Example: Line application b/17459982.
2347*ec779b8eSAndroid Build Coastguard Worker     if ((mTrack->getFlags()
2348*ec779b8eSAndroid Build Coastguard Worker             & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
2349*ec779b8eSAndroid Build Coastguard Worker         res = mTrack->setPlaybackRate(mPlaybackRate);
2350*ec779b8eSAndroid Build Coastguard Worker         if (res == NO_ERROR) {
2351*ec779b8eSAndroid Build Coastguard Worker             mTrack->setAuxEffectSendLevel(mSendLevel);
2352*ec779b8eSAndroid Build Coastguard Worker             res = mTrack->attachAuxEffect(mAuxEffectId);
2353*ec779b8eSAndroid Build Coastguard Worker         }
2354*ec779b8eSAndroid Build Coastguard Worker     }
2355*ec779b8eSAndroid Build Coastguard Worker     mTrack->setOutputDevice(mSelectedDeviceId);
2356*ec779b8eSAndroid Build Coastguard Worker     if (mDeviceCallbackEnabled) {
2357*ec779b8eSAndroid Build Coastguard Worker         mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
2358*ec779b8eSAndroid Build Coastguard Worker     }
2359*ec779b8eSAndroid Build Coastguard Worker     ALOGV("updateTrack() DONE status %d", res);
2360*ec779b8eSAndroid Build Coastguard Worker     return res;
2361*ec779b8eSAndroid Build Coastguard Worker }
2362*ec779b8eSAndroid Build Coastguard Worker 
start()2363*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::start()
2364*ec779b8eSAndroid Build Coastguard Worker {
2365*ec779b8eSAndroid Build Coastguard Worker     ALOGV("start");
2366*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2367*ec779b8eSAndroid Build Coastguard Worker     if (mCallbackData != NULL) {
2368*ec779b8eSAndroid Build Coastguard Worker         mCallbackData->endTrackSwitch();
2369*ec779b8eSAndroid Build Coastguard Worker     }
2370*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2371*ec779b8eSAndroid Build Coastguard Worker         mTrack->setVolume(mLeftVolume, mRightVolume);
2372*ec779b8eSAndroid Build Coastguard Worker         mTrack->setAuxEffectSendLevel(mSendLevel);
2373*ec779b8eSAndroid Build Coastguard Worker         status_t status = mTrack->start();
2374*ec779b8eSAndroid Build Coastguard Worker         if (status == NO_ERROR) {
2375*ec779b8eSAndroid Build Coastguard Worker             mVolumeHandler->setStarted();
2376*ec779b8eSAndroid Build Coastguard Worker         }
2377*ec779b8eSAndroid Build Coastguard Worker         return status;
2378*ec779b8eSAndroid Build Coastguard Worker     }
2379*ec779b8eSAndroid Build Coastguard Worker     return NO_INIT;
2380*ec779b8eSAndroid Build Coastguard Worker }
2381*ec779b8eSAndroid Build Coastguard Worker 
setPlayerIId(int32_t playerIId)2382*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::setPlayerIId(int32_t playerIId)
2383*ec779b8eSAndroid Build Coastguard Worker {
2384*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setPlayerIId(%d)", playerIId);
2385*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2386*ec779b8eSAndroid Build Coastguard Worker     mCachedPlayerIId = playerIId;
2387*ec779b8eSAndroid Build Coastguard Worker 
2388*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != nullptr) {
2389*ec779b8eSAndroid Build Coastguard Worker         mTrack->setPlayerIId(mCachedPlayerIId);
2390*ec779b8eSAndroid Build Coastguard Worker     }
2391*ec779b8eSAndroid Build Coastguard Worker }
2392*ec779b8eSAndroid Build Coastguard Worker 
setNextOutput(const sp<AudioOutput> & nextOutput)2393*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
2394*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2395*ec779b8eSAndroid Build Coastguard Worker     mNextOutput = nextOutput;
2396*ec779b8eSAndroid Build Coastguard Worker }
2397*ec779b8eSAndroid Build Coastguard Worker 
switchToNextOutput()2398*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::switchToNextOutput() {
2399*ec779b8eSAndroid Build Coastguard Worker     ALOGV("switchToNextOutput");
2400*ec779b8eSAndroid Build Coastguard Worker 
2401*ec779b8eSAndroid Build Coastguard Worker     // Try to acquire the callback lock before moving track (without incurring deadlock).
2402*ec779b8eSAndroid Build Coastguard Worker     const unsigned kMaxSwitchTries = 100;
2403*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2404*ec779b8eSAndroid Build Coastguard Worker     for (unsigned tries = 0;;) {
2405*ec779b8eSAndroid Build Coastguard Worker         if (mTrack == 0) {
2406*ec779b8eSAndroid Build Coastguard Worker             return;
2407*ec779b8eSAndroid Build Coastguard Worker         }
2408*ec779b8eSAndroid Build Coastguard Worker         if (mNextOutput != NULL && mNextOutput != this) {
2409*ec779b8eSAndroid Build Coastguard Worker             if (mCallbackData != NULL) {
2410*ec779b8eSAndroid Build Coastguard Worker                 // two alternative approaches
2411*ec779b8eSAndroid Build Coastguard Worker #if 1
2412*ec779b8eSAndroid Build Coastguard Worker                 sp<CallbackData> callbackData = mCallbackData;
2413*ec779b8eSAndroid Build Coastguard Worker                 mLock.unlock();
2414*ec779b8eSAndroid Build Coastguard Worker                 // proper acquisition sequence
2415*ec779b8eSAndroid Build Coastguard Worker                 callbackData->lock();
2416*ec779b8eSAndroid Build Coastguard Worker                 mLock.lock();
2417*ec779b8eSAndroid Build Coastguard Worker                 // Caution: it is unlikely that someone deleted our callback or changed our target
2418*ec779b8eSAndroid Build Coastguard Worker                 if (callbackData != mCallbackData || mNextOutput == NULL || mNextOutput == this) {
2419*ec779b8eSAndroid Build Coastguard Worker                     // fatal if we are starved out.
2420*ec779b8eSAndroid Build Coastguard Worker                     LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
2421*ec779b8eSAndroid Build Coastguard Worker                             "switchToNextOutput() cannot obtain correct lock sequence");
2422*ec779b8eSAndroid Build Coastguard Worker                     callbackData->unlock();
2423*ec779b8eSAndroid Build Coastguard Worker                     continue;
2424*ec779b8eSAndroid Build Coastguard Worker                 }
2425*ec779b8eSAndroid Build Coastguard Worker                 callbackData->mSwitching = true; // begin track switch
2426*ec779b8eSAndroid Build Coastguard Worker                 callbackData->setOutput(NULL);
2427*ec779b8eSAndroid Build Coastguard Worker #else
2428*ec779b8eSAndroid Build Coastguard Worker                 // tryBeginTrackSwitch() returns false if the callback has the lock.
2429*ec779b8eSAndroid Build Coastguard Worker                 if (!mCallbackData->tryBeginTrackSwitch()) {
2430*ec779b8eSAndroid Build Coastguard Worker                     // fatal if we are starved out.
2431*ec779b8eSAndroid Build Coastguard Worker                     LOG_ALWAYS_FATAL_IF(++tries > kMaxSwitchTries,
2432*ec779b8eSAndroid Build Coastguard Worker                             "switchToNextOutput() cannot obtain callback lock");
2433*ec779b8eSAndroid Build Coastguard Worker                     mLock.unlock();
2434*ec779b8eSAndroid Build Coastguard Worker                     usleep(5 * 1000 /* usec */); // allow callback to use AudioOutput
2435*ec779b8eSAndroid Build Coastguard Worker                     mLock.lock();
2436*ec779b8eSAndroid Build Coastguard Worker                     continue;
2437*ec779b8eSAndroid Build Coastguard Worker                 }
2438*ec779b8eSAndroid Build Coastguard Worker #endif
2439*ec779b8eSAndroid Build Coastguard Worker             }
2440*ec779b8eSAndroid Build Coastguard Worker 
2441*ec779b8eSAndroid Build Coastguard Worker             Mutex::Autolock nextLock(mNextOutput->mLock);
2442*ec779b8eSAndroid Build Coastguard Worker 
2443*ec779b8eSAndroid Build Coastguard Worker             // If the next output track is not NULL, then it has been
2444*ec779b8eSAndroid Build Coastguard Worker             // opened already for playback.
2445*ec779b8eSAndroid Build Coastguard Worker             // This is possible even without the next player being started,
2446*ec779b8eSAndroid Build Coastguard Worker             // for example, the next player could be prepared and seeked.
2447*ec779b8eSAndroid Build Coastguard Worker             //
2448*ec779b8eSAndroid Build Coastguard Worker             // Presuming it isn't advisable to force the track over.
2449*ec779b8eSAndroid Build Coastguard Worker              if (mNextOutput->mTrack == nullptr) {
2450*ec779b8eSAndroid Build Coastguard Worker                 ALOGD("Recycling track for gapless playback");
2451*ec779b8eSAndroid Build Coastguard Worker                 mNextOutput->mCallbackData = mCallbackData;
2452*ec779b8eSAndroid Build Coastguard Worker                 mNextOutput->mRecycledTrack = mTrack;
2453*ec779b8eSAndroid Build Coastguard Worker                 mNextOutput->mSampleRateHz = mSampleRateHz;
2454*ec779b8eSAndroid Build Coastguard Worker                 mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
2455*ec779b8eSAndroid Build Coastguard Worker                 mNextOutput->mFlags = mFlags;
2456*ec779b8eSAndroid Build Coastguard Worker                 mNextOutput->mFrameSize = mFrameSize;
2457*ec779b8eSAndroid Build Coastguard Worker                 close_l();
2458*ec779b8eSAndroid Build Coastguard Worker                 mCallbackData.clear();
2459*ec779b8eSAndroid Build Coastguard Worker             } else {
2460*ec779b8eSAndroid Build Coastguard Worker                 ALOGW("Ignoring gapless playback because next player has already started");
2461*ec779b8eSAndroid Build Coastguard Worker                 // remove track in case resource needed for future players.
2462*ec779b8eSAndroid Build Coastguard Worker                 if (mCallbackData != nullptr) {
2463*ec779b8eSAndroid Build Coastguard Worker                     mCallbackData->endTrackSwitch();  // release lock for callbacks before close.
2464*ec779b8eSAndroid Build Coastguard Worker                 }
2465*ec779b8eSAndroid Build Coastguard Worker                 close_l();
2466*ec779b8eSAndroid Build Coastguard Worker             }
2467*ec779b8eSAndroid Build Coastguard Worker         }
2468*ec779b8eSAndroid Build Coastguard Worker         break;
2469*ec779b8eSAndroid Build Coastguard Worker     }
2470*ec779b8eSAndroid Build Coastguard Worker }
2471*ec779b8eSAndroid Build Coastguard Worker 
write(const void * buffer,size_t size,bool blocking)2472*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, bool blocking)
2473*ec779b8eSAndroid Build Coastguard Worker {
2474*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2475*ec779b8eSAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
2476*ec779b8eSAndroid Build Coastguard Worker 
2477*ec779b8eSAndroid Build Coastguard Worker     //ALOGV("write(%p, %u)", buffer, size);
2478*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2479*ec779b8eSAndroid Build Coastguard Worker         return mTrack->write(buffer, size, blocking);
2480*ec779b8eSAndroid Build Coastguard Worker     }
2481*ec779b8eSAndroid Build Coastguard Worker     return NO_INIT;
2482*ec779b8eSAndroid Build Coastguard Worker }
2483*ec779b8eSAndroid Build Coastguard Worker 
stop()2484*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::stop()
2485*ec779b8eSAndroid Build Coastguard Worker {
2486*ec779b8eSAndroid Build Coastguard Worker     ALOGV("stop");
2487*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2488*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) mTrack->stop();
2489*ec779b8eSAndroid Build Coastguard Worker }
2490*ec779b8eSAndroid Build Coastguard Worker 
flush()2491*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::flush()
2492*ec779b8eSAndroid Build Coastguard Worker {
2493*ec779b8eSAndroid Build Coastguard Worker     ALOGV("flush");
2494*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2495*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) mTrack->flush();
2496*ec779b8eSAndroid Build Coastguard Worker }
2497*ec779b8eSAndroid Build Coastguard Worker 
pause()2498*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::pause()
2499*ec779b8eSAndroid Build Coastguard Worker {
2500*ec779b8eSAndroid Build Coastguard Worker     ALOGV("pause");
2501*ec779b8eSAndroid Build Coastguard Worker     // We use pauseAndWait() instead of pause() to ensure tracks ramp to silence before
2502*ec779b8eSAndroid Build Coastguard Worker     // any flush. We choose 40 ms timeout to allow 1 deep buffer mixer period
2503*ec779b8eSAndroid Build Coastguard Worker     // to occur.  Often waiting is 0 - 20 ms.
2504*ec779b8eSAndroid Build Coastguard Worker     using namespace std::chrono_literals;
2505*ec779b8eSAndroid Build Coastguard Worker     constexpr auto TIMEOUT_MS = 40ms;
2506*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2507*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) mTrack->pauseAndWait(TIMEOUT_MS);
2508*ec779b8eSAndroid Build Coastguard Worker }
2509*ec779b8eSAndroid Build Coastguard Worker 
close()2510*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::close()
2511*ec779b8eSAndroid Build Coastguard Worker {
2512*ec779b8eSAndroid Build Coastguard Worker     ALOGV("close");
2513*ec779b8eSAndroid Build Coastguard Worker     sp<AudioTrack> track;
2514*ec779b8eSAndroid Build Coastguard Worker     {
2515*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
2516*ec779b8eSAndroid Build Coastguard Worker         track = mTrack;
2517*ec779b8eSAndroid Build Coastguard Worker     }
2518*ec779b8eSAndroid Build Coastguard Worker 
2519*ec779b8eSAndroid Build Coastguard Worker     // do not hold lock while joining.
2520*ec779b8eSAndroid Build Coastguard Worker     if (track) {
2521*ec779b8eSAndroid Build Coastguard Worker         track->stopAndJoinCallbacks();
2522*ec779b8eSAndroid Build Coastguard Worker     }
2523*ec779b8eSAndroid Build Coastguard Worker 
2524*ec779b8eSAndroid Build Coastguard Worker     {
2525*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock lock(mLock);
2526*ec779b8eSAndroid Build Coastguard Worker         close_l(); // clears mTrack
2527*ec779b8eSAndroid Build Coastguard Worker     }
2528*ec779b8eSAndroid Build Coastguard Worker     // destruction of the track occurs outside of mutex.
2529*ec779b8eSAndroid Build Coastguard Worker }
2530*ec779b8eSAndroid Build Coastguard Worker 
setVolume(float left,float right)2531*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::setVolume(float left, float right)
2532*ec779b8eSAndroid Build Coastguard Worker {
2533*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setVolume(%f, %f)", left, right);
2534*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2535*ec779b8eSAndroid Build Coastguard Worker     mLeftVolume = left;
2536*ec779b8eSAndroid Build Coastguard Worker     mRightVolume = right;
2537*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2538*ec779b8eSAndroid Build Coastguard Worker         mTrack->setVolume(left, right);
2539*ec779b8eSAndroid Build Coastguard Worker     }
2540*ec779b8eSAndroid Build Coastguard Worker }
2541*ec779b8eSAndroid Build Coastguard Worker 
setPlaybackRate(const AudioPlaybackRate & rate)2542*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate)
2543*ec779b8eSAndroid Build Coastguard Worker {
2544*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setPlaybackRate(%f %f %d %d)",
2545*ec779b8eSAndroid Build Coastguard Worker                 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
2546*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2547*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) {
2548*ec779b8eSAndroid Build Coastguard Worker         // remember rate so that we can set it when the track is opened
2549*ec779b8eSAndroid Build Coastguard Worker         mPlaybackRate = rate;
2550*ec779b8eSAndroid Build Coastguard Worker         return OK;
2551*ec779b8eSAndroid Build Coastguard Worker     }
2552*ec779b8eSAndroid Build Coastguard Worker     status_t res = mTrack->setPlaybackRate(rate);
2553*ec779b8eSAndroid Build Coastguard Worker     if (res != NO_ERROR) {
2554*ec779b8eSAndroid Build Coastguard Worker         return res;
2555*ec779b8eSAndroid Build Coastguard Worker     }
2556*ec779b8eSAndroid Build Coastguard Worker     // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
2557*ec779b8eSAndroid Build Coastguard Worker     CHECK_GT(rate.mSpeed, 0.f);
2558*ec779b8eSAndroid Build Coastguard Worker     mPlaybackRate = rate;
2559*ec779b8eSAndroid Build Coastguard Worker     if (mSampleRateHz != 0) {
2560*ec779b8eSAndroid Build Coastguard Worker         mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
2561*ec779b8eSAndroid Build Coastguard Worker     }
2562*ec779b8eSAndroid Build Coastguard Worker     return res;
2563*ec779b8eSAndroid Build Coastguard Worker }
2564*ec779b8eSAndroid Build Coastguard Worker 
getPlaybackRate(AudioPlaybackRate * rate)2565*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::getPlaybackRate(AudioPlaybackRate *rate)
2566*ec779b8eSAndroid Build Coastguard Worker {
2567*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setPlaybackRate");
2568*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2569*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) {
2570*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
2571*ec779b8eSAndroid Build Coastguard Worker     }
2572*ec779b8eSAndroid Build Coastguard Worker     *rate = mTrack->getPlaybackRate();
2573*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
2574*ec779b8eSAndroid Build Coastguard Worker }
2575*ec779b8eSAndroid Build Coastguard Worker 
setAuxEffectSendLevel(float level)2576*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
2577*ec779b8eSAndroid Build Coastguard Worker {
2578*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setAuxEffectSendLevel(%f)", level);
2579*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2580*ec779b8eSAndroid Build Coastguard Worker     mSendLevel = level;
2581*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2582*ec779b8eSAndroid Build Coastguard Worker         return mTrack->setAuxEffectSendLevel(level);
2583*ec779b8eSAndroid Build Coastguard Worker     }
2584*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
2585*ec779b8eSAndroid Build Coastguard Worker }
2586*ec779b8eSAndroid Build Coastguard Worker 
attachAuxEffect(int effectId)2587*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
2588*ec779b8eSAndroid Build Coastguard Worker {
2589*ec779b8eSAndroid Build Coastguard Worker     ALOGV("attachAuxEffect(%d)", effectId);
2590*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2591*ec779b8eSAndroid Build Coastguard Worker     mAuxEffectId = effectId;
2592*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2593*ec779b8eSAndroid Build Coastguard Worker         return mTrack->attachAuxEffect(effectId);
2594*ec779b8eSAndroid Build Coastguard Worker     }
2595*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
2596*ec779b8eSAndroid Build Coastguard Worker }
2597*ec779b8eSAndroid Build Coastguard Worker 
setOutputDevice(audio_port_handle_t deviceId)2598*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::setOutputDevice(audio_port_handle_t deviceId)
2599*ec779b8eSAndroid Build Coastguard Worker {
2600*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setOutputDevice(%d)", deviceId);
2601*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2602*ec779b8eSAndroid Build Coastguard Worker     mSelectedDeviceId = deviceId;
2603*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2604*ec779b8eSAndroid Build Coastguard Worker         return mTrack->setOutputDevice(deviceId);
2605*ec779b8eSAndroid Build Coastguard Worker     }
2606*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
2607*ec779b8eSAndroid Build Coastguard Worker }
2608*ec779b8eSAndroid Build Coastguard Worker 
getRoutedDeviceIds(DeviceIdVector & deviceIds)2609*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::getRoutedDeviceIds(DeviceIdVector& deviceIds)
2610*ec779b8eSAndroid Build Coastguard Worker {
2611*ec779b8eSAndroid Build Coastguard Worker     ALOGV("getRoutedDeviceIds");
2612*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2613*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2614*ec779b8eSAndroid Build Coastguard Worker         mRoutedDeviceIds = mTrack->getRoutedDeviceIds();
2615*ec779b8eSAndroid Build Coastguard Worker     }
2616*ec779b8eSAndroid Build Coastguard Worker     deviceIds = mRoutedDeviceIds;
2617*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
2618*ec779b8eSAndroid Build Coastguard Worker }
2619*ec779b8eSAndroid Build Coastguard Worker 
enableAudioDeviceCallback(bool enabled)2620*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::AudioOutput::enableAudioDeviceCallback(bool enabled)
2621*ec779b8eSAndroid Build Coastguard Worker {
2622*ec779b8eSAndroid Build Coastguard Worker     ALOGV("enableAudioDeviceCallback, %d", enabled);
2623*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2624*ec779b8eSAndroid Build Coastguard Worker     mDeviceCallbackEnabled = enabled;
2625*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2626*ec779b8eSAndroid Build Coastguard Worker         status_t status;
2627*ec779b8eSAndroid Build Coastguard Worker         if (enabled) {
2628*ec779b8eSAndroid Build Coastguard Worker             status = mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
2629*ec779b8eSAndroid Build Coastguard Worker         } else {
2630*ec779b8eSAndroid Build Coastguard Worker             status = mTrack->removeAudioDeviceCallback(mDeviceCallback.promote());
2631*ec779b8eSAndroid Build Coastguard Worker         }
2632*ec779b8eSAndroid Build Coastguard Worker         return status;
2633*ec779b8eSAndroid Build Coastguard Worker     }
2634*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
2635*ec779b8eSAndroid Build Coastguard Worker }
2636*ec779b8eSAndroid Build Coastguard Worker 
applyVolumeShaper(const sp<VolumeShaper::Configuration> & configuration,const sp<VolumeShaper::Operation> & operation)2637*ec779b8eSAndroid Build Coastguard Worker VolumeShaper::Status MediaPlayerService::AudioOutput::applyVolumeShaper(
2638*ec779b8eSAndroid Build Coastguard Worker                 const sp<VolumeShaper::Configuration>& configuration,
2639*ec779b8eSAndroid Build Coastguard Worker                 const sp<VolumeShaper::Operation>& operation)
2640*ec779b8eSAndroid Build Coastguard Worker {
2641*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2642*ec779b8eSAndroid Build Coastguard Worker     ALOGV("AudioOutput::applyVolumeShaper");
2643*ec779b8eSAndroid Build Coastguard Worker 
2644*ec779b8eSAndroid Build Coastguard Worker     if (configuration == nullptr) {
2645*ec779b8eSAndroid Build Coastguard Worker         ALOGE("AudioOutput::applyVolumeShaper Null configuration parameter");
2646*ec779b8eSAndroid Build Coastguard Worker         return VolumeShaper::Status(BAD_VALUE);
2647*ec779b8eSAndroid Build Coastguard Worker     }
2648*ec779b8eSAndroid Build Coastguard Worker 
2649*ec779b8eSAndroid Build Coastguard Worker     if (operation == nullptr) {
2650*ec779b8eSAndroid Build Coastguard Worker         ALOGE("AudioOutput::applyVolumeShaper Null operation parameter");
2651*ec779b8eSAndroid Build Coastguard Worker         return VolumeShaper::Status(BAD_VALUE);
2652*ec779b8eSAndroid Build Coastguard Worker     }
2653*ec779b8eSAndroid Build Coastguard Worker 
2654*ec779b8eSAndroid Build Coastguard Worker     mVolumeHandler->setIdIfNecessary(configuration);
2655*ec779b8eSAndroid Build Coastguard Worker 
2656*ec779b8eSAndroid Build Coastguard Worker     VolumeShaper::Status status;
2657*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2658*ec779b8eSAndroid Build Coastguard Worker         status = mTrack->applyVolumeShaper(configuration, operation);
2659*ec779b8eSAndroid Build Coastguard Worker         if (status >= 0) {
2660*ec779b8eSAndroid Build Coastguard Worker             (void)mVolumeHandler->applyVolumeShaper(configuration, operation);
2661*ec779b8eSAndroid Build Coastguard Worker             if (mTrack->isPlaying()) { // match local AudioTrack to properly restore.
2662*ec779b8eSAndroid Build Coastguard Worker                 mVolumeHandler->setStarted();
2663*ec779b8eSAndroid Build Coastguard Worker             }
2664*ec779b8eSAndroid Build Coastguard Worker         }
2665*ec779b8eSAndroid Build Coastguard Worker     } else {
2666*ec779b8eSAndroid Build Coastguard Worker         // VolumeShapers are not affected when a track moves between players for
2667*ec779b8eSAndroid Build Coastguard Worker         // gapless playback (setNextMediaPlayer).
2668*ec779b8eSAndroid Build Coastguard Worker         // We forward VolumeShaper operations that do not change configuration
2669*ec779b8eSAndroid Build Coastguard Worker         // to the new player so that unducking may occur as expected.
2670*ec779b8eSAndroid Build Coastguard Worker         // Unducking is an idempotent operation, same if applied back-to-back.
2671*ec779b8eSAndroid Build Coastguard Worker         if (configuration->getType() == VolumeShaper::Configuration::TYPE_ID
2672*ec779b8eSAndroid Build Coastguard Worker                 && mNextOutput != nullptr) {
2673*ec779b8eSAndroid Build Coastguard Worker             ALOGV("applyVolumeShaper: Attempting to forward missed operation: %s %s",
2674*ec779b8eSAndroid Build Coastguard Worker                     configuration->toString().c_str(), operation->toString().c_str());
2675*ec779b8eSAndroid Build Coastguard Worker             Mutex::Autolock nextLock(mNextOutput->mLock);
2676*ec779b8eSAndroid Build Coastguard Worker 
2677*ec779b8eSAndroid Build Coastguard Worker             // recycled track should be forwarded from this AudioSink by switchToNextOutput
2678*ec779b8eSAndroid Build Coastguard Worker             sp<AudioTrack> track = mNextOutput->mRecycledTrack;
2679*ec779b8eSAndroid Build Coastguard Worker             if (track != nullptr) {
2680*ec779b8eSAndroid Build Coastguard Worker                 ALOGD("Forward VolumeShaper operation to recycled track %p", track.get());
2681*ec779b8eSAndroid Build Coastguard Worker                 (void)track->applyVolumeShaper(configuration, operation);
2682*ec779b8eSAndroid Build Coastguard Worker             } else {
2683*ec779b8eSAndroid Build Coastguard Worker                 // There is a small chance that the unduck occurs after the next
2684*ec779b8eSAndroid Build Coastguard Worker                 // player has already started, but before it is registered to receive
2685*ec779b8eSAndroid Build Coastguard Worker                 // the unduck command.
2686*ec779b8eSAndroid Build Coastguard Worker                 track = mNextOutput->mTrack;
2687*ec779b8eSAndroid Build Coastguard Worker                 if (track != nullptr) {
2688*ec779b8eSAndroid Build Coastguard Worker                     ALOGD("Forward VolumeShaper operation to track %p", track.get());
2689*ec779b8eSAndroid Build Coastguard Worker                     (void)track->applyVolumeShaper(configuration, operation);
2690*ec779b8eSAndroid Build Coastguard Worker                 }
2691*ec779b8eSAndroid Build Coastguard Worker             }
2692*ec779b8eSAndroid Build Coastguard Worker         }
2693*ec779b8eSAndroid Build Coastguard Worker         status = mVolumeHandler->applyVolumeShaper(configuration, operation);
2694*ec779b8eSAndroid Build Coastguard Worker     }
2695*ec779b8eSAndroid Build Coastguard Worker     return status;
2696*ec779b8eSAndroid Build Coastguard Worker }
2697*ec779b8eSAndroid Build Coastguard Worker 
getVolumeShaperState(int id)2698*ec779b8eSAndroid Build Coastguard Worker sp<VolumeShaper::State> MediaPlayerService::AudioOutput::getVolumeShaperState(int id)
2699*ec779b8eSAndroid Build Coastguard Worker {
2700*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2701*ec779b8eSAndroid Build Coastguard Worker     if (mTrack != 0) {
2702*ec779b8eSAndroid Build Coastguard Worker         return mTrack->getVolumeShaperState(id);
2703*ec779b8eSAndroid Build Coastguard Worker     } else {
2704*ec779b8eSAndroid Build Coastguard Worker         return mVolumeHandler->getVolumeShaperState(id);
2705*ec779b8eSAndroid Build Coastguard Worker     }
2706*ec779b8eSAndroid Build Coastguard Worker }
2707*ec779b8eSAndroid Build Coastguard Worker 
onMoreData(const AudioTrack::Buffer & buffer)2708*ec779b8eSAndroid Build Coastguard Worker size_t MediaPlayerService::AudioOutput::CallbackData::onMoreData(const AudioTrack::Buffer& buffer) {
2709*ec779b8eSAndroid Build Coastguard Worker     ALOGD("data callback");
2710*ec779b8eSAndroid Build Coastguard Worker     lock();
2711*ec779b8eSAndroid Build Coastguard Worker     sp<AudioOutput> me = getOutput();
2712*ec779b8eSAndroid Build Coastguard Worker     if (me == nullptr) {
2713*ec779b8eSAndroid Build Coastguard Worker         unlock();
2714*ec779b8eSAndroid Build Coastguard Worker         return 0;
2715*ec779b8eSAndroid Build Coastguard Worker     }
2716*ec779b8eSAndroid Build Coastguard Worker     size_t actualSize = (*me->mCallback)(
2717*ec779b8eSAndroid Build Coastguard Worker             me, buffer.data(), buffer.size(), me->mCallbackCookie,
2718*ec779b8eSAndroid Build Coastguard Worker             CB_EVENT_FILL_BUFFER);
2719*ec779b8eSAndroid Build Coastguard Worker 
2720*ec779b8eSAndroid Build Coastguard Worker     // Log when no data is returned from the callback.
2721*ec779b8eSAndroid Build Coastguard Worker     // (1) We may have no data (especially with network streaming sources).
2722*ec779b8eSAndroid Build Coastguard Worker     // (2) We may have reached the EOS and the audio track is not stopped yet.
2723*ec779b8eSAndroid Build Coastguard Worker     // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
2724*ec779b8eSAndroid Build Coastguard Worker     // NuPlayerRenderer will return zero when it doesn't have data (it doesn't block to fill).
2725*ec779b8eSAndroid Build Coastguard Worker     //
2726*ec779b8eSAndroid Build Coastguard Worker     // This is a benign busy-wait, with the next data request generated 10 ms or more later;
2727*ec779b8eSAndroid Build Coastguard Worker     // nevertheless for power reasons, we don't want to see too many of these.
2728*ec779b8eSAndroid Build Coastguard Worker 
2729*ec779b8eSAndroid Build Coastguard Worker     ALOGV_IF(actualSize == 0 && buffer.size() > 0, "callbackwrapper: empty buffer returned");
2730*ec779b8eSAndroid Build Coastguard Worker     unlock();
2731*ec779b8eSAndroid Build Coastguard Worker     return actualSize;
2732*ec779b8eSAndroid Build Coastguard Worker }
2733*ec779b8eSAndroid Build Coastguard Worker 
onStreamEnd()2734*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::CallbackData::onStreamEnd() {
2735*ec779b8eSAndroid Build Coastguard Worker     lock();
2736*ec779b8eSAndroid Build Coastguard Worker     sp<AudioOutput> me = getOutput();
2737*ec779b8eSAndroid Build Coastguard Worker     if (me == nullptr) {
2738*ec779b8eSAndroid Build Coastguard Worker         unlock();
2739*ec779b8eSAndroid Build Coastguard Worker         return;
2740*ec779b8eSAndroid Build Coastguard Worker     }
2741*ec779b8eSAndroid Build Coastguard Worker     ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
2742*ec779b8eSAndroid Build Coastguard Worker     (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
2743*ec779b8eSAndroid Build Coastguard Worker             me->mCallbackCookie, CB_EVENT_STREAM_END);
2744*ec779b8eSAndroid Build Coastguard Worker     unlock();
2745*ec779b8eSAndroid Build Coastguard Worker }
2746*ec779b8eSAndroid Build Coastguard Worker 
2747*ec779b8eSAndroid Build Coastguard Worker 
onNewIAudioTrack()2748*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::CallbackData::onNewIAudioTrack() {
2749*ec779b8eSAndroid Build Coastguard Worker     lock();
2750*ec779b8eSAndroid Build Coastguard Worker     sp<AudioOutput> me = getOutput();
2751*ec779b8eSAndroid Build Coastguard Worker     if (me == nullptr) {
2752*ec779b8eSAndroid Build Coastguard Worker         unlock();
2753*ec779b8eSAndroid Build Coastguard Worker         return;
2754*ec779b8eSAndroid Build Coastguard Worker     }
2755*ec779b8eSAndroid Build Coastguard Worker     ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
2756*ec779b8eSAndroid Build Coastguard Worker     (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
2757*ec779b8eSAndroid Build Coastguard Worker             me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
2758*ec779b8eSAndroid Build Coastguard Worker     unlock();
2759*ec779b8eSAndroid Build Coastguard Worker }
2760*ec779b8eSAndroid Build Coastguard Worker 
onUnderrun()2761*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::AudioOutput::CallbackData::onUnderrun() {
2762*ec779b8eSAndroid Build Coastguard Worker     // This occurs when there is no data available, typically
2763*ec779b8eSAndroid Build Coastguard Worker     // when there is a failure to supply data to the AudioTrack.  It can also
2764*ec779b8eSAndroid Build Coastguard Worker     // occur in non-offloaded mode when the audio device comes out of standby.
2765*ec779b8eSAndroid Build Coastguard Worker     //
2766*ec779b8eSAndroid Build Coastguard Worker     // If an AudioTrack underruns it outputs silence. Since this happens suddenly
2767*ec779b8eSAndroid Build Coastguard Worker     // it may sound like an audible pop or glitch.
2768*ec779b8eSAndroid Build Coastguard Worker     //
2769*ec779b8eSAndroid Build Coastguard Worker     // The underrun event is sent once per track underrun; the condition is reset
2770*ec779b8eSAndroid Build Coastguard Worker     // when more data is sent to the AudioTrack.
2771*ec779b8eSAndroid Build Coastguard Worker     ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
2772*ec779b8eSAndroid Build Coastguard Worker 
2773*ec779b8eSAndroid Build Coastguard Worker }
2774*ec779b8eSAndroid Build Coastguard Worker 
getSessionId() const2775*ec779b8eSAndroid Build Coastguard Worker audio_session_t MediaPlayerService::AudioOutput::getSessionId() const
2776*ec779b8eSAndroid Build Coastguard Worker {
2777*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2778*ec779b8eSAndroid Build Coastguard Worker     return mSessionId;
2779*ec779b8eSAndroid Build Coastguard Worker }
2780*ec779b8eSAndroid Build Coastguard Worker 
getSampleRate() const2781*ec779b8eSAndroid Build Coastguard Worker uint32_t MediaPlayerService::AudioOutput::getSampleRate() const
2782*ec779b8eSAndroid Build Coastguard Worker {
2783*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2784*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) return 0;
2785*ec779b8eSAndroid Build Coastguard Worker     return mTrack->getSampleRate();
2786*ec779b8eSAndroid Build Coastguard Worker }
2787*ec779b8eSAndroid Build Coastguard Worker 
getBufferDurationInUs() const2788*ec779b8eSAndroid Build Coastguard Worker int64_t MediaPlayerService::AudioOutput::getBufferDurationInUs() const
2789*ec779b8eSAndroid Build Coastguard Worker {
2790*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2791*ec779b8eSAndroid Build Coastguard Worker     if (mTrack == 0) {
2792*ec779b8eSAndroid Build Coastguard Worker         return 0;
2793*ec779b8eSAndroid Build Coastguard Worker     }
2794*ec779b8eSAndroid Build Coastguard Worker     int64_t duration;
2795*ec779b8eSAndroid Build Coastguard Worker     if (mTrack->getBufferDurationInUs(&duration) != OK) {
2796*ec779b8eSAndroid Build Coastguard Worker         return 0;
2797*ec779b8eSAndroid Build Coastguard Worker     }
2798*ec779b8eSAndroid Build Coastguard Worker     return duration;
2799*ec779b8eSAndroid Build Coastguard Worker }
2800*ec779b8eSAndroid Build Coastguard Worker 
2801*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
2802*ec779b8eSAndroid Build Coastguard Worker 
2803*ec779b8eSAndroid Build Coastguard Worker struct CallbackThread : public Thread {
2804*ec779b8eSAndroid Build Coastguard Worker     CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
2805*ec779b8eSAndroid Build Coastguard Worker                    MediaPlayerBase::AudioSink::AudioCallback cb,
2806*ec779b8eSAndroid Build Coastguard Worker                    const wp<RefBase>& cookie);
2807*ec779b8eSAndroid Build Coastguard Worker 
2808*ec779b8eSAndroid Build Coastguard Worker protected:
2809*ec779b8eSAndroid Build Coastguard Worker     virtual ~CallbackThread();
2810*ec779b8eSAndroid Build Coastguard Worker 
2811*ec779b8eSAndroid Build Coastguard Worker     virtual bool threadLoop();
2812*ec779b8eSAndroid Build Coastguard Worker 
2813*ec779b8eSAndroid Build Coastguard Worker private:
2814*ec779b8eSAndroid Build Coastguard Worker     wp<MediaPlayerBase::AudioSink> mSink;
2815*ec779b8eSAndroid Build Coastguard Worker     MediaPlayerBase::AudioSink::AudioCallback mCallback;
2816*ec779b8eSAndroid Build Coastguard Worker     wp<RefBase> mCookie;
2817*ec779b8eSAndroid Build Coastguard Worker     void *mBuffer;
2818*ec779b8eSAndroid Build Coastguard Worker     size_t mBufferSize;
2819*ec779b8eSAndroid Build Coastguard Worker 
2820*ec779b8eSAndroid Build Coastguard Worker     CallbackThread(const CallbackThread &);
2821*ec779b8eSAndroid Build Coastguard Worker     CallbackThread &operator=(const CallbackThread &);
2822*ec779b8eSAndroid Build Coastguard Worker };
2823*ec779b8eSAndroid Build Coastguard Worker 
CallbackThread(const wp<MediaPlayerBase::AudioSink> & sink,MediaPlayerBase::AudioSink::AudioCallback cb,const wp<RefBase> & cookie)2824*ec779b8eSAndroid Build Coastguard Worker CallbackThread::CallbackThread(
2825*ec779b8eSAndroid Build Coastguard Worker         const wp<MediaPlayerBase::AudioSink> &sink,
2826*ec779b8eSAndroid Build Coastguard Worker         MediaPlayerBase::AudioSink::AudioCallback cb,
2827*ec779b8eSAndroid Build Coastguard Worker         const wp<RefBase>& cookie)
2828*ec779b8eSAndroid Build Coastguard Worker     : mSink(sink),
2829*ec779b8eSAndroid Build Coastguard Worker       mCallback(cb),
2830*ec779b8eSAndroid Build Coastguard Worker       mCookie(cookie),
2831*ec779b8eSAndroid Build Coastguard Worker       mBuffer(NULL),
2832*ec779b8eSAndroid Build Coastguard Worker       mBufferSize(0) {
2833*ec779b8eSAndroid Build Coastguard Worker }
2834*ec779b8eSAndroid Build Coastguard Worker 
~CallbackThread()2835*ec779b8eSAndroid Build Coastguard Worker CallbackThread::~CallbackThread() {
2836*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer) {
2837*ec779b8eSAndroid Build Coastguard Worker         free(mBuffer);
2838*ec779b8eSAndroid Build Coastguard Worker         mBuffer = NULL;
2839*ec779b8eSAndroid Build Coastguard Worker     }
2840*ec779b8eSAndroid Build Coastguard Worker }
2841*ec779b8eSAndroid Build Coastguard Worker 
threadLoop()2842*ec779b8eSAndroid Build Coastguard Worker bool CallbackThread::threadLoop() {
2843*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
2844*ec779b8eSAndroid Build Coastguard Worker     if (sink == NULL) {
2845*ec779b8eSAndroid Build Coastguard Worker         return false;
2846*ec779b8eSAndroid Build Coastguard Worker     }
2847*ec779b8eSAndroid Build Coastguard Worker 
2848*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer == NULL) {
2849*ec779b8eSAndroid Build Coastguard Worker         mBufferSize = sink->bufferSize();
2850*ec779b8eSAndroid Build Coastguard Worker         mBuffer = malloc(mBufferSize);
2851*ec779b8eSAndroid Build Coastguard Worker     }
2852*ec779b8eSAndroid Build Coastguard Worker 
2853*ec779b8eSAndroid Build Coastguard Worker     size_t actualSize =
2854*ec779b8eSAndroid Build Coastguard Worker         (*mCallback)(sink, mBuffer, mBufferSize, mCookie,
2855*ec779b8eSAndroid Build Coastguard Worker                 MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER);
2856*ec779b8eSAndroid Build Coastguard Worker 
2857*ec779b8eSAndroid Build Coastguard Worker     if (actualSize > 0) {
2858*ec779b8eSAndroid Build Coastguard Worker         sink->write(mBuffer, actualSize);
2859*ec779b8eSAndroid Build Coastguard Worker         // Could return false on sink->write() error or short count.
2860*ec779b8eSAndroid Build Coastguard Worker         // Not necessarily appropriate but would work for AudioCache behavior.
2861*ec779b8eSAndroid Build Coastguard Worker     }
2862*ec779b8eSAndroid Build Coastguard Worker 
2863*ec779b8eSAndroid Build Coastguard Worker     return true;
2864*ec779b8eSAndroid Build Coastguard Worker }
2865*ec779b8eSAndroid Build Coastguard Worker 
2866*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
2867*ec779b8eSAndroid Build Coastguard Worker 
addBatteryData(uint32_t params)2868*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::addBatteryData(uint32_t params) {
2869*ec779b8eSAndroid Build Coastguard Worker     mBatteryTracker.addBatteryData(params);
2870*ec779b8eSAndroid Build Coastguard Worker }
2871*ec779b8eSAndroid Build Coastguard Worker 
pullBatteryData(Parcel * reply)2872*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
2873*ec779b8eSAndroid Build Coastguard Worker     return mBatteryTracker.pullBatteryData(reply);
2874*ec779b8eSAndroid Build Coastguard Worker }
2875*ec779b8eSAndroid Build Coastguard Worker 
BatteryTracker()2876*ec779b8eSAndroid Build Coastguard Worker MediaPlayerService::BatteryTracker::BatteryTracker() {
2877*ec779b8eSAndroid Build Coastguard Worker     mBatteryAudio.refCount = 0;
2878*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2879*ec779b8eSAndroid Build Coastguard Worker         mBatteryAudio.deviceOn[i] = 0;
2880*ec779b8eSAndroid Build Coastguard Worker         mBatteryAudio.lastTime[i] = 0;
2881*ec779b8eSAndroid Build Coastguard Worker         mBatteryAudio.totalTime[i] = 0;
2882*ec779b8eSAndroid Build Coastguard Worker     }
2883*ec779b8eSAndroid Build Coastguard Worker     // speaker is on by default
2884*ec779b8eSAndroid Build Coastguard Worker     mBatteryAudio.deviceOn[SPEAKER] = 1;
2885*ec779b8eSAndroid Build Coastguard Worker 
2886*ec779b8eSAndroid Build Coastguard Worker     // reset battery stats
2887*ec779b8eSAndroid Build Coastguard Worker     // if the mediaserver has crashed, battery stats could be left
2888*ec779b8eSAndroid Build Coastguard Worker     // in bad state, reset the state upon service start.
2889*ec779b8eSAndroid Build Coastguard Worker     BatteryNotifier::getInstance().noteResetVideo();
2890*ec779b8eSAndroid Build Coastguard Worker }
2891*ec779b8eSAndroid Build Coastguard Worker 
addBatteryData(uint32_t params)2892*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerService::BatteryTracker::addBatteryData(uint32_t params)
2893*ec779b8eSAndroid Build Coastguard Worker {
2894*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
2895*ec779b8eSAndroid Build Coastguard Worker 
2896*ec779b8eSAndroid Build Coastguard Worker     int32_t time = systemTime() / 1000000L;
2897*ec779b8eSAndroid Build Coastguard Worker 
2898*ec779b8eSAndroid Build Coastguard Worker     // change audio output devices. This notification comes from AudioFlinger
2899*ec779b8eSAndroid Build Coastguard Worker     if ((params & kBatteryDataSpeakerOn)
2900*ec779b8eSAndroid Build Coastguard Worker             || (params & kBatteryDataOtherAudioDeviceOn)) {
2901*ec779b8eSAndroid Build Coastguard Worker 
2902*ec779b8eSAndroid Build Coastguard Worker         int deviceOn[NUM_AUDIO_DEVICES];
2903*ec779b8eSAndroid Build Coastguard Worker         for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2904*ec779b8eSAndroid Build Coastguard Worker             deviceOn[i] = 0;
2905*ec779b8eSAndroid Build Coastguard Worker         }
2906*ec779b8eSAndroid Build Coastguard Worker 
2907*ec779b8eSAndroid Build Coastguard Worker         if ((params & kBatteryDataSpeakerOn)
2908*ec779b8eSAndroid Build Coastguard Worker                 && (params & kBatteryDataOtherAudioDeviceOn)) {
2909*ec779b8eSAndroid Build Coastguard Worker             deviceOn[SPEAKER_AND_OTHER] = 1;
2910*ec779b8eSAndroid Build Coastguard Worker         } else if (params & kBatteryDataSpeakerOn) {
2911*ec779b8eSAndroid Build Coastguard Worker             deviceOn[SPEAKER] = 1;
2912*ec779b8eSAndroid Build Coastguard Worker         } else {
2913*ec779b8eSAndroid Build Coastguard Worker             deviceOn[OTHER_AUDIO_DEVICE] = 1;
2914*ec779b8eSAndroid Build Coastguard Worker         }
2915*ec779b8eSAndroid Build Coastguard Worker 
2916*ec779b8eSAndroid Build Coastguard Worker         for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2917*ec779b8eSAndroid Build Coastguard Worker             if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
2918*ec779b8eSAndroid Build Coastguard Worker 
2919*ec779b8eSAndroid Build Coastguard Worker                 if (mBatteryAudio.refCount > 0) { // if playing audio
2920*ec779b8eSAndroid Build Coastguard Worker                     if (!deviceOn[i]) {
2921*ec779b8eSAndroid Build Coastguard Worker                         mBatteryAudio.lastTime[i] += time;
2922*ec779b8eSAndroid Build Coastguard Worker                         mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2923*ec779b8eSAndroid Build Coastguard Worker                         mBatteryAudio.lastTime[i] = 0;
2924*ec779b8eSAndroid Build Coastguard Worker                     } else {
2925*ec779b8eSAndroid Build Coastguard Worker                         mBatteryAudio.lastTime[i] = 0 - time;
2926*ec779b8eSAndroid Build Coastguard Worker                     }
2927*ec779b8eSAndroid Build Coastguard Worker                 }
2928*ec779b8eSAndroid Build Coastguard Worker 
2929*ec779b8eSAndroid Build Coastguard Worker                 mBatteryAudio.deviceOn[i] = deviceOn[i];
2930*ec779b8eSAndroid Build Coastguard Worker             }
2931*ec779b8eSAndroid Build Coastguard Worker         }
2932*ec779b8eSAndroid Build Coastguard Worker         return;
2933*ec779b8eSAndroid Build Coastguard Worker     }
2934*ec779b8eSAndroid Build Coastguard Worker 
2935*ec779b8eSAndroid Build Coastguard Worker     // an audio stream is started
2936*ec779b8eSAndroid Build Coastguard Worker     if (params & kBatteryDataAudioFlingerStart) {
2937*ec779b8eSAndroid Build Coastguard Worker         // record the start time only if currently no other audio
2938*ec779b8eSAndroid Build Coastguard Worker         // is being played
2939*ec779b8eSAndroid Build Coastguard Worker         if (mBatteryAudio.refCount == 0) {
2940*ec779b8eSAndroid Build Coastguard Worker             for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2941*ec779b8eSAndroid Build Coastguard Worker                 if (mBatteryAudio.deviceOn[i]) {
2942*ec779b8eSAndroid Build Coastguard Worker                     mBatteryAudio.lastTime[i] -= time;
2943*ec779b8eSAndroid Build Coastguard Worker                 }
2944*ec779b8eSAndroid Build Coastguard Worker             }
2945*ec779b8eSAndroid Build Coastguard Worker         }
2946*ec779b8eSAndroid Build Coastguard Worker 
2947*ec779b8eSAndroid Build Coastguard Worker         mBatteryAudio.refCount ++;
2948*ec779b8eSAndroid Build Coastguard Worker         return;
2949*ec779b8eSAndroid Build Coastguard Worker 
2950*ec779b8eSAndroid Build Coastguard Worker     } else if (params & kBatteryDataAudioFlingerStop) {
2951*ec779b8eSAndroid Build Coastguard Worker         if (mBatteryAudio.refCount <= 0) {
2952*ec779b8eSAndroid Build Coastguard Worker             ALOGW("Battery track warning: refCount is <= 0");
2953*ec779b8eSAndroid Build Coastguard Worker             return;
2954*ec779b8eSAndroid Build Coastguard Worker         }
2955*ec779b8eSAndroid Build Coastguard Worker 
2956*ec779b8eSAndroid Build Coastguard Worker         // record the stop time only if currently this is the only
2957*ec779b8eSAndroid Build Coastguard Worker         // audio being played
2958*ec779b8eSAndroid Build Coastguard Worker         if (mBatteryAudio.refCount == 1) {
2959*ec779b8eSAndroid Build Coastguard Worker             for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
2960*ec779b8eSAndroid Build Coastguard Worker                 if (mBatteryAudio.deviceOn[i]) {
2961*ec779b8eSAndroid Build Coastguard Worker                     mBatteryAudio.lastTime[i] += time;
2962*ec779b8eSAndroid Build Coastguard Worker                     mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
2963*ec779b8eSAndroid Build Coastguard Worker                     mBatteryAudio.lastTime[i] = 0;
2964*ec779b8eSAndroid Build Coastguard Worker                 }
2965*ec779b8eSAndroid Build Coastguard Worker             }
2966*ec779b8eSAndroid Build Coastguard Worker         }
2967*ec779b8eSAndroid Build Coastguard Worker 
2968*ec779b8eSAndroid Build Coastguard Worker         mBatteryAudio.refCount --;
2969*ec779b8eSAndroid Build Coastguard Worker         return;
2970*ec779b8eSAndroid Build Coastguard Worker     }
2971*ec779b8eSAndroid Build Coastguard Worker 
2972*ec779b8eSAndroid Build Coastguard Worker     uid_t uid = IPCThreadState::self()->getCallingUid();
2973*ec779b8eSAndroid Build Coastguard Worker     if (uid == AID_MEDIA) {
2974*ec779b8eSAndroid Build Coastguard Worker         return;
2975*ec779b8eSAndroid Build Coastguard Worker     }
2976*ec779b8eSAndroid Build Coastguard Worker     int index = mBatteryData.indexOfKey(uid);
2977*ec779b8eSAndroid Build Coastguard Worker 
2978*ec779b8eSAndroid Build Coastguard Worker     if (index < 0) { // create a new entry for this UID
2979*ec779b8eSAndroid Build Coastguard Worker         BatteryUsageInfo info;
2980*ec779b8eSAndroid Build Coastguard Worker         info.audioTotalTime = 0;
2981*ec779b8eSAndroid Build Coastguard Worker         info.videoTotalTime = 0;
2982*ec779b8eSAndroid Build Coastguard Worker         info.audioLastTime = 0;
2983*ec779b8eSAndroid Build Coastguard Worker         info.videoLastTime = 0;
2984*ec779b8eSAndroid Build Coastguard Worker         info.refCount = 0;
2985*ec779b8eSAndroid Build Coastguard Worker 
2986*ec779b8eSAndroid Build Coastguard Worker         if (mBatteryData.add(uid, info) == NO_MEMORY) {
2987*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Battery track error: no memory for new app");
2988*ec779b8eSAndroid Build Coastguard Worker             return;
2989*ec779b8eSAndroid Build Coastguard Worker         }
2990*ec779b8eSAndroid Build Coastguard Worker     }
2991*ec779b8eSAndroid Build Coastguard Worker 
2992*ec779b8eSAndroid Build Coastguard Worker     BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
2993*ec779b8eSAndroid Build Coastguard Worker 
2994*ec779b8eSAndroid Build Coastguard Worker     if (params & kBatteryDataCodecStarted) {
2995*ec779b8eSAndroid Build Coastguard Worker         if (params & kBatteryDataTrackAudio) {
2996*ec779b8eSAndroid Build Coastguard Worker             info.audioLastTime -= time;
2997*ec779b8eSAndroid Build Coastguard Worker             info.refCount ++;
2998*ec779b8eSAndroid Build Coastguard Worker         }
2999*ec779b8eSAndroid Build Coastguard Worker         if (params & kBatteryDataTrackVideo) {
3000*ec779b8eSAndroid Build Coastguard Worker             info.videoLastTime -= time;
3001*ec779b8eSAndroid Build Coastguard Worker             info.refCount ++;
3002*ec779b8eSAndroid Build Coastguard Worker         }
3003*ec779b8eSAndroid Build Coastguard Worker     } else {
3004*ec779b8eSAndroid Build Coastguard Worker         if (info.refCount == 0) {
3005*ec779b8eSAndroid Build Coastguard Worker             ALOGW("Battery track warning: refCount is already 0");
3006*ec779b8eSAndroid Build Coastguard Worker             return;
3007*ec779b8eSAndroid Build Coastguard Worker         } else if (info.refCount < 0) {
3008*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Battery track error: refCount < 0");
3009*ec779b8eSAndroid Build Coastguard Worker             mBatteryData.removeItem(uid);
3010*ec779b8eSAndroid Build Coastguard Worker             return;
3011*ec779b8eSAndroid Build Coastguard Worker         }
3012*ec779b8eSAndroid Build Coastguard Worker 
3013*ec779b8eSAndroid Build Coastguard Worker         if (params & kBatteryDataTrackAudio) {
3014*ec779b8eSAndroid Build Coastguard Worker             info.audioLastTime += time;
3015*ec779b8eSAndroid Build Coastguard Worker             info.refCount --;
3016*ec779b8eSAndroid Build Coastguard Worker         }
3017*ec779b8eSAndroid Build Coastguard Worker         if (params & kBatteryDataTrackVideo) {
3018*ec779b8eSAndroid Build Coastguard Worker             info.videoLastTime += time;
3019*ec779b8eSAndroid Build Coastguard Worker             info.refCount --;
3020*ec779b8eSAndroid Build Coastguard Worker         }
3021*ec779b8eSAndroid Build Coastguard Worker 
3022*ec779b8eSAndroid Build Coastguard Worker         // no stream is being played by this UID
3023*ec779b8eSAndroid Build Coastguard Worker         if (info.refCount == 0) {
3024*ec779b8eSAndroid Build Coastguard Worker             info.audioTotalTime += info.audioLastTime;
3025*ec779b8eSAndroid Build Coastguard Worker             info.audioLastTime = 0;
3026*ec779b8eSAndroid Build Coastguard Worker             info.videoTotalTime += info.videoLastTime;
3027*ec779b8eSAndroid Build Coastguard Worker             info.videoLastTime = 0;
3028*ec779b8eSAndroid Build Coastguard Worker         }
3029*ec779b8eSAndroid Build Coastguard Worker     }
3030*ec779b8eSAndroid Build Coastguard Worker }
3031*ec779b8eSAndroid Build Coastguard Worker 
pullBatteryData(Parcel * reply)3032*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerService::BatteryTracker::pullBatteryData(Parcel* reply) {
3033*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock(mLock);
3034*ec779b8eSAndroid Build Coastguard Worker 
3035*ec779b8eSAndroid Build Coastguard Worker     // audio output devices usage
3036*ec779b8eSAndroid Build Coastguard Worker     int32_t time = systemTime() / 1000000L; //in ms
3037*ec779b8eSAndroid Build Coastguard Worker     int32_t totalTime;
3038*ec779b8eSAndroid Build Coastguard Worker 
3039*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
3040*ec779b8eSAndroid Build Coastguard Worker         totalTime = mBatteryAudio.totalTime[i];
3041*ec779b8eSAndroid Build Coastguard Worker 
3042*ec779b8eSAndroid Build Coastguard Worker         if (mBatteryAudio.deviceOn[i]
3043*ec779b8eSAndroid Build Coastguard Worker             && (mBatteryAudio.lastTime[i] != 0)) {
3044*ec779b8eSAndroid Build Coastguard Worker                 int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
3045*ec779b8eSAndroid Build Coastguard Worker                 totalTime += tmpTime;
3046*ec779b8eSAndroid Build Coastguard Worker         }
3047*ec779b8eSAndroid Build Coastguard Worker 
3048*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(totalTime);
3049*ec779b8eSAndroid Build Coastguard Worker         // reset the total time
3050*ec779b8eSAndroid Build Coastguard Worker         mBatteryAudio.totalTime[i] = 0;
3051*ec779b8eSAndroid Build Coastguard Worker    }
3052*ec779b8eSAndroid Build Coastguard Worker 
3053*ec779b8eSAndroid Build Coastguard Worker     // codec usage
3054*ec779b8eSAndroid Build Coastguard Worker     BatteryUsageInfo info;
3055*ec779b8eSAndroid Build Coastguard Worker     int size = mBatteryData.size();
3056*ec779b8eSAndroid Build Coastguard Worker 
3057*ec779b8eSAndroid Build Coastguard Worker     reply->writeInt32(size);
3058*ec779b8eSAndroid Build Coastguard Worker     int i = 0;
3059*ec779b8eSAndroid Build Coastguard Worker 
3060*ec779b8eSAndroid Build Coastguard Worker     while (i < size) {
3061*ec779b8eSAndroid Build Coastguard Worker         info = mBatteryData.valueAt(i);
3062*ec779b8eSAndroid Build Coastguard Worker 
3063*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(mBatteryData.keyAt(i)); //UID
3064*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(info.audioTotalTime);
3065*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(info.videoTotalTime);
3066*ec779b8eSAndroid Build Coastguard Worker 
3067*ec779b8eSAndroid Build Coastguard Worker         info.audioTotalTime = 0;
3068*ec779b8eSAndroid Build Coastguard Worker         info.videoTotalTime = 0;
3069*ec779b8eSAndroid Build Coastguard Worker 
3070*ec779b8eSAndroid Build Coastguard Worker         // remove the UID entry where no stream is being played
3071*ec779b8eSAndroid Build Coastguard Worker         if (info.refCount <= 0) {
3072*ec779b8eSAndroid Build Coastguard Worker             mBatteryData.removeItemsAt(i);
3073*ec779b8eSAndroid Build Coastguard Worker             size --;
3074*ec779b8eSAndroid Build Coastguard Worker             i --;
3075*ec779b8eSAndroid Build Coastguard Worker         }
3076*ec779b8eSAndroid Build Coastguard Worker         i++;
3077*ec779b8eSAndroid Build Coastguard Worker     }
3078*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
3079*ec779b8eSAndroid Build Coastguard Worker }
3080*ec779b8eSAndroid Build Coastguard Worker 
3081*ec779b8eSAndroid Build Coastguard Worker #ifdef FUZZ_MODE_MEDIA_PLAYER_SERVICE
createForFuzzTesting()3082*ec779b8eSAndroid Build Coastguard Worker sp<MediaPlayerService> MediaPlayerService::createForFuzzTesting() {
3083*ec779b8eSAndroid Build Coastguard Worker     return sp<MediaPlayerService>::make();
3084*ec779b8eSAndroid Build Coastguard Worker }
3085*ec779b8eSAndroid Build Coastguard Worker #endif // FUZZ_MODE_MEDIA_PLAYER_SERVICE
3086*ec779b8eSAndroid Build Coastguard Worker 
3087*ec779b8eSAndroid Build Coastguard Worker } // namespace android
3088