一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Android 開(kāi)發(fā)之漫漫長(zhǎng)途 IX——徹底掌握 Binder

 codingSmart 2021-10-22

作者:忘了12138
地址:http://www.cnblogs.com/wangle12138/p/8192638.html
聲明:本文是 忘了12138 原創(chuàng)投稿,轉(zhuǎn)發(fā)請(qǐng)聯(lián)系原作者授權(quán)

該文章是一個(gè)系列文章,是本人在Android開(kāi)發(fā)的漫漫長(zhǎng)途上的一點(diǎn)感想和記錄,往期如下:

Android開(kāi)發(fā)之漫漫長(zhǎng)途 Ⅷ——Android Binder(也許是最容易理解的)

Android 消息機(jī)制(Looper Handler MessageQueue Message)

Android開(kāi)發(fā)之漫漫長(zhǎng)途 番外篇——自定義View的各種姿勢(shì)1

Android開(kāi)發(fā)之漫漫長(zhǎng)途 Ⅵ——圖解Android事件分發(fā)機(jī)制(深入底層源碼)

Activity 顯示之 ViewRootImpl的PreMeasure、WindowLayout、EndMeasure 等方法

Android 開(kāi)發(fā)之漫漫長(zhǎng)途 Ⅳ——Activity 的顯示之 ViewRootImpl 初探

Android 開(kāi)發(fā)之漫漫長(zhǎng)途 Ⅲ—Activity 的顯示之 Window和View(2)

Android 開(kāi)發(fā)之漫漫長(zhǎng)途 Ⅱ——Activity的顯示之Window和View(1)

Android 開(kāi)發(fā)之漫漫長(zhǎng)途Ⅰ—Android 系統(tǒng)的創(chuàng)世之初以及 Activity 的生命周期


前言

上一次還不如不說(shuō)去面試了呢,估計(jì)是掛了,數(shù)據(jù)結(jié)構(gòu)與算法方面雖然面試前突擊了一波,但是時(shí)間太短,當(dāng)時(shí)學(xué)的也不好。另外Android的一些知識(shí)也不是很了解。不過(guò)這也加大了我寫(xiě)博客的動(dòng)力。許多知識(shí)總覺(jué)得自己掌握的還挺好,不過(guò)一問(wèn)到比較細(xì)節(jié)的方面就不太清楚了。所以寫(xiě)這整個(gè)博客的目的也是加深自己的知識(shí),培養(yǎng)自己的溝通能力,和大家一起學(xué)習(xí)吧。


好了,閑話少說(shuō),我們這一篇先解決上一篇中遺留的問(wèn)題,之后有時(shí)間的話,我把這次的面試經(jīng)歷單寫(xiě)一篇博客,和大家共勉。

本篇我們來(lái)看一下 ServiceManager。上一篇中沒(méi)怎么說(shuō)它,ServiceManager 作為 Android 系統(tǒng)服務(wù)的大管家。我們還是有必要來(lái)看一下它的。

ServiceManager概述

ServiceManager 是 Android 世界中所有重要系統(tǒng)服務(wù)的大管家。像前文提到的AMS(ActivityManagerService),還有許多以后可能分析到的PackageManagerService等等服務(wù)都需要像ServiceManager中注冊(cè)。那么為何需要一個(gè)ServiceManager呢,其重要作用何在呢?私認(rèn)為有以下幾點(diǎn):

  1. ServiceManager能集中管理系統(tǒng)內(nèi)的所有服務(wù),它能施加權(quán)限控制,并不是任何進(jìn)程都能注冊(cè)服務(wù)的。

  2. ServiceManager支持通過(guò)字符串名稱來(lái)查找對(duì)應(yīng)的Service。這個(gè)功能很像DNS。由于各種原因的影響,Server進(jìn)程可能生死無(wú)常。 如果讓每個(gè)Client都去檢測(cè),壓力實(shí)在太大了。 現(xiàn)在有了統(tǒng)一的管理機(jī)構(gòu),Client只需要查詢ServiceManager,就能把握動(dòng)向,得到最新信息。

ServiceManager

[SystemServer.java]

public void setSystemProcess() {
   try {
       //注冊(cè)服務(wù),第二個(gè)參數(shù)為this,這里假設(shè)SystemServer通過(guò)“socket”與SM交互
       ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
       ..........
   } catch (PackageManager.NameNotFoundException e) {
       ........
   }
}

