深入了解MediaServer-1

1.mediaserver位于main_mediaserver.cpp,其源码如下:

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();     //音频系统的mixer and resampler
    MediaPlayerService::instantiate();  //创建一个player,并进行AV播放
    CameraService::instantiate();     // 摄像和照相的服务
    AudioPolicyService::instantiate();  //音频策略的服务
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

此程序的进程名为:/system/bin/mediaserver

void AudioFlinger::instantiate() {
    defaultServiceManager()->addService(
            String16("media.audio_flinger"), new AudioFlinger());
}

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

void CameraService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.camera"), new CameraService());
}

void AudioPolicyService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.audio_policy"), new AudioPolicyService());
}

查看系统已经注册的media类Service,其结果如下:

# service list | busybox grep media
5 audio: [android.media.IAudioService]
63 media.audio_policy: [android.media.IAudioPolicyService]
64 media.camera: [android.hardware.ICameraService]
65 media.player: [android.media.IMediaPlayerService]
66 media.audio_flinger: [android.media.IAudioFlinger]

 

2. 独一无二的ProcessState

ProcessState是一个单实例,每个进程只有一个实例。ProcessState::self()功能为打开/dev/binder设备,设置线程池中最大线程数,通过mmap把Binder Driver为其分配的内在映射到用户空间,以便把发送方的数据从发送方的用户空间直接copy到接收方的mmap空间。

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // XXX Ideally, there should be a specific define for whether we
        // have mmap (or whether we could possibly have the kernel module
        // availabla).
#if !defined(HAVE_WIN32_IPC)
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }
    if (mDriverFD < 0) {
        // Need to run without the driver, starting our own thread pool.
    }
}

3. 神奇的 defaultServiceManager

defaultServiceManager在IServiceManager.cpp中实现,其功能是获得一个IServiceManager对象。通过这个对象,就可以与进程/system/bin/servicemanager进行通信。

(defaultServiceManager实际返回的是BpServiceManager,它的remote对象是BpBinder,传入的那个handle参数是0。)

sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        if (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
        }
    }
    
    return gDefaultServiceManager;
}

ProcessState::self()->getContextObject(NULL)->  getStrongProxyForHandle(0)-> new BpBinder(handle) // handle值为0, 0在binder系统中代表ServiceManger所对应的BBinder.

 

即:gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0))

它创建了两个关键对象:

1)BpBinder对象,其handle为0

2)BpServiceManager对象,其mRemote值为1)中创建的BpBinder对象。

BpServiceManager实现了IServiceManager中定义的业务逻辑,又有一个成员BpBinder作为其通信代理。

3.1 如何把BpBinder转换为IServiceManager呢?

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}
即:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
    return IServiceManager::asInterface(obj);
}


3.2 ServiceManager所提供的服务

//IServiceManager.h
class IServiceManager : public IInterface
{
public:
    DECLARE_META_INTERFACE(ServiceManager);

    /**
     * Retrieve an existing service, blocking for a few seconds
     * if it doesn't yet exist.
     */
    virtual sp<IBinder>         getService( const String16& name) const = 0;

    /**
     * Retrieve an existing service, non-blocking.
     */
    virtual sp<IBinder>         checkService( const String16& name) const = 0;

    /**
     * Register a service.
     */
    virtual status_t            addService( const String16& name,
                                            const sp<IBinder>& service) = 0;

    /**
     * Return list of all existing services.
     */
    virtual Vector<String16>    listServices() = 0;

    enum {
        GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
        CHECK_SERVICE_TRANSACTION,
        ADD_SERVICE_TRANSACTION,
        LIST_SERVICES_TRANSACTION,
    };
}

3.3 如何把业务与Binder通信连接起来

//IInterface.h
#define DECLARE_META_INTERFACE(INTERFACE)                               \
    static const String16 descriptor;                                   \
    static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj);        \
    virtual const String16& getInterfaceDescriptor() const;             \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \

