Bundler機(jī)制

Bundler在app中是以AIDL的方式表現(xiàn)的铐殃。
AIDL實(shí)現(xiàn)類中海洼,有2個(gè)重要的三要素,DESCRIPTOR(描述)富腊、Stub(存根)坏逢、Proxy(代理)。
Stub是服務(wù)端赘被,Proxy是客戶端是整。
客戶端在拿到服務(wù)端傳過(guò)來(lái)的IBunder引用,會(huì)調(diào)用asInterface民假,這里會(huì)根據(jù)當(dāng)前的描述是否相同浮入,如果相同說(shuō)明是同一個(gè)進(jìn)程。
原因在于在new的時(shí)候綁定了描述阳欲。

//AIDL中
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
//bundler中
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
}

客戶端通過(guò)Proxy拿到mRemote引用調(diào)用mRemote.transact()服務(wù)端的方法舵盈。
服務(wù)端通過(guò)transact()回調(diào)AIDL在service的實(shí)現(xiàn)方法陋率。

怎么拿到引用呢球化?

bindService(new Intent(xx,xxx), new ServiceConnection() {
 @Override
public void onServiceConnected(ComponentName name, IBinder service) {
//這里的service就是遠(yuǎn)程的引用
  IMyAidlInterface test = IMyAidlInterface.Stub.asInterface(service);
}
@Override
  public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);

主要是通過(guò)ActivityManagerService來(lái)拿到引用的。
通過(guò)2次進(jìn)程間通信瓦糟。第一次是調(diào)用ASM的bindService第二次是
在服務(wù)端AcitivityThread類中handlerService方法中調(diào)用ASM的publishService中回調(diào)ServiceConnection的方法拿到引用筒愚。

private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (DEBUG_SERVICE)
            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to bind to service " + s
                            + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }

畫圖表示一下過(guò)程

bindService流程圖