我們 SystemServer 進(jìn)程中的 AMS 通過(guò) SM 的代理與SM進(jìn)程交互(讀者也可以把這個(gè)過(guò)程想象為你所能理解的進(jìn)程間通信方式,例如管道、Socket等),并把自己注冊(cè)在SM中。這個(gè)情況下,我們使用 ServiceManager 的代理與SM進(jìn)程交互,既然有代理,那么也得有對(duì)應(yīng)的服務(wù)端。那么根據(jù)我們之前博客的思路分析的話,就是如下的流程:

ServiceManager是如何啟動(dòng)的?

按照我們之前博客的思路,我們?cè)赟ystemServer端有了個(gè)ServiceManager的代理,那么Android系統(tǒng)中應(yīng)該提供類似AMS這樣的繼承或間接繼承自java層Binder然后重寫(xiě)onTransact方法以處理請(qǐng)求。但是并沒(méi)有,ServiceManager并沒(méi)有使用如AMS這樣復(fù)雜的Binder類結(jié)構(gòu)。而是直接與Binder驅(qū)動(dòng)設(shè)備打交道。所以我們上一篇說(shuō)了ServiceManager不一樣。我們來(lái)看具體看一下。

ServiceManager在init.rc配置文件中配置啟動(dòng),是一個(gè)以c/c++語(yǔ)言編寫(xiě)的程序。init進(jìn)程、SM進(jìn)程等關(guān)系如下圖


我們來(lái)看它的main方法。

int main(int argc, char **argv)
{
   struct binder_state *bs;
   //①應(yīng)該是打開(kāi)binder設(shè)備吧?
   bs = binder_open(128*1024);
   if (!bs) {
       ALOGE("failed to open binder driver\n");
       return -1;
   }
   //②成為manager
   if (binder_become_context_manager(bs)) {
       ALOGE("cannot become context manager (%s)\n", strerror(errno));
       return -1;
   }
  ......
   //③處理客戶端發(fā)過(guò)來(lái)的請(qǐng)求
   binder_loop(bs, svcmgr_handler);
   return 0;
}

①打開(kāi)Binder設(shè)備

[binder.c]

struct binder_state*binder_open(unsigned mapsize)
{
   struct binder_state*bs;
   bs=malloc(sizeof(*bs));
   ......
   //打開(kāi)Binder設(shè)備
   bs->fd=open("/dev/binder",O_RDWR);
   ......
   bs->mapsize=mapsize;
   //進(jìn)行內(nèi)存映射
   bs->mapped=mmap(NULL,mapsize,PROT_READ,MAP_PRIVATE,bs->
   fd,0);
}

這一步的目的是把內(nèi)核層的binder驅(qū)動(dòng)映射到用戶空間。我們知道進(jìn)程之間是獨(dú)立的,進(jìn)程呢運(yùn)行在用戶空間內(nèi),內(nèi)核層的Binder驅(qū)動(dòng)可以看成是一個(gè)文件(實(shí)際上它也是,Linux上都是文件)。這一步呢,可以看成把一個(gè)文件映射到用戶空間,我們的進(jìn)程呢通過(guò)這個(gè)文件進(jìn)行交互。

②成為manager

[Binder.c]

int binder_become_context_manager(struct binder_state*bs)
{
   //實(shí)現(xiàn)太簡(jiǎn)單了!這個(gè)有個(gè)0,什么鬼?
   return ioctl(bs->fd,BINDER_SET_CONTEXT_MGR,0);
}

③處理客戶端發(fā)過(guò)來(lái)的請(qǐng)求

[Binder.c]

void binder_loop(struct binder_state *bs, binder_handler func)
{
   int res;
   struct binder_write_read bwr;
   uint32_t readbuf[32];
   bwr.write_size = 0;
   bwr.write_consumed = 0;
   bwr.write_buffer = 0;
   readbuf[0] = BC_ENTER_LOOPER;
   binder_write(bs, readbuf, sizeof(uint32_t));
   for (;;) {//果然是循環(huán)
       bwr.read_size = sizeof(readbuf);
       bwr.read_consumed = 0;
       bwr.read_buffer = (uintptr_t) readbuf;
       res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
       if (res < 0) {
           ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
           break;
       }
       //接收到請(qǐng)求交給binder_parse,最終會(huì)調(diào)用func來(lái)處理這些請(qǐng)求
       res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
       if (res == 0) {
           ALOGE("binder_loop: unexpected reply?!\n");
           break;
       }
       if (res < 0) {
           ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
           break;
       }
   }
}

上面?zhèn)魅雈unc的是svcmgr_ handler函數(shù)指針,所以會(huì)在svcmgr_handler中進(jìn)行集中處理客戶端的請(qǐng)求。