替换后得到:

    static const String16 descriptor;                                  
    static sp<IServiceManager> asInterface(const sp<IBinder>& obj);   
    virtual const String16& getInterfaceDescriptor() const;             
    IServiceManager();                                                  
    virtual ~IServiceManager();   


asInterface是如何实现的?

// IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

//IInterface.h
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const String16 I##INTERFACE::descriptor(NAME);                      \
    const String16& I##INTERFACE::getInterfaceDescriptor() const {      \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj)  \
    {                                                                   \
        sp<I##INTERFACE> intr;                                          \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \


替换后为:

    const String16 IServiceManager::descriptor("android.os.IServiceManager");                      
    const String16& IServiceManagerE::getInterfaceDescriptor() const {      
        return IServiceManager::descriptor;                                
    }                                                                   
    sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)  
    {                                                                   
        sp<IServiceManager> intr;                                          
        if (obj != NULL) {                                              
            intr = static_cast<IServiceManager*>(                          
                obj->queryLocalInterface(                               
                        IServiceManager::descriptor).get());               
            if (intr == NULL) {                                         
                intr = new BpServiceManager(obj);                          
            }                                                           
        }                                                               
        return intr;                                                    
    }                                                                   
    IServiceManager::IServiceManager() { }                                    
    IServiceManager::~IServiceManager() { }          


如何把BpBinder转换为IServiceManager的答案为:intr = new BpServiceManager(obj);

其原理为:interface_cast并不是一个指针转换,而是把BpBinder做为一个参数,创建了一个新的BpServiceManager.

 

3.3.1 IServiceManager家族图谱

转自:http://book.51cto.com/art/201109/293428.htm

1)IServiceManager,BpServiceManager和BnServiceManager都与业务逻辑相关。

2)class BnServiceManager : public BnInterface<IServiceManager>
     BnServiceManager同时从IServiceManager和BBinder派生,表示它可以直接参与Binder通信。

3)class BpServiceManager : public BpInterface<IServiceManager>
     BpServiceManager同时从IServiceManager和BpRefBase派生。
     BpRefBase中有一个成员变量:IBinder* const   mRemote;

     注:以上关系较复杂,但ServiceManger并没有使用以上派生关系,而是直接打开Binder设备并与之交互。

4)BpRefBase的成员变量mRemote的值就是传进去的BpBinder,使用它就可以与BBinder进行通信了

5)intr = new BpServiceManager(obj);详细过程如下:

BpServiceManager(const sp<IBinder>& impl)
   : BpInterface<IServiceManager>(impl)
{
}
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}
BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(NULL), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

 o.get(),这个是sp类的获取实际数据指针的一个方法,它返回的是sp<xxxx>中xxx* 类型的指针。

 

3.4 ProcessState & IPCThreadState

      ProcessState负责打开BinderDriver,准备好与Binder Driver通信;而IPCThreadState负责通过Binder Driver而进行跨进程的实际数据的读写。例如,client进程的程序调用BpBinder的IBinder中的transact()函数,此transact()函数则调用IPCThreadState中的transact()函数调用Binder Driver的ioctl()函数进行数据的传输。

IPCThreadState::transact->IPCThreadState::waitForResponse-> IPCThreadState::talkWithDriver->ioctl

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}


 4. 注册一个Service

以MediaPlayerService为例分析注册过程。 

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}
MediaPlayerService::MediaPlayerService()
{
    LOGV("MediaPlayerService created");
    mNextConnId = 1;
    mRatio = -1;
    mCrvs = -1;
    mLeft = -1;
    mTop =-1;
    mWidth =-1;
    mHeight =-1;
}
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
    Parcel data, reply;
    data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
    data.writeString16(name);
    data.writeStrongBinder(service);
    status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
    return err == NO_ERROR ? reply.readInt32() : err;
}

remote()返回的就是BpServiceManager中保存的BpBinder。

