MediaPlayerService.cpp revision a64c8c79af1a15911c55306d83a797fa50969f77
1/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18// Proxy for media player implementations
19
20//#define LOG_NDEBUG 0
21#define LOG_TAG "MediaPlayerService"
22#include <utils/Log.h>
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <dirent.h>
27#include <unistd.h>
28
29#include <string.h>
30
31#include <cutils/atomic.h>
32#include <cutils/properties.h> // for property_get
33
34#include <utils/misc.h>
35
36#include <android_runtime/ActivityManager.h>
37
38#include <binder/IPCThreadState.h>
39#include <binder/IServiceManager.h>
40#include <binder/MemoryHeapBase.h>
41#include <binder/MemoryBase.h>
42#include <utils/Errors.h>  // for status_t
43#include <utils/String8.h>
44#include <utils/Vector.h>
45#include <cutils/properties.h>
46
47#include <media/MediaPlayerInterface.h>
48#include <media/mediarecorder.h>
49#include <media/MediaMetadataRetrieverInterface.h>
50#include <media/Metadata.h>
51#include <media/AudioTrack.h>
52
53#include "MediaRecorderClient.h"
54#include "MediaPlayerService.h"
55#include "MetadataRetrieverClient.h"
56
57#include "MidiFile.h"
58#include "VorbisPlayer.h"
59#include <media/PVPlayer.h>
60#include "TestPlayerStub.h"
61
62#if USE_STAGEFRIGHT
63#include "StagefrightPlayer.h"
64#endif
65
66#ifdef BUILD_WITH_STAGEFRIGHT
67#include <OMX.h>
68#else
69#include <media/IOMX.h>
70#endif
71
72
73
74/* desktop Linux needs a little help with gettid() */
75#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
76#define __KERNEL__
77# include <linux/unistd.h>
78#ifdef _syscall0
79_syscall0(pid_t,gettid)
80#else
81pid_t gettid() { return syscall(__NR_gettid);}
82#endif
83#undef __KERNEL__
84#endif
85
86namespace {
87using android::media::Metadata;
88using android::status_t;
89using android::OK;
90using android::BAD_VALUE;
91using android::NOT_ENOUGH_DATA;
92using android::Parcel;
93
94// Max number of entries in the filter.
95const int kMaxFilterSize = 64;  // I pulled that out of thin air.
96
97// FIXME: Move all the metadata related function in the Metadata.cpp
98
99
100// Unmarshall a filter from a Parcel.
101// Filter format in a parcel:
102//
103//  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
104// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105// |                       number of entries (n)                   |
106// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107// |                       metadata type 1                         |
108// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109// |                       metadata type 2                         |
110// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111//  ....
112// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113// |                       metadata type n                         |
114// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115//
116// @param p Parcel that should start with a filter.
117// @param[out] filter On exit contains the list of metadata type to be
118//                    filtered.
119// @param[out] status On exit contains the status code to be returned.
120// @return true if the parcel starts with a valid filter.
121bool unmarshallFilter(const Parcel& p,
122                      Metadata::Filter *filter,
123                      status_t *status)
124{
125    int32_t val;
126    if (p.readInt32(&val) != OK)
127    {
128        LOGE("Failed to read filter's length");
129        *status = NOT_ENOUGH_DATA;
130        return false;
131    }
132
133    if( val > kMaxFilterSize || val < 0)
134    {
135        LOGE("Invalid filter len %d", val);
136        *status = BAD_VALUE;
137        return false;
138    }
139
140    const size_t num = val;
141
142    filter->clear();
143    filter->setCapacity(num);
144
145    size_t size = num * sizeof(Metadata::Type);
146
147
148    if (p.dataAvail() < size)
149    {
150        LOGE("Filter too short expected %d but got %d", size, p.dataAvail());
151        *status = NOT_ENOUGH_DATA;
152        return false;
153    }
154
155    const Metadata::Type *data =
156            static_cast<const Metadata::Type*>(p.readInplace(size));
157
158    if (NULL == data)
159    {
160        LOGE("Filter had no data");
161        *status = BAD_VALUE;
162        return false;
163    }
164
165    // TODO: The stl impl of vector would be more efficient here
166    // because it degenerates into a memcpy on pod types. Try to
167    // replace later or use stl::set.
168    for (size_t i = 0; i < num; ++i)
169    {
170        filter->add(*data);
171        ++data;
172    }
173    *status = OK;
174    return true;
175}
176
177// @param filter Of metadata type.
178// @param val To be searched.
179// @return true if a match was found.
180bool findMetadata(const Metadata::Filter& filter, const int32_t val)
181{
182    // Deal with empty and ANY right away
183    if (filter.isEmpty()) return false;
184    if (filter[0] == Metadata::kAny) return true;
185
186    return filter.indexOf(val) >= 0;
187}
188
189}  // anonymous namespace
190
191
192namespace android {
193
194// TODO: Temp hack until we can register players
195typedef struct {
196    const char *extension;
197    const player_type playertype;
198} extmap;
199extmap FILE_EXTS [] =  {
200#if USE_STAGEFRIGHT
201        {".mp4", STAGEFRIGHT_PLAYER},
202        {".3gp", STAGEFRIGHT_PLAYER},
203#endif
204        {".mid", SONIVOX_PLAYER},
205        {".midi", SONIVOX_PLAYER},
206        {".smf", SONIVOX_PLAYER},
207        {".xmf", SONIVOX_PLAYER},
208        {".imy", SONIVOX_PLAYER},
209        {".rtttl", SONIVOX_PLAYER},
210        {".rtx", SONIVOX_PLAYER},
211        {".ota", SONIVOX_PLAYER},
212        {".ogg", VORBIS_PLAYER},
213        {".oga", VORBIS_PLAYER},
214};
215
216// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
217/* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 96;
218/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
219/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
220
221void MediaPlayerService::instantiate() {
222    defaultServiceManager()->addService(
223            String16("media.player"), new MediaPlayerService());
224}
225
226MediaPlayerService::MediaPlayerService()
227{
228    LOGV("MediaPlayerService created");
229    mNextConnId = 1;
230}
231
232MediaPlayerService::~MediaPlayerService()
233{
234    LOGV("MediaPlayerService destroyed");
235}
236
237sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
238{
239#ifndef NO_OPENCORE
240    sp<MediaRecorderClient> recorder = new MediaRecorderClient(pid);
241#else
242    sp<MediaRecorderClient> recorder = NULL;
243#endif
244    LOGV("Create new media recorder client from pid %d", pid);
245    return recorder;
246}
247
248sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
249{
250    sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
251    LOGV("Create new media retriever from pid %d", pid);
252    return retriever;
253}
254
255sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
256{
257    int32_t connId = android_atomic_inc(&mNextConnId);
258    sp<Client> c = new Client(this, pid, connId, client);
259    LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
260    if (NO_ERROR != c->setDataSource(url))
261    {
262        c.clear();
263        return c;
264    }
265    wp<Client> w = c;
266    Mutex::Autolock lock(mLock);
267    mClients.add(w);
268    return c;
269}
270
271sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
272        int fd, int64_t offset, int64_t length)
273{
274    int32_t connId = android_atomic_inc(&mNextConnId);
275    sp<Client> c = new Client(this, pid, connId, client);
276    LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
277            connId, pid, fd, offset, length);
278    if (NO_ERROR != c->setDataSource(fd, offset, length)) {
279        c.clear();
280    } else {
281        wp<Client> w = c;
282        Mutex::Autolock lock(mLock);
283        mClients.add(w);
284    }
285    ::close(fd);
286    return c;
287}
288
289sp<IOMX> MediaPlayerService::createOMX() {
290#ifdef BUILD_WITH_STAGEFRIGHT
291    return new OMX;
292#else
293    return NULL;
294#endif
295}
296
297status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
298{
299    const size_t SIZE = 256;
300    char buffer[SIZE];
301    String8 result;
302
303    result.append(" AudioCache\n");
304    if (mHeap != 0) {
305        snprintf(buffer, 255, "  heap base(%p), size(%d), flags(%d), device(%s)\n",
306                mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
307        result.append(buffer);
308    }
309    snprintf(buffer, 255, "  msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
310            mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
311    result.append(buffer);
312    snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
313            mSampleRate, mSize, mError, mCommandComplete?"true":"false");
314    result.append(buffer);
315    ::write(fd, result.string(), result.size());
316    return NO_ERROR;
317}
318
319status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
320{
321    const size_t SIZE = 256;
322    char buffer[SIZE];
323    String8 result;
324
325    result.append(" AudioOutput\n");
326    snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n",
327            mStreamType, mLeftVolume, mRightVolume);
328    result.append(buffer);
329    snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
330            mMsecsPerFrame, mLatency);
331    result.append(buffer);
332    ::write(fd, result.string(), result.size());
333    if (mTrack != 0) {
334        mTrack->dump(fd, args);
335    }
336    return NO_ERROR;
337}
338
339status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args) const
340{
341    const size_t SIZE = 256;
342    char buffer[SIZE];
343    String8 result;
344    result.append(" Client\n");
345    snprintf(buffer, 255, "  pid(%d), connId(%d), status(%d), looping(%s)\n",
346            mPid, mConnId, mStatus, mLoop?"true": "false");
347    result.append(buffer);
348    write(fd, result.string(), result.size());
349    if (mAudioOutput != 0) {
350        mAudioOutput->dump(fd, args);
351    }
352    write(fd, "\n", 1);
353    return NO_ERROR;
354}
355
356static int myTid() {
357#ifdef HAVE_GETTID
358    return gettid();
359#else
360    return getpid();
361#endif
362}
363
364#if defined(__arm__)
365extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
366        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
367extern "C" void free_malloc_leak_info(uint8_t* info);
368
369void memStatus(int fd, const Vector<String16>& args)
370{
371    const size_t SIZE = 256;
372    char buffer[SIZE];
373    String8 result;
374
375    typedef struct {
376        size_t size;
377        size_t dups;
378        intptr_t * backtrace;
379    } AllocEntry;
380
381    uint8_t *info = NULL;
382    size_t overallSize = 0;
383    size_t infoSize = 0;
384    size_t totalMemory = 0;
385    size_t backtraceSize = 0;
386
387    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
388    if (info) {
389        uint8_t *ptr = info;
390        size_t count = overallSize / infoSize;
391
392        snprintf(buffer, SIZE, " Allocation count %i\n", count);
393        result.append(buffer);
394
395        AllocEntry * entries = new AllocEntry[count];
396
397        for (size_t i = 0; i < count; i++) {
398            // Each entry should be size_t, size_t, intptr_t[backtraceSize]
399            AllocEntry *e = &entries[i];
400
401            e->size = *reinterpret_cast<size_t *>(ptr);
402            ptr += sizeof(size_t);
403
404            e->dups = *reinterpret_cast<size_t *>(ptr);
405            ptr += sizeof(size_t);
406
407            e->backtrace = reinterpret_cast<intptr_t *>(ptr);
408            ptr += sizeof(intptr_t) * backtraceSize;
409        }
410
411        // Now we need to sort the entries.  They come sorted by size but
412        // not by stack trace which causes problems using diff.
413        bool moved;
414        do {
415            moved = false;
416            for (size_t i = 0; i < (count - 1); i++) {
417                AllocEntry *e1 = &entries[i];
418                AllocEntry *e2 = &entries[i+1];
419
420                bool swap = e1->size < e2->size;
421                if (e1->size == e2->size) {
422                    for(size_t j = 0; j < backtraceSize; j++) {
423                        if (e1->backtrace[j] == e2->backtrace[j]) {
424                            continue;
425                        }
426                        swap = e1->backtrace[j] < e2->backtrace[j];
427                        break;
428                    }
429                }
430                if (swap) {
431                    AllocEntry t = entries[i];
432                    entries[i] = entries[i+1];
433                    entries[i+1] = t;
434                    moved = true;
435                }
436            }
437        } while (moved);
438
439        for (size_t i = 0; i < count; i++) {
440            AllocEntry *e = &entries[i];
441
442            snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups);
443            result.append(buffer);
444            for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
445                if (ct) {
446                    result.append(", ");
447                }
448                snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
449                result.append(buffer);
450            }
451            result.append("\n");
452        }
453
454        delete[] entries;
455        free_malloc_leak_info(info);
456    }
457
458    write(fd, result.string(), result.size());
459}
460#endif
461
462status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
463{
464    const size_t SIZE = 256;
465    char buffer[SIZE];
466    String8 result;
467    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
468        snprintf(buffer, SIZE, "Permission Denial: "
469                "can't dump MediaPlayerService from pid=%d, uid=%d\n",
470                IPCThreadState::self()->getCallingPid(),
471                IPCThreadState::self()->getCallingUid());
472        result.append(buffer);
473    } else {
474        Mutex::Autolock lock(mLock);
475        for (int i = 0, n = mClients.size(); i < n; ++i) {
476            sp<Client> c = mClients[i].promote();
477            if (c != 0) c->dump(fd, args);
478        }
479        result.append(" Files opened and/or mapped:\n");
480        snprintf(buffer, SIZE, "/proc/%d/maps", myTid());
481        FILE *f = fopen(buffer, "r");
482        if (f) {
483            while (!feof(f)) {
484                fgets(buffer, SIZE, f);
485                if (strstr(buffer, " /sdcard/") ||
486                    strstr(buffer, " /system/sounds/") ||
487                    strstr(buffer, " /system/media/")) {
488                    result.append("  ");
489                    result.append(buffer);
490                }
491            }
492            fclose(f);
493        } else {
494            result.append("couldn't open ");
495            result.append(buffer);
496            result.append("\n");
497        }
498
499        snprintf(buffer, SIZE, "/proc/%d/fd", myTid());
500        DIR *d = opendir(buffer);
501        if (d) {
502            struct dirent *ent;
503            while((ent = readdir(d)) != NULL) {
504                if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
505                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", myTid(), ent->d_name);
506                    struct stat s;
507                    if (lstat(buffer, &s) == 0) {
508                        if ((s.st_mode & S_IFMT) == S_IFLNK) {
509                            char linkto[256];
510                            int len = readlink(buffer, linkto, sizeof(linkto));
511                            if(len > 0) {
512                                if(len > 255) {
513                                    linkto[252] = '.';
514                                    linkto[253] = '.';
515                                    linkto[254] = '.';
516                                    linkto[255] = 0;
517                                } else {
518                                    linkto[len] = 0;
519                                }
520                                if (strstr(linkto, "/sdcard/") == linkto ||
521                                    strstr(linkto, "/system/sounds/") == linkto ||
522                                    strstr(linkto, "/system/media/") == linkto) {
523                                    result.append("  ");
524                                    result.append(buffer);
525                                    result.append(" -> ");
526                                    result.append(linkto);
527                                    result.append("\n");
528                                }
529                            }
530                        } else {
531                            result.append("  unexpected type for ");
532                            result.append(buffer);
533                            result.append("\n");
534                        }
535                    }
536                }
537            }
538            closedir(d);
539        } else {
540            result.append("couldn't open ");
541            result.append(buffer);
542            result.append("\n");
543        }
544
545#if defined(__arm__)
546        bool dumpMem = false;
547        for (size_t i = 0; i < args.size(); i++) {
548            if (args[i] == String16("-m")) {
549                dumpMem = true;
550            }
551        }
552        if (dumpMem) {
553            memStatus(fd, args);
554        }
555#endif
556    }
557    write(fd, result.string(), result.size());
558    return NO_ERROR;
559}
560
561void MediaPlayerService::removeClient(wp<Client> client)
562{
563    Mutex::Autolock lock(mLock);
564    mClients.remove(client);
565}
566
567MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
568        int32_t connId, const sp<IMediaPlayerClient>& client)
569{
570    LOGV("Client(%d) constructor", connId);
571    mPid = pid;
572    mConnId = connId;
573    mService = service;
574    mClient = client;
575    mLoop = false;
576    mStatus = NO_INIT;
577#if CALLBACK_ANTAGONIZER
578    LOGD("create Antagonizer");
579    mAntagonizer = new Antagonizer(notify, this);
580#endif
581}
582
583MediaPlayerService::Client::~Client()
584{
585    LOGV("Client(%d) destructor pid = %d", mConnId, mPid);
586    mAudioOutput.clear();
587    wp<Client> client(this);
588    disconnect();
589    mService->removeClient(client);
590}
591
592void MediaPlayerService::Client::disconnect()
593{
594    LOGV("disconnect(%d) from pid %d", mConnId, mPid);
595    // grab local reference and clear main reference to prevent future
596    // access to object
597    sp<MediaPlayerBase> p;
598    {
599        Mutex::Autolock l(mLock);
600        p = mPlayer;
601    }
602    mClient.clear();
603
604    mPlayer.clear();
605
606    // clear the notification to prevent callbacks to dead client
607    // and reset the player. We assume the player will serialize
608    // access to itself if necessary.
609    if (p != 0) {
610        p->setNotifyCallback(0, 0);
611#if CALLBACK_ANTAGONIZER
612        LOGD("kill Antagonizer");
613        mAntagonizer->kill();
614#endif
615        p->reset();
616    }
617
618    IPCThreadState::self()->flushCommands();
619}
620
621static player_type getPlayerType(int fd, int64_t offset, int64_t length)
622{
623    char buf[20];
624    lseek(fd, offset, SEEK_SET);
625    read(fd, buf, sizeof(buf));
626    lseek(fd, offset, SEEK_SET);
627
628    long ident = *((long*)buf);
629
630    // Ogg vorbis?
631    if (ident == 0x5367674f) // 'OggS'
632        return VORBIS_PLAYER;
633
634    // Some kind of MIDI?
635    EAS_DATA_HANDLE easdata;
636    if (EAS_Init(&easdata) == EAS_SUCCESS) {
637        EAS_FILE locator;
638        locator.path = NULL;
639        locator.fd = fd;
640        locator.offset = offset;
641        locator.length = length;
642        EAS_HANDLE  eashandle;
643        if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
644            EAS_CloseFile(easdata, eashandle);
645            EAS_Shutdown(easdata);
646            return SONIVOX_PLAYER;
647        }
648        EAS_Shutdown(easdata);
649    }
650
651#if USE_STAGEFRIGHT
652    return STAGEFRIGHT_PLAYER;
653#endif
654
655    // Fall through to PV
656    return PV_PLAYER;
657}
658
659static player_type getPlayerType(const char* url)
660{
661    if (TestPlayerStub::canBeUsed(url)) {
662        return TEST_PLAYER;
663    }
664
665    // use MidiFile for MIDI extensions
666    int lenURL = strlen(url);
667    for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
668        int len = strlen(FILE_EXTS[i].extension);
669        int start = lenURL - len;
670        if (start > 0) {
671            if (!strncmp(url + start, FILE_EXTS[i].extension, len)) {
672                return FILE_EXTS[i].playertype;
673            }
674        }
675    }
676
677#if USE_STAGEFRIGHT
678    return STAGEFRIGHT_PLAYER;
679#endif
680
681    // Fall through to PV
682    return PV_PLAYER;
683}
684
685static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
686        notify_callback_f notifyFunc)
687{
688    sp<MediaPlayerBase> p;
689    switch (playerType) {
690#ifndef NO_OPENCORE
691        case PV_PLAYER:
692            LOGV(" create PVPlayer");
693            p = new PVPlayer();
694            break;
695#endif
696        case SONIVOX_PLAYER:
697            LOGV(" create MidiFile");
698            p = new MidiFile();
699            break;
700        case VORBIS_PLAYER:
701            LOGV(" create VorbisPlayer");
702            p = new VorbisPlayer();
703            break;
704#if USE_STAGEFRIGHT
705        case STAGEFRIGHT_PLAYER:
706            LOGV(" create StagefrightPlayer");
707            p = new StagefrightPlayer;
708            break;
709#else
710        case STAGEFRIGHT_PLAYER:
711            LOG_ALWAYS_FATAL(
712                    "Should not be here, stagefright player not enabled.");
713            break;
714#endif
715        case TEST_PLAYER:
716            LOGV("Create Test Player stub");
717            p = new TestPlayerStub();
718            break;
719    }
720    if (p != NULL) {
721        if (p->initCheck() == NO_ERROR) {
722            p->setNotifyCallback(cookie, notifyFunc);
723        } else {
724            p.clear();
725        }
726    }
727    if (p == NULL) {
728        LOGE("Failed to create player object");
729    }
730    return p;
731}
732
733sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
734{
735    // determine if we have the right player type
736    sp<MediaPlayerBase> p = mPlayer;
737    if ((p != NULL) && (p->playerType() != playerType)) {
738        LOGV("delete player");
739        p.clear();
740    }
741    if (p == NULL) {
742        p = android::createPlayer(playerType, this, notify);
743    }
744    return p;
745}
746
747status_t MediaPlayerService::Client::setDataSource(const char *url)
748{
749    LOGV("setDataSource(%s)", url);
750    if (url == NULL)
751        return UNKNOWN_ERROR;
752
753    if (strncmp(url, "content://", 10) == 0) {
754        // get a filedescriptor for the content Uri and
755        // pass it to the setDataSource(fd) method
756
757        String16 url16(url);
758        int fd = android::openContentProviderFile(url16);
759        if (fd < 0)
760        {
761            LOGE("Couldn't open fd for %s", url);
762            return UNKNOWN_ERROR;
763        }
764        setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
765        close(fd);
766        return mStatus;
767    } else {
768        player_type playerType = getPlayerType(url);
769        LOGV("player type = %d", playerType);
770
771        // create the right type of player
772        sp<MediaPlayerBase> p = createPlayer(playerType);
773        if (p == NULL) return NO_INIT;
774
775        if (!p->hardwareOutput()) {
776            mAudioOutput = new AudioOutput();
777            static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
778        }
779
780        // now set data source
781        LOGV(" setDataSource");
782        mStatus = p->setDataSource(url);
783        if (mStatus == NO_ERROR) {
784            mPlayer = p;
785        } else {
786            LOGE("  error: %d", mStatus);
787        }
788        return mStatus;
789    }
790}
791
792status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
793{
794    LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
795    struct stat sb;
796    int ret = fstat(fd, &sb);
797    if (ret != 0) {
798        LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
799        return UNKNOWN_ERROR;
800    }
801
802    LOGV("st_dev  = %llu", sb.st_dev);
803    LOGV("st_mode = %u", sb.st_mode);
804    LOGV("st_uid  = %lu", sb.st_uid);
805    LOGV("st_gid  = %lu", sb.st_gid);
806    LOGV("st_size = %llu", sb.st_size);
807
808    if (offset >= sb.st_size) {
809        LOGE("offset error");
810        ::close(fd);
811        return UNKNOWN_ERROR;
812    }
813    if (offset + length > sb.st_size) {
814        length = sb.st_size - offset;
815        LOGV("calculated length = %lld", length);
816    }
817
818    player_type playerType = getPlayerType(fd, offset, length);
819    LOGV("player type = %d", playerType);
820
821    // create the right type of player
822    sp<MediaPlayerBase> p = createPlayer(playerType);
823    if (p == NULL) return NO_INIT;
824
825    if (!p->hardwareOutput()) {
826        mAudioOutput = new AudioOutput();
827        static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
828    }
829
830    // now set data source
831    mStatus = p->setDataSource(fd, offset, length);
832    if (mStatus == NO_ERROR) mPlayer = p;
833    return mStatus;
834}
835
836status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface)
837{
838    LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
839    sp<MediaPlayerBase> p = getPlayer();
840    if (p == 0) return UNKNOWN_ERROR;
841    return p->setVideoSurface(surface);
842}
843
844status_t MediaPlayerService::Client::invoke(const Parcel& request,
845                                            Parcel *reply)
846{
847    sp<MediaPlayerBase> p = getPlayer();
848    if (p == NULL) return UNKNOWN_ERROR;
849    return p->invoke(request, reply);
850}
851
852// This call doesn't need to access the native player.
853status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
854{
855    status_t status;
856    media::Metadata::Filter allow, drop;
857
858    if (unmarshallFilter(filter, &allow, &status) &&
859        unmarshallFilter(filter, &drop, &status)) {
860        Mutex::Autolock lock(mLock);
861
862        mMetadataAllow = allow;
863        mMetadataDrop = drop;
864    }
865    return status;
866}
867
868status_t MediaPlayerService::Client::getMetadata(
869        bool update_only, bool apply_filter, Parcel *reply)
870{
871    sp<MediaPlayerBase> player = getPlayer();
872    if (player == 0) return UNKNOWN_ERROR;
873
874    status_t status;
875    // Placeholder for the return code, updated by the caller.
876    reply->writeInt32(-1);
877
878    media::Metadata::Filter ids;
879
880    // We don't block notifications while we fetch the data. We clear
881    // mMetadataUpdated first so we don't lose notifications happening
882    // during the rest of this call.
883    {
884        Mutex::Autolock lock(mLock);
885        if (update_only) {
886            ids = mMetadataUpdated;
887        }
888        mMetadataUpdated.clear();
889    }
890
891    media::Metadata metadata(reply);
892
893    metadata.appendHeader();
894    status = player->getMetadata(ids, reply);
895
896    if (status != OK) {
897        metadata.resetParcel();
898        LOGE("getMetadata failed %d", status);
899        return status;
900    }
901
902    // FIXME: Implement filtering on the result. Not critical since
903    // filtering takes place on the update notifications already. This
904    // would be when all the metadata are fetch and a filter is set.
905
906    // Everything is fine, update the metadata length.
907    metadata.updateLength();
908    return OK;
909}
910
911status_t MediaPlayerService::Client::prepareAsync()
912{
913    LOGV("[%d] prepareAsync", mConnId);
914    sp<MediaPlayerBase> p = getPlayer();
915    if (p == 0) return UNKNOWN_ERROR;
916    status_t ret = p->prepareAsync();
917#if CALLBACK_ANTAGONIZER
918    LOGD("start Antagonizer");
919    if (ret == NO_ERROR) mAntagonizer->start();
920#endif
921    return ret;
922}
923
924status_t MediaPlayerService::Client::start()
925{
926    LOGV("[%d] start", mConnId);
927    sp<MediaPlayerBase> p = getPlayer();
928    if (p == 0) return UNKNOWN_ERROR;
929    p->setLooping(mLoop);
930    return p->start();
931}
932
933status_t MediaPlayerService::Client::stop()
934{
935    LOGV("[%d] stop", mConnId);
936    sp<MediaPlayerBase> p = getPlayer();
937    if (p == 0) return UNKNOWN_ERROR;
938    return p->stop();
939}
940
941status_t MediaPlayerService::Client::pause()
942{
943    LOGV("[%d] pause", mConnId);
944    sp<MediaPlayerBase> p = getPlayer();
945    if (p == 0) return UNKNOWN_ERROR;
946    return p->pause();
947}
948
949status_t MediaPlayerService::Client::isPlaying(bool* state)
950{
951    *state = false;
952    sp<MediaPlayerBase> p = getPlayer();
953    if (p == 0) return UNKNOWN_ERROR;
954    *state = p->isPlaying();
955    LOGV("[%d] isPlaying: %d", mConnId, *state);
956    return NO_ERROR;
957}
958
959status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
960{
961    LOGV("getCurrentPosition");
962    sp<MediaPlayerBase> p = getPlayer();
963    if (p == 0) return UNKNOWN_ERROR;
964    status_t ret = p->getCurrentPosition(msec);
965    if (ret == NO_ERROR) {
966        LOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
967    } else {
968        LOGE("getCurrentPosition returned %d", ret);
969    }
970    return ret;
971}
972
973status_t MediaPlayerService::Client::getDuration(int *msec)
974{
975    LOGV("getDuration");
976    sp<MediaPlayerBase> p = getPlayer();
977    if (p == 0) return UNKNOWN_ERROR;
978    status_t ret = p->getDuration(msec);
979    if (ret == NO_ERROR) {
980        LOGV("[%d] getDuration = %d", mConnId, *msec);
981    } else {
982        LOGE("getDuration returned %d", ret);
983    }
984    return ret;
985}
986
987status_t MediaPlayerService::Client::seekTo(int msec)
988{
989    LOGV("[%d] seekTo(%d)", mConnId, msec);
990    sp<MediaPlayerBase> p = getPlayer();
991    if (p == 0) return UNKNOWN_ERROR;
992    return p->seekTo(msec);
993}
994
995status_t MediaPlayerService::Client::reset()
996{
997    LOGV("[%d] reset", mConnId);
998    sp<MediaPlayerBase> p = getPlayer();
999    if (p == 0) return UNKNOWN_ERROR;
1000    return p->reset();
1001}
1002
1003status_t MediaPlayerService::Client::setAudioStreamType(int type)
1004{
1005    LOGV("[%d] setAudioStreamType(%d)", mConnId, type);
1006    // TODO: for hardware output, call player instead
1007    Mutex::Autolock l(mLock);
1008    if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
1009    return NO_ERROR;
1010}
1011
1012status_t MediaPlayerService::Client::setLooping(int loop)
1013{
1014    LOGV("[%d] setLooping(%d)", mConnId, loop);
1015    mLoop = loop;
1016    sp<MediaPlayerBase> p = getPlayer();
1017    if (p != 0) return p->setLooping(loop);
1018    return NO_ERROR;
1019}
1020
1021status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
1022{
1023    LOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
1024    // TODO: for hardware output, call player instead
1025    Mutex::Autolock l(mLock);
1026    if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
1027    return NO_ERROR;
1028}
1029
1030
1031void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
1032{
1033    Client* client = static_cast<Client*>(cookie);
1034
1035    if (MEDIA_INFO == msg &&
1036        MEDIA_INFO_METADATA_UPDATE == ext1) {
1037        const media::Metadata::Type metadata_type = ext2;
1038
1039        if(client->shouldDropMetadata(metadata_type)) {
1040            return;
1041        }
1042
1043        // Update the list of metadata that have changed. getMetadata
1044        // also access mMetadataUpdated and clears it.
1045        client->addNewMetadataUpdate(metadata_type);
1046    }
1047    LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
1048    client->mClient->notify(msg, ext1, ext2);
1049}
1050
1051
1052bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
1053{
1054    Mutex::Autolock lock(mLock);
1055
1056    if (findMetadata(mMetadataDrop, code)) {
1057        return true;
1058    }
1059
1060    if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
1061        return false;
1062    } else {
1063        return true;
1064    }
1065}
1066
1067
1068void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
1069    Mutex::Autolock lock(mLock);
1070    if (mMetadataUpdated.indexOf(metadata_type) < 0) {
1071        mMetadataUpdated.add(metadata_type);
1072    }
1073}
1074
1075#if CALLBACK_ANTAGONIZER
1076const int Antagonizer::interval = 10000; // 10 msecs
1077
1078Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
1079    mExit(false), mActive(false), mClient(client), mCb(cb)
1080{
1081    createThread(callbackThread, this);
1082}
1083
1084void Antagonizer::kill()
1085{
1086    Mutex::Autolock _l(mLock);
1087    mActive = false;
1088    mExit = true;
1089    mCondition.wait(mLock);
1090}
1091
1092int Antagonizer::callbackThread(void* user)
1093{
1094    LOGD("Antagonizer started");
1095    Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
1096    while (!p->mExit) {
1097        if (p->mActive) {
1098            LOGV("send event");
1099            p->mCb(p->mClient, 0, 0, 0);
1100        }
1101        usleep(interval);
1102    }
1103    Mutex::Autolock _l(p->mLock);
1104    p->mCondition.signal();
1105    LOGD("Antagonizer stopped");
1106    return 0;
1107}
1108#endif
1109
1110static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
1111
1112sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
1113{
1114    LOGV("decode(%s)", url);
1115    sp<MemoryBase> mem;
1116    sp<MediaPlayerBase> player;
1117
1118    // Protect our precious, precious DRMd ringtones by only allowing
1119    // decoding of http, but not filesystem paths or content Uris.
1120    // If the application wants to decode those, it should open a
1121    // filedescriptor for them and use that.
1122    if (url != NULL && strncmp(url, "http://", 7) != 0) {
1123        LOGD("Can't decode %s by path, use filedescriptor instead", url);
1124        return mem;
1125    }
1126
1127    player_type playerType = getPlayerType(url);
1128    LOGV("player type = %d", playerType);
1129
1130    // create the right type of player
1131    sp<AudioCache> cache = new AudioCache(url);
1132    player = android::createPlayer(playerType, cache.get(), cache->notify);
1133    if (player == NULL) goto Exit;
1134    if (player->hardwareOutput()) goto Exit;
1135
1136    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
1137
1138    // set data source
1139    if (player->setDataSource(url) != NO_ERROR) goto Exit;
1140
1141    LOGV("prepare");
1142    player->prepareAsync();
1143
1144    LOGV("wait for prepare");
1145    if (cache->wait() != NO_ERROR) goto Exit;
1146
1147    LOGV("start");
1148    player->start();
1149
1150    LOGV("wait for playback complete");
1151    if (cache->wait() != NO_ERROR) goto Exit;
1152
1153    mem = new MemoryBase(cache->getHeap(), 0, cache->size());
1154    *pSampleRate = cache->sampleRate();
1155    *pNumChannels = cache->channelCount();
1156    *pFormat = cache->format();
1157    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
1158
1159Exit:
1160    if (player != 0) player->reset();
1161    return mem;
1162}
1163
1164sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
1165{
1166    LOGV("decode(%d, %lld, %lld)", fd, offset, length);
1167    sp<MemoryBase> mem;
1168    sp<MediaPlayerBase> player;
1169
1170    player_type playerType = getPlayerType(fd, offset, length);
1171    LOGV("player type = %d", playerType);
1172
1173    // create the right type of player
1174    sp<AudioCache> cache = new AudioCache("decode_fd");
1175    player = android::createPlayer(playerType, cache.get(), cache->notify);
1176    if (player == NULL) goto Exit;
1177    if (player->hardwareOutput()) goto Exit;
1178
1179    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
1180
1181    // set data source
1182    if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
1183
1184    LOGV("prepare");
1185    player->prepareAsync();
1186
1187    LOGV("wait for prepare");
1188    if (cache->wait() != NO_ERROR) goto Exit;
1189
1190    LOGV("start");
1191    player->start();
1192
1193    LOGV("wait for playback complete");
1194    if (cache->wait() != NO_ERROR) goto Exit;
1195
1196    mem = new MemoryBase(cache->getHeap(), 0, cache->size());
1197    *pSampleRate = cache->sampleRate();
1198    *pNumChannels = cache->channelCount();
1199    *pFormat = cache->format();
1200    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
1201
1202Exit:
1203    if (player != 0) player->reset();
1204    ::close(fd);
1205    return mem;
1206}
1207
1208#undef LOG_TAG
1209#define LOG_TAG "AudioSink"
1210MediaPlayerService::AudioOutput::AudioOutput()
1211    : mCallback(NULL),
1212      mCallbackCookie(NULL) {
1213    mTrack = 0;
1214    mStreamType = AudioSystem::MUSIC;
1215    mLeftVolume = 1.0;
1216    mRightVolume = 1.0;
1217    mLatency = 0;
1218    mMsecsPerFrame = 0;
1219    setMinBufferCount();
1220}
1221
1222MediaPlayerService::AudioOutput::~AudioOutput()
1223{
1224    close();
1225}
1226
1227void MediaPlayerService::AudioOutput::setMinBufferCount()
1228{
1229    char value[PROPERTY_VALUE_MAX];
1230    if (property_get("ro.kernel.qemu", value, 0)) {
1231        mIsOnEmulator = true;
1232        mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
1233    }
1234}
1235
1236bool MediaPlayerService::AudioOutput::isOnEmulator()
1237{
1238    setMinBufferCount();
1239    return mIsOnEmulator;
1240}
1241
1242int MediaPlayerService::AudioOutput::getMinBufferCount()
1243{
1244    setMinBufferCount();
1245    return mMinBufferCount;
1246}
1247
1248ssize_t MediaPlayerService::AudioOutput::bufferSize() const
1249{
1250    if (mTrack == 0) return NO_INIT;
1251    return mTrack->frameCount() * frameSize();
1252}
1253
1254ssize_t MediaPlayerService::AudioOutput::frameCount() const
1255{
1256    if (mTrack == 0) return NO_INIT;
1257    return mTrack->frameCount();
1258}
1259
1260ssize_t MediaPlayerService::AudioOutput::channelCount() const
1261{
1262    if (mTrack == 0) return NO_INIT;
1263    return mTrack->channelCount();
1264}
1265
1266ssize_t MediaPlayerService::AudioOutput::frameSize() const
1267{
1268    if (mTrack == 0) return NO_INIT;
1269    return mTrack->frameSize();
1270}
1271
1272uint32_t MediaPlayerService::AudioOutput::latency () const
1273{
1274    return mLatency;
1275}
1276
1277float MediaPlayerService::AudioOutput::msecsPerFrame() const
1278{
1279    return mMsecsPerFrame;
1280}
1281
1282status_t MediaPlayerService::AudioOutput::open(
1283        uint32_t sampleRate, int channelCount, int format, int bufferCount,
1284        AudioCallback cb, void *cookie)
1285{
1286    mCallback = cb;
1287    mCallbackCookie = cookie;
1288
1289    // Check argument "bufferCount" against the mininum buffer count
1290    if (bufferCount < mMinBufferCount) {
1291        LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
1292        bufferCount = mMinBufferCount;
1293
1294    }
1295    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
1296    if (mTrack) close();
1297    int afSampleRate;
1298    int afFrameCount;
1299    int frameCount;
1300
1301    if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
1302        return NO_INIT;
1303    }
1304    if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
1305        return NO_INIT;
1306    }
1307
1308    frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
1309
1310    AudioTrack *t;
1311    if (mCallback != NULL) {
1312        t = new AudioTrack(
1313                mStreamType, sampleRate, format, channelCount, frameCount,
1314                0 /* flags */, CallbackWrapper, this);
1315    } else {
1316        t = new AudioTrack(
1317                mStreamType, sampleRate, format, channelCount, frameCount);
1318    }
1319
1320    if ((t == 0) || (t->initCheck() != NO_ERROR)) {
1321        LOGE("Unable to create audio track");
1322        delete t;
1323        return NO_INIT;
1324    }
1325
1326    LOGV("setVolume");
1327    t->setVolume(mLeftVolume, mRightVolume);
1328    mMsecsPerFrame = 1.e3 / (float) sampleRate;
1329    mLatency = t->latency() + kAudioVideoDelayMs;
1330    mTrack = t;
1331    return NO_ERROR;
1332}
1333
1334void MediaPlayerService::AudioOutput::start()
1335{
1336    LOGV("start");
1337    if (mTrack) {
1338        mTrack->setVolume(mLeftVolume, mRightVolume);
1339        mTrack->start();
1340    }
1341}
1342
1343ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
1344{
1345    LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
1346
1347    //LOGV("write(%p, %u)", buffer, size);
1348    if (mTrack) return mTrack->write(buffer, size);
1349    return NO_INIT;
1350}
1351
1352void MediaPlayerService::AudioOutput::stop()
1353{
1354    LOGV("stop");
1355    if (mTrack) mTrack->stop();
1356}
1357
1358void MediaPlayerService::AudioOutput::flush()
1359{
1360    LOGV("flush");
1361    if (mTrack) mTrack->flush();
1362}
1363
1364void MediaPlayerService::AudioOutput::pause()
1365{
1366    LOGV("pause");
1367    if (mTrack) mTrack->pause();
1368}
1369
1370void MediaPlayerService::AudioOutput::close()
1371{
1372    LOGV("close");
1373    delete mTrack;
1374    mTrack = 0;
1375}
1376
1377void MediaPlayerService::AudioOutput::setVolume(float left, float right)
1378{
1379    LOGV("setVolume(%f, %f)", left, right);
1380    mLeftVolume = left;
1381    mRightVolume = right;
1382    if (mTrack) {
1383        mTrack->setVolume(left, right);
1384    }
1385}
1386
1387// static
1388void MediaPlayerService::AudioOutput::CallbackWrapper(
1389        int event, void *cookie, void *info) {
1390    if (event != AudioTrack::EVENT_MORE_DATA) {
1391        return;
1392    }
1393
1394    AudioOutput *me = (AudioOutput *)cookie;
1395    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
1396
1397    (*me->mCallback)(
1398            me, buffer->raw, buffer->size, me->mCallbackCookie);
1399}
1400
1401#undef LOG_TAG
1402#define LOG_TAG "AudioCache"
1403MediaPlayerService::AudioCache::AudioCache(const char* name) :
1404    mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
1405    mError(NO_ERROR), mCommandComplete(false)
1406{
1407    // create ashmem heap
1408    mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name);
1409}
1410
1411uint32_t MediaPlayerService::AudioCache::latency () const
1412{
1413    return 0;
1414}
1415
1416float MediaPlayerService::AudioCache::msecsPerFrame() const
1417{
1418    return mMsecsPerFrame;
1419}
1420
1421status_t MediaPlayerService::AudioCache::open(
1422        uint32_t sampleRate, int channelCount, int format, int bufferCount,
1423        AudioCallback cb, void *cookie)
1424{
1425    if (cb != NULL) {
1426        return UNKNOWN_ERROR;  // TODO: implement this.
1427    }
1428
1429    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
1430    if (mHeap->getHeapID() < 0) return NO_INIT;
1431    mSampleRate = sampleRate;
1432    mChannelCount = (uint16_t)channelCount;
1433    mFormat = (uint16_t)format;
1434    mMsecsPerFrame = 1.e3 / (float) sampleRate;
1435    return NO_ERROR;
1436}
1437
1438ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
1439{
1440    LOGV("write(%p, %u)", buffer, size);
1441    if ((buffer == 0) || (size == 0)) return size;
1442
1443    uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
1444    if (p == NULL) return NO_INIT;
1445    p += mSize;
1446    LOGV("memcpy(%p, %p, %u)", p, buffer, size);
1447    if (mSize + size > mHeap->getSize()) {
1448        LOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
1449        size = mHeap->getSize() - mSize;
1450    }
1451    memcpy(p, buffer, size);
1452    mSize += size;
1453    return size;
1454}
1455
1456// call with lock held
1457status_t MediaPlayerService::AudioCache::wait()
1458{
1459    Mutex::Autolock lock(mLock);
1460    if (!mCommandComplete) {
1461        mSignal.wait(mLock);
1462    }
1463    mCommandComplete = false;
1464
1465    if (mError == NO_ERROR) {
1466        LOGV("wait - success");
1467    } else {
1468        LOGV("wait - error");
1469    }
1470    return mError;
1471}
1472
1473void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2)
1474{
1475    LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
1476    AudioCache* p = static_cast<AudioCache*>(cookie);
1477
1478    // ignore buffering messages
1479    if (msg == MEDIA_BUFFERING_UPDATE) return;
1480
1481    // set error condition
1482    if (msg == MEDIA_ERROR) {
1483        LOGE("Error %d, %d occurred", ext1, ext2);
1484        p->mError = ext1;
1485    }
1486
1487    // wake up thread
1488    LOGV("wakeup thread");
1489    p->mCommandComplete = true;
1490    p->mSignal.signal();
1491}
1492
1493} // namespace android
1494