[service_manager.c]

int svcmgr_handler(struct binder_state *bs,
                  struct binder_transaction_data *txn,
                  struct binder_io *msg,
                  struct binder_io *reply)

{
   struct svcinfo *si;
   uint16_t *s;
   size_t len;
   uint32_t handle;
   uint32_t strict_policy;
   int allow_isolated;
   if (txn->target.ptr != BINDER_SERVICE_MANAGER)
       return -1;
   if (txn->code == PING_TRANSACTION)
       return 0;
   strict_policy = bio_get_uint32(msg);
   s = bio_get_string16(msg, &len);
   if (s == NULL) {
       return -1;
   }
   if ((len != (sizeof(svcmgr_id) / 2)) ||
       memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
       fprintf(stderr,"invalid id %s\n", str8(s, len));
       return -1;
   }
   if (sehandle && selinux_status_updated() > 0) {
       struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
       if (tmp_sehandle) {
           selabel_close(sehandle);
           sehandle = tmp_sehandle;
       }
   }
   switch(txn->code) {
   case SVC_MGR_GET_SERVICE://得到某個(gè)service的信息,service用字符串表示。
   case SVC_MGR_CHECK_SERVICE:
       s = bio_get_string16(msg, &len);//s是字符串表示的service名稱。
       if (s == NULL) {
           return -1;
       }
       handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
       if (!handle)
           break;
       bio_put_ref(reply, handle);
       return 0;
   case SVC_MGR_ADD_SERVICE://對(duì)應(yīng)addService請(qǐng)求。
       s = bio_get_string16(msg, &len);
       if (s == NULL) {
           return -1;
       }
       handle = bio_get_ref(msg);
       allow_isolated = bio_get_uint32(msg) ? 1 : 0;
       if (do_add_service(bs, s, len, handle, txn->sender_euid,
           allow_isolated, txn->sender_pid))
           return -1;
       break;
   case SVC_MGR_LIST_SERVICES: {//得到當(dāng)前系統(tǒng)已經(jīng)注冊(cè)的所有service的名字。
       uint32_t n = bio_get_uint32(msg);
       if (!svc_can_list(txn->sender_pid)) {
           ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                   txn->sender_euid);
           return -1;
       }
       si = svclist;
       while ((n-- > 0) && si)
           si = si->next;
       if (si) {
           bio_put_string16(reply, si->name);
           return 0;
       }
       return -1;
   }
   default:
       ALOGE("unknown code %d\n", txn->code);
       return -1;
   }
   bio_put_uint32(reply, 0);
   return 0;
}

ServiceManager的代理是如何獲得的?

我們來(lái)回到最初的調(diào)用

[SystemServer.java]

public void setSystemProcess() {
   try {
       //注冊(cè)服務(wù),第二個(gè)參數(shù)為this,這里假設(shè)SystemServer通過(guò)“socket”與SM交互
       ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
       ..........
   } catch (PackageManager.NameNotFoundException e) {
       ........
   }
}

上面的請(qǐng)求最終是通過(guò)SM服務(wù)代理發(fā)送的,那這個(gè)代理是怎么來(lái)的呢?我們來(lái)看

[ServiceManager.java]

public static void addService(String name, IBinder service) {
   try {
       getIServiceManager().addService(name, service, false);
   } catch (RemoteException e) {
       Log.e(TAG, "error in addService", e);
   }
}
private static IServiceManager getIServiceManager() {
   if (sServiceManager != null) {
       return sServiceManager;
   }
   // 是這里,沒(méi)錯(cuò)了
   sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
   return sServiceManager;
}

我們先來(lái)看BinderInternal.getContextObject()

[BinderInternal.java]

//好吧,它還是個(gè)native函數(shù)
public static final native IBinder getContextObject();

跟進(jìn)[android_ util_Binder.cpp]

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
   sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
   return javaObjectForIBinder(env, b);
}

跟進(jìn)[ProcessState.cpp]

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
   return getStrongProxyForHandle(0);
}
/*這個(gè)函數(shù)是不是我們之前見(jiàn)過(guò)*/
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
   sp<IBinder> result;
   AutoMutex _l(mLock);
   handle_entry* e = lookupHandleLocked(handle);
   if (e != NULL) {
       IBinder* b = e->binder;
       if (b == NULL || !e->refs->attemptIncWeak(this)) {
           if (handle == 0) {//這里我們的handle為0
               Parcel data;
           //在handle對(duì)應(yīng)的BpBinder第一次創(chuàng)建時(shí)
           //會(huì)執(zhí)行一次虛擬的事務(wù)請(qǐng)求,以確保ServiceManager已經(jīng)注冊(cè)
               status_t status = IPCThreadState::self()->transact(
                       0, IBinder::PING_TRANSACTION, data, NULL, 0);
               if (status == DEAD_OBJECT)
                  return NULL;//如果ServiceManager沒(méi)有注冊(cè),直接返回
           }
           //這里還是以handle參數(shù)創(chuàng)建了BpBinder
           b = new BpBinder(handle);
           e->binder = b;
           if (b) e->refs = b->getWeakRefs();
           result = b;
       } else {
           result.force_set(b);
           e->refs->decWeak(this);
       }
   }
   return result;
}