MediaPlayerService 从BnMediaPlayerService派生,其家族关系如下:

class MediaPlayerService : public BnMediaPlayerService //业务逻辑和通信
class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
class BnInterface : public IMediaPlayerService, public BBinder
//IMediaPlayerService:负责业务逻辑
//BBinder:负责通信
class MediaPlayerService : public BnMediaPlayerService
{
    class Client;
    class MediaConfigClient;

    class AudioOutput : public MediaPlayerBase::AudioSink
    {
     ...
    };

    class AudioCache : public MediaPlayerBase::AudioSink
    {
     ...
    };

public:
    static  void                instantiate();

    // IMediaPlayerService interface
    virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid);
    void    removeMediaRecorderClient(wp<MediaRecorderClient> client);
    virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);

    // House keeping for media player clients
    virtual sp<IMediaPlayer>    create(
            pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
            const KeyedVector<String8, String8> *headers);

    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
    virtual sp<IMediaConfig>   createMediaConfig(pid_t pid);
    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
    virtual sp<IMemory>         snoop();
    virtual sp<IOMX>            getOMX();
private:

    class Client : public BnMediaPlayer {
        virtual status_t        prepareAsync();
        virtual status_t        start();
        virtual status_t        stop();
        virtual status_t        pause();
        virtual status_t        isPlaying(bool* state);
        virtual status_t        seekTo(int msec);
        virtual status_t        getCurrentPosition(int* msec);
        virtual status_t        getDuration(int* msec);
        virtual status_t        reset();
        virtual status_t        setAudioStreamType(int type);
        virtual status_t        setLooping(int loop);
        virtual status_t        setVolume(float leftVolume, float rightVolume);
        virtual status_t        invoke(const Parcel& request, Parcel *reply);
        virtual status_t        setMetadataFilter(const Parcel& filter);
        virtual status_t        getMetadata(bool update_only,
                                            bool apply_filter,
                                            Parcel *reply);

        sp<MediaPlayerBase>     createPlayer(player_type playerType);

                status_t        setDataSource(
                                const char *url,
                                const KeyedVector<String8, String8> *headers);

                status_t        setDataSource(int fd, int64_t offset, int64_t length);
        static  void            notify(void* cookie, int msg, int ext1, int ext2);

    private:
        friend class MediaPlayerService;
        sp<MediaPlayerBase>     getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; }
    };


    class MediaConfigClient: public BnMediaConfig
    {
       ...
    };

// ----------------------------------------------------------------------------

                            MediaPlayerService();
    virtual                 ~MediaPlayerService();

    mutable     Mutex                       mLock;
                SortedVector< wp<Client> >  mClients;
                SortedVector< wp<MediaRecorderClient> > mMediaRecorderClients;
                int32_t                     mNextConnId;
                sp<IOMX>                    mOMX;
    int32_t mRatio;
    int32_t mCrvs;
    int32_t mLeft;
    int32_t mTop;
    int32_t mWidth;
    int32_t mHeight;
}

 

4.1 addService

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

创建一个新的Service—BnMediaPlayerService,想把它告诉ServiceManager。然后调用BpServiceManger的addService来向ServiceManager中增加一个Service.其它进程可通过字符串"media.player"来向ServiceManger查询到此服务。

addService是调用的BpServiceManager的函数。

virtual status_t addService(const String16& name, const sp<IBinder>& service)

    {

        Parcel data, reply;

        //data是发送到BnServiceManager的命令包

        //看见没?先把Interface名字写进去,也就是什么android.os.IServiceManager

        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        //再把新service的名字写进去 叫media.player

        data.writeString16(name);

        //把新服务service—>就是MediaPlayerService写到命令中

        data.writeStrongBinder(service); //把MediaPlayerService写入flat_binder_object中

        //调用remote的transact函数

        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

        return err == NO_ERROR ? reply.readInt32() : err;

}

remote()返回的是前面创建的BpBinder(0).

