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