我們?cè)僖徊讲椒祷?br>[android_ util_Binder.cpp]

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
   sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
   //這里的b = new BpBinder(0);
   return javaObjectForIBinder(env, b);
}
/*這個(gè)函數(shù)我們上一篇是不是也見(jiàn)過(guò)*/
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
   if (val == NULL) return NULL;
   //如果val是Binder對(duì)象,進(jìn)入下面分支,此時(shí)val是BpBinder
   if (val->checkSubclass(&gBinderOffsets)) {
       // One of our own!
       jobject object = static_cast<JavaBBinder*>(val.get())->object();
       LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
       return object;
   }
   .........
   //調(diào)用BpBinder的findObject函數(shù)
   //在Native層的BpBinder中有一個(gè)ObjectManager,它用來(lái)管理在Native BpBinder上創(chuàng)建的Java BinderProxy對(duì)象
   //findObject用于判斷gBinderProxyOffsets中,是否存儲(chǔ)了已經(jīng)被ObjectManager管理的Java BinderProxy對(duì)象
   jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
   if (object != NULL) {
       jobject res = jniGetReferent(env, object);
       ............
       //如果該Java BinderProxy已經(jīng)被管理,則刪除這個(gè)舊的BinderProxy
       android_atomic_dec(&gNumProxyRefs);
       val->detachObject(&gBinderProxyOffsets);
       env->DeleteGlobalRef(object);
   }
   //創(chuàng)建一個(gè)新的BinderProxy對(duì)象
   object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
   if (object != NULL) {
       env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
       val->incStrong((void*)javaObjectForIBinder);
       jobject refObject = env->NewGlobalRef(
               env->GetObjectField(object, gBinderProxyOffsets.mSelf));
       //新創(chuàng)建的BinderProxy對(duì)象注冊(cè)到BpBinder的ObjectManager中,同時(shí)注冊(cè)一個(gè)回收函數(shù)proxy_cleanup
       //當(dāng)BinderProxy對(duì)象detach時(shí),proxy_cleanup函數(shù)將被調(diào)用,以釋放一些資源
       val->attachObject(&gBinderProxyOffsets, refObject,
               jnienv_to_javavm(env), proxy_cleanup);
       // Also remember the death recipients registered on this proxy
       sp<DeathRecipientList> drl = new DeathRecipientList;
       drl->incStrong((void*)javaObjectForIBinder);
       //將死亡通知list和BinderProxy聯(lián)系起來(lái)
       env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
       // Note that a new object reference has been created.
       android_atomic_inc(&gNumProxyRefs);
       //垃圾回收相關(guān);利用gNumRefsCreated記錄創(chuàng)建出的BinderProxy數(shù)量
       //當(dāng)創(chuàng)建出的BinderProxy數(shù)量大于200時(shí),該函數(shù)將利用BinderInternal的ForceGc函數(shù)進(jìn)行一個(gè)垃圾回收
       incRefsCreated(env);
       return object;
   }
}

接著返回到[ServiceManager.java]

private static IServiceManager getIServiceManager() {
   if (sServiceManager != null) {
       return sServiceManager;
   }
   // 是這里,沒(méi)錯(cuò)了BinderInternal.getContextObject()是BinderProxy對(duì)象
   sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
   return sServiceManager;
}

跟進(jìn)[[ServiceManagerNative.java]]

static public IServiceManager asInterface(IBinder obj)
{
   if (obj == null) {
       return null;
   }
   我們知道這里的obj指向的是BinderProxy對(duì)象
   IServiceManager in =
       (IServiceManager)obj.queryLocalInterface(descriptor);
   if (in != null) {
       return in;
   }
   return new ServiceManagerProxy(obj);
}

跟進(jìn)[Binder.java]

final class BinderProxy implements IBinder {
   public IInterface queryLocalInterface(String descriptor) {
       return null;
   }
}

跟進(jìn)[ServiceManagerNative.java]