這是ASM調(diào)用ActiveServices管理類來(lái)實(shí)現(xiàn)服務(wù)的注冊(cè)管理的。


    int bindServiceLocked(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
        if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
                + " type=" + resolvedType + " conn=" + connection.asBinder()
                + " flags=0x" + Integer.toHexString(flags));
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        if (callerApp == null) {
            throw new SecurityException(
                    "Unable to find app for caller " + caller
                    + " (pid=" + Binder.getCallingPid()
                    + ") when binding service " + service);
        }

        ActivityRecord activity = null;
        if (token != null) {
            activity = ActivityRecord.isInStackLocked(token);
            if (activity == null) {
                Slog.w(TAG, "Binding with unknown activity: " + token);
                return 0;
            }
        }

        int clientLabel = 0;
        PendingIntent clientIntent = null;

        if (callerApp.info.uid == Process.SYSTEM_UID) {
            // Hacky kind of thing -- allow system stuff to tell us
            // what they are, so we can report this elsewhere for
            // others to know why certain services are running.
            try {
                clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
            } catch (RuntimeException e) {
            }
            if (clientIntent != null) {
                clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
                if (clientLabel != 0) {
                    // There are no useful extras in the intent, trash them.
                    // System code calling with this stuff just needs to know
                    // this will happen.
                    service = service.cloneFilter();
                }
            }
        }

        if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
            mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                    "BIND_TREAT_LIKE_ACTIVITY");
        }

        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;

        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
        if (res == null) {
            return 0;
        }
        if (res.record == null) {
            return -1;
        }
        ServiceRecord s = res.record;

        final long origId = Binder.clearCallingIdentity();

        try {
            if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
                        + s);
            }

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (!s.hasAutoCreateConnections()) {
                    // This is the first binding, let the tracker know.
                    ProcessStats.ServiceState stracker = s.getTracker();
                    if (stracker != null) {
                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                s.lastActivity);
                    }
                }
            }

            mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                    s.appInfo.uid, s.name, s.processName);

            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                s.connections.put(binder, clist);
            }
            clist.add(c);
            b.connections.add(c);
            if (activity != null) {
                if (activity.connections == null) {
                    activity.connections = new HashSet<ConnectionRecord>();
                }
                activity.connections.add(c);
            }
            b.client.connections.add(c);
            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.hasAboveClient = true;
            }
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c, true);
            }
            clist = mServiceConnections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                mServiceConnections.put(binder, clist);
            }
            clist.add(c);

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }

            if (s.app != null) {
                if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                    s.app.treatLikeActivity = true;
                }
                // This could have made the service more important.
                mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                        || s.app.treatLikeActivity, b.client);
                mAm.updateOomAdjLocked(s.app);
            }

            if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
                    + ": received=" + b.intent.received
                    + " apps=" + b.intent.apps.size()
                    + " doRebind=" + b.intent.doRebind);

            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                    c.conn.connected(s.name, b.intent.binder);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }

                // If this is the first app connected back to this binding,
                // and the service had previously asked to be told when
                // rebound, then do so.
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }

            getServiceMap(s.userId).ensureNotStartingBackground(s);

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;
    }
  • 最后ActivityManagerNative getDefault留個(gè)下次分解
 static public IActivityManager getDefault() {
        return gDefault.get();
    }

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末菩浙,一起剝皮案震驚了整個(gè)濱河市巢掺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌劲蜻,老刑警劉巖陆淀,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異先嬉,居然都是意外死亡轧苫,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門疫蔓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)含懊,“玉大人,你說(shuō)我怎么就攤上這事衅胀〔砬牵” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵滚躯,是天一觀的道長(zhǎng)雏门。 經(jīng)常有香客問(wèn)我嘿歌,道長(zhǎng),這世上最難降的妖魔是什么茁影? 我笑而不...
    開(kāi)封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任搅幅,我火速辦了婚禮,結(jié)果婚禮上呼胚,老公的妹妹穿的比我還像新娘茄唐。我一直安慰自己,他們只是感情好蝇更,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布沪编。 她就那樣靜靜地躺著,像睡著了一般年扩。 火紅的嫁衣襯著肌膚如雪蚁廓。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天厨幻,我揣著相機(jī)與錄音相嵌,去河邊找鬼。 笑死况脆,一個(gè)胖子當(dāng)著我的面吹牛饭宾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播格了,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼看铆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了盛末?” 一聲冷哼從身側(cè)響起弹惦,我...
    開(kāi)封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悄但,沒(méi)想到半個(gè)月后棠隐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡檐嚣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年助泽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片净嘀。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡报咳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挖藏,到底是詐尸還是另有隱情暑刃,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布膜眠,位于F島的核電站岩臣,受9級(jí)特大地震影響溜嗜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜架谎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一炸宵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谷扣,春花似錦土全、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至末秃,卻和暖如春概页,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背练慕。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工惰匙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铃将。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓项鬼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親麸塞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秃臣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 一涧衙、IPC簡(jiǎn)介 (1)IPC是Inter-Process Communication的縮寫哪工,含義為進(jìn)程間通信或者跨...
    遙遙的遠(yuǎn)方閱讀 7,202評(píng)論 0 3
  • Binder簡(jiǎn)析 直觀來(lái)說(shuō),Binder 是 Android 中的一個(gè)類弧哎,是繼承了 IBinder 接口雁比;從 IP...
    任教主來(lái)也閱讀 2,035評(píng)論 0 3
  • 原文鏈接: http://weishu.me/2016/01/12/binder-index-for-newer/...
    miniminiming閱讀 721評(píng)論 1 6
  • 簡(jiǎn)單說(shuō)Binder Binder算是Android中比較難懂的一部分內(nèi)容了,但是非常的重要撤嫩,要想研究Framewo...
    EsonJack閱讀 1,542評(píng)論 0 4
  • 節(jié)至中秋人兩地偎捎,通宵墜雨月無(wú)華。 多年?duì)€漫常環(huán)膝序攘,以后團(tuán)圓別有家茴她。 性到椿萱剛自減,言逢掌玉潤(rùn)相加程奠。 平生奉事遵賢...
    心硯YCH閱讀 430評(píng)論 1 4