status_t BpBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{
        //注意啊,这里的mHandle为0,code是ADD_SERVICE_TRANSACTION,data是命令包
         //reply是回复包,flags=0
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
           return status;
    }
...
}

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    status_t err = data.errorCheck();

    flags |= TF_ACCEPT_FDS;

    IF_LOG_TRANSACTIONS() {
        TextOutput::Bundle _b(alog);
        alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
            << handle << " / code " << TypeCode(code) << ": "
            << indent << data << dedent << endl;
    }
    
    if (err == NO_ERROR) {
        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);//把要发送的数据写入binder_transaction_data中
    }
    
    if (err != NO_ERROR) {
        if (reply) reply->setError(err);
        return (mLastError = err);
    }
    
    if ((flags & TF_ONE_WAY) == 0) {
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        
        IF_LOG_TRANSACTIONS() {
            TextOutput::Bundle _b(alog);
            alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
                << handle << ": ";
            if (reply) alog << indent << *reply << dedent << endl;
            else alog << "(none requested)" << endl;
        }
    } else {
        err = waitForResponse(NULL, NULL);
    }
    
    return err;
}

 

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;

    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    
    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = statusBuffer;
        tr.offsets_size = 0;
        tr.data.ptr.offsets = NULL;
    } else {
        return (mLastError = err);
    }
    
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));
    
    return NO_ERROR;
}

上面的代码把数据封装成binder_transaction_data,然后写到mOut中。mOut是一个命令buffer,也是一个Parcel.

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    int32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break; //发送数据到ServiceManager
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;
        
        cmd = mIn.readInt32();
        
        IF_LOG_COMMANDS() {
            alog << "Processing waitForResponse Command: "
                << getReturnString(cmd) << endl;
        }

        switch (cmd) {
        case BR_TRANSACTION_COMPLETE:
            if (!reply && !acquireResult) goto finish;
            break;
        
        case BR_DEAD_REPLY:
            err = DEAD_OBJECT;
            goto finish;

        case BR_FAILED_REPLY:
            err = FAILED_TRANSACTION;
            goto finish;
        
        case BR_ACQUIRE_RESULT:
            {
                LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
                const int32_t result = mIn.readInt32();
                if (!acquireResult) continue;
                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
            }
            goto finish;
        
        case BR_REPLY:
            {
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr));
                LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
                if (err != NO_ERROR) goto finish;

                if (reply) {
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        reply->ipcSetDataReference(
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(size_t),
                            freeBuffer, this);
                    } else {
                        err = *static_cast<const status_t*>(tr.data.ptr.buffer);
                        freeBuffer(NULL,
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(size_t), this);
                    }
                } else {
                    freeBuffer(NULL,
                        reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                        tr.data_size,
                        reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                        tr.offsets_size/sizeof(size_t), this);
                    continue;
                }
            }
            goto finish;

        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

finish:
    if (err != NO_ERROR) {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
    }
    
    return err;
}

 

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
    
    binder_write_read bwr;
    
    // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    
    // We don't want to write anything if we are still reading
    // from data left in the input buffer and the caller
    // has requested to read the next data.
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
    
    bwr.write_size = outAvail;
    bwr.write_buffer = (long unsigned int)mOut.data();

    // This is what we'll read.
    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (long unsigned int)mIn.data();
    } else {
        bwr.read_size = 0;
    }
    
    IF_LOG_COMMANDS() {
        TextOutput::Bundle _b(alog);
        if (outAvail != 0) {
            alog << "Sending commands to driver: " << indent;
            const void* cmds = (const void*)bwr.write_buffer;
            const void* end = ((const uint8_t*)cmds)+bwr.write_size;
            alog << HexDump(cmds, bwr.write_size) << endl;
            while (cmds < end) cmds = printCommand(alog, cmds);
            alog << dedent;
        }
        alog << "Size of receive buffer: " << bwr.read_size
            << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
    }
    
    // Return immediately if there is nothing to do.
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
    
    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do { //中间东西太复杂了,就是把mOut发送数据和mIn接收数据的处理后赋值给bwr
        IF_LOG_COMMANDS() {
            alog << "About to read/write, write size = " << mOut.dataSize() << endl;
        }
#if defined(HAVE_ANDROID_OS)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
        IF_LOG_COMMANDS() {
            alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
        }
    } while (err == -EINTR);
    //到这里,回复数据就在bwr中了,bwr接收回复数据的buffer就是mIn提供的