class ServiceManagerProxy implements IServiceManager {
   public ServiceManagerProxy(IBinder remote) {
       //這里的mRemote指向了BinderProxy,與我們上一篇博客中講述的遙相呼應(yīng)
       mRemote = remote;
   }
}

本節(jié)小結(jié)

我們?cè)敱M講述了SM進(jìn)程的啟動(dòng)以及它作為服務(wù)大管家的意義。結(jié)合上一篇的內(nèi)容我們總算是把Binder講述的比較清楚了。

Binder補(bǔ)充說(shuō)明

AIDL

經(jīng)過(guò)上面的介紹,你應(yīng)該明白Java層Binder的架構(gòu)中,Bp端可以通過(guò)BinderProxy的transact()方法與Bn端發(fā)送請(qǐng)求,而B(niǎo)n端通過(guò)集成Binder重寫(xiě)onTransact()接收并處理來(lái)自Bp端的請(qǐng)求。這個(gè)結(jié)構(gòu)非常清晰簡(jiǎn)單,在Android6.0,我們可以處處看到這樣的設(shè)計(jì),比如我們的ActivityManagerNavtive這個(gè)類,涉及到Binder通信的基本上都是這種設(shè)計(jì)。不過(guò)如果我們想要自己來(lái)定義一些遠(yuǎn)程服務(wù)。那這樣的寫(xiě)法就比較繁瑣,還好Android提供了AIDL,并且在Android8.0之后,我們可以看到與ActivityManagerNavtive相似的許多類已經(jīng)被標(biāo)注過(guò)時(shí),因?yàn)锳ndroid系統(tǒng)也使用AIDL了。

AIDL的簡(jiǎn)單例子

AIDL的語(yǔ)法與定義一個(gè)java接口非常類似。下面我就定以一個(gè)非常簡(jiǎn)單的aidl

IMyAidlInterface.aidl

interface IMyAidlInterface {
   int getTest();
}

然后基本上就行了,我們重新build之后會(huì)得到一個(gè)
IMyAidlInterface.java文件,這個(gè)文件由aidl工具生成,我們現(xiàn)在使用的基本是AndroidStudio,即使你使用的是Eclipse也沒(méi)關(guān)系,這個(gè)文件會(huì)自動(dòng)生成,不需要你操心。但是我們還是得來(lái)看看我們生成的這個(gè)文件

public interface IMyAidlInterface extends android.os.IInterface {
   //抽象的Stub類,繼承自Binder并實(shí)現(xiàn)我們定義的IMyAidlInterface接口
   //繼承自Binder,重寫(xiě)onTransact方法,是不是感覺(jué)跟我們的XXXNative很像
   public static abstract class Stub extends android.os.Binder implements com.mafeibiao.testapplication.IMyAidlInterface {
       private static final java.lang.String DESCRIPTOR = "com.mafeibiao.testapplication.IMyAidlInterface";
       /**
        * Construct the stub at attach it to the interface.
        */

       public Stub() {
           this.attachInterface(this, DESCRIPTOR);
       }
       /**
        * Cast an IBinder object into an com.mafeibiao.testapplication.IMyAidlInterface interface,
        * generating a proxy if needed.
        */

       public static com.mafeibiao.testapplication.IMyAidlInterface asInterface(android.os.IBinder obj) {
           if ((obj == null)) {
               return null;
           }
           android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
           if (((iin != null) && (iin instanceof com.mafeibiao.testapplication.IMyAidlInterface))) {
               return ((com.mafeibiao.testapplication.IMyAidlInterface) iin);
           }
           return new com.mafeibiao.testapplication.IMyAidlInterface.Stub.Proxy(obj);
       }
       @Override
       public android.os.IBinder asBinder() {
           return this;
       }
       @Override
       public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
           switch (code) {
               case INTERFACE_TRANSACTION: {
                   reply.writeString(DESCRIPTOR);
                   return true;
               }
               case TRANSACTION_getTest: {
                   data.enforceInterface(DESCRIPTOR);
                   int _result = this.getTest();
                   reply.writeNoException();
                   reply.writeInt(_result);
                   return true;
               }
           }
           return super.onTransact(code, data, reply, flags);
       }
       /*這個(gè)Proxy不用說(shuō)肯定是代理了,其內(nèi)部還有個(gè)mRemote對(duì)象*/
       private static class Proxy implements com.mafeibiao.testapplication.IMyAidlInterface {
           private android.os.IBinder mRemote;
           Proxy(android.os.IBinder remote) {
               mRemote = remote;
           }
           @Override
           public android.os.IBinder asBinder() {
               return mRemote;
           }
           public java.lang.String getInterfaceDescriptor() {
               return DESCRIPTOR;
           }
           @Override
           public int getTest() throws android.os.RemoteException {
               android.os.Parcel _data = android.os.Parcel.obtain();
               android.os.Parcel _reply = android.os.Parcel.obtain();
               int _result;
               try {
                   _data.writeInterfaceToken(DESCRIPTOR);
                   mRemote.transact(Stub.TRANSACTION_getTest, _data, _reply, 0);
                   _reply.readException();
                   _result = _reply.readInt();
               } finally {
                   _reply.recycle();
                   _data.recycle();
               }
               return _result;
           }
       }
       static final int TRANSACTION_getTest = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
   }
   public int getTest() throws android.os.RemoteException;
}

可見(jiàn),AIDL的本質(zhì)與XXXNative之類的類并沒(méi)有什么本質(zhì)的不同,不過(guò)他的出現(xiàn)使得構(gòu)建一個(gè)Binder服務(wù)的工作大大簡(jiǎn)化了。

AIDL的使用詳解

上面用一個(gè)非常簡(jiǎn)單的小例子來(lái)解密AIDL的本質(zhì),但是在實(shí)際使用AIDL的時(shí)候還有許多地方需要注意。

AIDL支持的數(shù)據(jù)類型

  • 基本數(shù)據(jù)類型(int,long,charmboolean,double等)

  • String和CharSequence

  • List:只支持ArrrayList,并且里面每個(gè)元素的類型必須是AIDL支持的

  • Map:只支持HashMap,t,并且里面每個(gè)元素的類型必須是AIDL支持的

  • Parcelable:所有實(shí)現(xiàn)Parcelable接口的對(duì)象

  • AIDL:所有的AIDL接口本身也可以在AIDL文件中使用

以上6種數(shù)據(jù)類型就是AIDL所支持的所有類型,其中自定義的Parcel對(duì)象和AIDL對(duì)象必須要顯示import進(jìn)來(lái),不管他們是否和當(dāng)前的AIDL文件位于同一個(gè)包內(nèi)。

另外一個(gè)需要注意的地方是如果我們?cè)贏IDL中使用了自定義的Parcelable接口的對(duì)象,那么我們必須新建一個(gè)和它同名的AIDL文件,并在其中聲明它為Parcelable類型。
如下例

[IBookManager.aidl]

package com.ryg.chapter_2.aidl;
/*這里顯示import*/
import com.ryg.chapter_2.aidl.Book;
interface IBookManager {
    //這里我們使用了自定義的Parcelable對(duì)象
    List<Book> getBookList();
    void addBook(in Book book);
}

這里我們新建一個(gè)與Book同名的AIDL文件并聲明

[Book.aidl]

package com.ryg.chapter_2.aidl;
parcelable Book;

定向tag

定向tag:這是一個(gè)極易被忽略的點(diǎn)——這里的“被忽略”指的不是大家都不知道,而是很少人會(huì)正確的使用它。

AIDL中的定向 tag 表示了在跨進(jìn)程通信中數(shù)據(jù)的流向,其中 in 表示數(shù)據(jù)只能由客戶端流向服務(wù)端, out 表示數(shù)據(jù)只能由服務(wù)端流向客戶端,而 inout 則表示數(shù)據(jù)可在服務(wù)端與客戶端之間雙向流通。其中,數(shù)據(jù)流向是針對(duì)在客戶端中的那個(gè)傳入方法的對(duì)象而言的。in 為定向 tag 的話表現(xiàn)為服務(wù)端將會(huì)接收到一個(gè)那個(gè)對(duì)象的完整數(shù)據(jù),但是客戶端的那個(gè)對(duì)象不會(huì)因?yàn)榉?wù)端對(duì)傳參的修改而發(fā)生變動(dòng);out 的話表現(xiàn)為服務(wù)端將會(huì)接收到那個(gè)對(duì)象的的空對(duì)象,但是在服務(wù)端對(duì)接收到的空對(duì)象有任何修改之后客戶端將會(huì)同步變動(dòng);inout 為定向 tag 的情況下,服務(wù)端將會(huì)接收到客戶端傳來(lái)對(duì)象的完整信息,并且客戶端將會(huì)同步服務(wù)端對(duì)該對(duì)象的任何變動(dòng)。