IF_LOG_COMMANDS() { alog << "Our err: " << (void*)err << ", write consumed: " << bwr.write_consumed << " (of " << mOut.dataSize() << "), read consumed: " << bwr.read_consumed << endl; } if (err >= NO_ERROR) { if (bwr.write_consumed > 0) { if (bwr.write_consumed < (ssize_t)mOut.dataSize()) mOut.remove(0, bwr.write_consumed); else mOut.setDataSize(0); } if (bwr.read_consumed > 0) { mIn.setDataSize(bwr.read_consumed); mIn.setDataPosition(0); } IF_LOG_COMMANDS() { TextOutput::Bundle _b(alog); alog << "Remaining data size: " << mOut.dataSize() << endl; alog << "Received commands from driver: " << indent; const void* cmds = mIn.data(); const void* end = mIn.data() + mIn.dataSize(); alog << HexDump(cmds, mIn.dataSize()) << endl; while (cmds < end) cmds = printReturnCommand(alog, cmds); alog << dedent; } return NO_ERROR; } return err; }

       至此发送addService到ServiceManager就已经结束了。BpServiceManager发送了一个addService命令到BnServiceManager,然后收到回复。

 

       问题:MediaPlayerService是一个BnMediaPlayerService,那么它是不是应该等着

BpMediaPlayerService来和他交互呢?但是我们没看见MediaPlayerService有打开binder设备的操作啊!

 

发布了349 篇原创文章 · 获赞 1083 · 访问量 501万+
展开阅读全文

安卓录像问题。报错Media server died.

09-28

public class MainActivity extends Activity { MediaRecorder recorder= null; Button startButton = null; Button endtButton = null; SurfaceView face = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startButton=(Button) findViewById(R.id.end); endtButton= (Button) findViewById(R.id.start); face= (SurfaceView) findViewById(R.id.surfaceView); face.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); face.getHolder().setFixedSize(176, 144); face.getHolder().setKeepScreenOn(true); startButton.setOnClickListener(ButtonClickDo); endtButton.setOnClickListener(ButtonClickDo); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void startRecord() throws Throwable, IOException{ File f = new File( Environment.getExternalStorageDirectory() ,System.currentTimeMillis()+".3gp"); recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setVideoSize(320, 240); recorder.setVideoFrameRate(5); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB); recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); recorder.setOutputFile(f.getAbsolutePath()); recorder.setPreviewDisplay(face.getHolder().getSurface()); System.out.println("路径"+ f.getAbsolutePath()); recorder.prepare(); recorder.start(); } public void stopRecord(){ if(recorder!=null){ recorder.stop(); recorder.release(); recorder=null; } } private OnClickListener ButtonClickDo = new OnClickListener() { @Override public void onClick(View v) { Integer id = v.getId(); System.out.println("id为:"+ id +"结果" +(endtButton.getId()==id)); if(endtButton.getId()==id){ try { startRecord(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } } else{ stopRecord(); } } }; } 这段代码可以正常的录像, 发到手机内存里 。但是我把 recorder.setPreviewDisplay(face.getHolder().getSurface()); 这句话给注释掉就报 Media server died. 。拍出来的东西只有23KB 怎么拍都只有23KB 不能播放 说文件损坏, 请问是怎么回事。 我想达到 录像 但不显示录像的画面。 怎么操作 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览