另外,Java 中的基本類型和 String ,CharSequence 的定向 tag 默認(rèn)且只能是 in 。還有,請(qǐng)注意,請(qǐng)不要濫用定向 tag ,而是要根據(jù)需要選取合適的——要是不管三七二十一,全都一上來(lái)就用 inout ,等工程大了系統(tǒng)的開(kāi)銷就會(huì)大很多——因?yàn)榕帕姓韰?shù)的開(kāi)銷是很昂貴的。

所有的非基本參數(shù)都需要一個(gè)定向tag來(lái)指出數(shù)據(jù)的流向,不管是 in , out , 還是 inout ?;緟?shù)的定向tag默認(rèn)是并且只能是 in 。

Binder傳輸數(shù)據(jù)的大小限制

雖然APP開(kāi)發(fā)時(shí)候,Binder對(duì)程序員幾乎不可見(jiàn),但是作為Android的數(shù)據(jù)運(yùn)輸系統(tǒng),Binder的影響是全面性的,所以有時(shí)候如果不了解Binder的一些限制,在出現(xiàn)問(wèn)題的時(shí)候往往是沒(méi)有任何頭緒,比如在Activity之間傳輸BitMap的時(shí)候,如果Bitmap過(guò)大,就會(huì)引起問(wèn)題,比如崩潰等,這其實(shí)就跟Binder傳輸數(shù)據(jù)大小的限制有關(guān)系。

普通的由Zygote孵化而來(lái)的用戶進(jìn)程,所映射的Binder內(nèi)存大小是不到1M的,準(zhǔn)確說(shuō)是 110241024) - (4096 *2) :這個(gè)限制定義在ProcessState類中,如果傳輸說(shuō)句超過(guò)這個(gè)大小,系統(tǒng)就會(huì)報(bào)錯(cuò),因?yàn)锽inder本身就是為了進(jìn)程間頻繁而靈活的通信所設(shè)計(jì)的,并不是為了拷貝大數(shù)據(jù)而使用的:

[ProcessState.cpp]

#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))

有個(gè)特殊的進(jìn)程ServiceManager進(jìn)程,它為自己申請(qǐng)的Binder內(nèi)核空間是128K,這個(gè)同ServiceManager的用途是分不開(kāi)的,ServcieManager主要面向系統(tǒng)Service,只是簡(jiǎn)單的提供一些addServcie,getService的功能,不涉及多大的數(shù)據(jù)傳輸,因此不需要申請(qǐng)多大的內(nèi)存:

int main(int argc, char **argv)
{
   struct binder_state *bs;
   void *svcmgr = BINDER_SERVICE_MANAGER;
   // 僅僅申請(qǐng)了128k
   bs = binder_open(128*1024);
   if (binder_become_context_manager(bs)) {
       ALOGE("cannot become context manager (%s)\n", strerror(errno));
       return -1;
   }
   svcmgr_handle = svcmgr;
   binder_loop(bs, svcmgr_handler);
   return 0;
}

Android APP進(jìn)程天生支持Binder通信的原理是什么

Android APP進(jìn)程都是由Zygote進(jìn)程孵化出來(lái)的。常見(jiàn)場(chǎng)景:點(diǎn)擊桌面icon啟動(dòng)APP,或者startActivity啟動(dòng)一個(gè)新進(jìn)程里面的Activity,最終都會(huì)由AMS去調(diào)用Process.start()方法去向Zygote進(jìn)程發(fā)送請(qǐng)求,讓Zygote去fork一個(gè)新進(jìn)程,Zygote收到請(qǐng)求后會(huì)調(diào)用Zygote.forkAndSpecialize()來(lái)fork出新進(jìn)程,之后會(huì)通過(guò)RuntimeInit.nativeZygoteInit來(lái)初始化Andriod APP運(yùn)行需要的一些環(huán)境,而binder線程就是在這個(gè)時(shí)候新建啟動(dòng)的,
[RuntimeInit.java]

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
       throws ZygoteInit.MethodAndArgsCaller
{
   //關(guān)鍵代碼
   nativeZygoteInit();
}

nativeZygoteInit屬于Native方法,該方法位于AndroidRuntime.cpp中,其實(shí)就是調(diào)用調(diào)用到app_main.cpp中的onZygoteInit
[app_main.cpp]

virtual void onZygoteInit()
{
   sp<ProcessState> proc = ProcessState::self();
   proc->startThreadPool();
}

首先,ProcessState::self()函數(shù)會(huì)調(diào)用open()打開(kāi)/dev/binder設(shè)備,這個(gè)時(shí)候Client就能通過(guò)Binder進(jìn)行遠(yuǎn)程通信;其次,proc->startThreadPool()負(fù)責(zé)新建一個(gè)binder線程,監(jiān)聽(tīng)Binder設(shè)備,這樣進(jìn)程就具備了作為Binder服務(wù)端的資格。每個(gè)APP的進(jìn)程都會(huì)通過(guò)onZygoteInit打開(kāi)Binder,既能作為Client,也能作為Server,這就是Android進(jìn)程天然支持Binder通信的原因。

Binder與線程的關(guān)系

從上面的知識(shí)我們知道我們的App進(jìn)程在啟動(dòng)的時(shí)候至少會(huì)有一個(gè)Binder線程來(lái)作為請(qǐng)求或者處理數(shù)據(jù)的實(shí)際執(zhí)行者。

我們的SystemServer進(jìn)程同樣是由Zygote通過(guò)fork得來(lái)的,SystemServer進(jìn)程也至少有一個(gè)線程來(lái)請(qǐng)求或者處理數(shù)據(jù)。

實(shí)際上在Android4.0上我們可以找到
[system_init.cpp]

extern "C" status_t system_init()
{
   //通過(guò) ProcessState::self()->startThreadPool()新加了一個(gè)Binder線程
   ProcessState::self()->startThreadPool();
   //通過(guò)IPCThreadState::self()->joinThreadPool();將當(dāng)前線程變成Binder線程,
   IPCThreadState::self()->joinThreadPool();
   return NO_ERROR;
}

但是我們?cè)贏ndroid5.0之后就看不到了

另外需要注意的是Binder線程的數(shù)目不是固定的,而且有默認(rèn)的最大數(shù)量(默認(rèn)是15),驅(qū)動(dòng)會(huì)根據(jù)目標(biāo)進(jìn)程中是否存在足夠多的Binder線程來(lái)告訴進(jìn)程是不是要新建Binder線程。

上一次有讀者問(wèn)我一個(gè),Binder傳輸時(shí)是運(yùn)行在單獨(dú)的線程么,還是主線程,還是說(shuō)分情況,比如:ActivityThread 向 AMS 通過(guò)Binder傳輸時(shí)在主線程,而AMS向ApplicationThread通過(guò)Binder傳輸時(shí)在單獨(dú)的一個(gè)線程中?

這個(gè)我只能說(shuō)具體問(wèn)題具體分析,并且這個(gè)還跟Android版本有關(guān)系。不過(guò)貌似沒(méi)有必要再這個(gè)問(wèn)題上糾結(jié)啊,在目標(biāo)進(jìn)程上至少存在一個(gè)Binder線程,這些線程的創(chuàng)建以及管理類似線程池線程復(fù)用的概念。


本篇總結(jié)

我們本篇詳細(xì)分析了 ServiceManager,ServiceManager 并沒(méi)有使用復(fù)雜的類結(jié)構(gòu),他直接與 Binder 驅(qū)動(dòng)設(shè)備交互達(dá)到IPC通信的目的。(欠下的債終于補(bǔ)上了)


下篇預(yù)告

下篇我們來(lái)講一下 Android 序列化相關(guān)知識(shí)。


此致,敬禮

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    欧美黑人在线一区二区| 国产在线视频好看不卡| 两性色午夜天堂免费视频| 国产丝袜女优一区二区三区| 日本熟妇五十一区二区三区| 欧美野外在线刺激在线观看| av在线免费观看一区二区三区| 精品人妻少妇二区三区| 精品国产亚洲av久一区二区三区 | 国产免费人成视频尤物| 99免费人成看国产片| 91亚洲国产日韩在线| 亚洲欧美日韩熟女第一页| 激情偷拍一区二区三区视频| 小草少妇视频免费看视频| 91免费精品国自产拍偷拍| 午夜精品黄片在线播放| 国产毛片对白精品看片| 日韩一级毛一欧美一级乱| 久久精品久久久精品久久| 好吊日成人免费视频公开| 亚洲一区二区三区在线免费| 东京热男人的天堂久久综合| 日韩精品你懂的在线观看| 欧美日韩国产欧美日韩| 91免费一区二区三区| 出差被公高潮久久中文字幕| 又色又爽又无遮挡的视频| 国产精品午夜福利免费阅读| 免费特黄一级一区二区三区| 偷拍偷窥女厕一区二区视频| 欧美一区二区三区性视频| 欧美高潮喷吹一区二区| 午夜国产福利在线播放| 欧美精品激情视频一区| 日韩欧美91在线视频| 亚洲国产成人久久99精品| 黄色三级日本在线观看| 亚洲精品一区三区三区| 不卡视频在线一区二区三区| 日本 一区二区 在线|