溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android?Service啟動(dòng)綁定流程是什么

發(fā)布時(shí)間:2023-03-09 10:09:39 來源:億速云 閱讀:163 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹了Android Service啟動(dòng)綁定流程是什么的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Android Service啟動(dòng)綁定流程是什么文章都會(huì)有所收獲,下面我們一起來看看吧。

一、Service 的啟動(dòng)流程

1、ContextImpl.startService

啟動(dòng)一個(gè)Service,通常在Activity調(diào)用startService來啟動(dòng)。

@Override
public ComponentName startService(Intent service) {
    return startServiceCommon(service, false, mUser);
}
2、ContextImpl.startServiceCommon

startServiceCommon檢查intent內(nèi)容是否合法,然后做一些離開當(dāng)前進(jìn)程的準(zhǔn)備操作。調(diào)用 ActivityManager.getService()獲得AMS的本地引用,并調(diào)用其startService函數(shù)。

也就是說通過Binder機(jī)制跨進(jìn)程通信調(diào)用了AMSstartService函數(shù)。

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        //檢查intent 的compant和package是否合法
        validateServiceIntent(service);
        ...
        ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                getOpPackageName(), getAttributionTag(), user.getIdentifier());
        ...
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

通過 ActivityManager.getService()的實(shí)現(xiàn)。

    @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    @UnsupportedAppUsage
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
3、AMS.startService

AMS.startService函數(shù)獲取調(diào)用PidUid,然后調(diào)用ActiveServicestartServiceLocked函數(shù)。

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage,
        String callingFeatureId, int userId)
        throws TransactionTooLargeException {
    ...
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, callingFeatureId, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}
4、ActiveService.startServiceLock

ActiveService.startServiceLock函數(shù),對一些合法性的檢查,例如前臺(tái)Service的權(quán)限、限制性后臺(tái)Service進(jìn)行延遲運(yùn)行(standby)。并將要啟動(dòng)的信息封裝成ServiceRecord。然后調(diào)用了startServiceInnerLocked函數(shù)。

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage,
        @Nullable String callingFeatureId, final int userId)
        throws TransactionTooLargeException {
    return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
            callingPackage, callingFeatureId, userId, false);
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage,
        @Nullable String callingFeatureId, final int userId,
        boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
    final boolean callerFg;
    if (caller != null) {
        //獲取調(diào)用Service的應(yīng)用程序進(jìn)程描述
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        if (callerApp == null) {
          ...
        }
        callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
    } else {
        callerFg = true;
    }
    //檢索ServiceRecord,包括同應(yīng)用和其他應(yīng)用
    ServiceLookupResult res =
        retrieveServiceLocked(service, null, resolvedType, callingPackage,
                callingPid, callingUid, userId, true, callerFg, false, false);
    ...
    //要啟動(dòng)的ServiceRecord
    ServiceRecord r = res.record;
    ...
    r.lastActivity = SystemClock.uptimeMillis();
    r.startRequested = true;
    r.delayedStop = false;
    r.fgRequired = fgRequired;
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants, callingUid));
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    ...
    return cmp;
}
5、ActiveServices.startServiceInnerLocker

調(diào)用了bringUpServiceLocked函數(shù),會(huì)將ServiceRecord添加到ServiceMap類型的smap集合,進(jìn)行緩存。

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    r.callStart = false;
    ...
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    ...
    return r.name;
}
6、 ActiveService.bringUpServiceLocked

分析一:首次啟動(dòng)Service時(shí),在執(zhí)行bringUpServiceLocked函數(shù),ServiceRecord是屬于新創(chuàng)建的,而非從AMS的緩存mServices中檢索而來,所以此時(shí)的ServiceRecordProcessRecord類型appIApplicationThread類型thread都是null。只有啟動(dòng)過后的ServiceRecord才有值,才會(huì)執(zhí)行sendServiceArgsLocked函數(shù),重復(fù)調(diào)用Service的生命周期onStartCommand,而不調(diào)用onCreate函數(shù)。

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //分析一:未啟動(dòng)過的ServiceRecord兩者都是null,重復(fù)啟動(dòng)會(huì)執(zhí)行該函數(shù),
        //會(huì)重復(fù)調(diào)用service的onStartCommand函數(shù)。
        if (r.app != null &amp;&amp; r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
		...
        final boolean isolated = (r.serviceInfo.flags&amp;ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
        ProcessRecord app;
        if (!isolated) {
        	////通過AMS獲取service所在進(jìn)程的ProcessRecord。ProcessList=&gt;MyProcessMap=》會(huì)緩存已創(chuàng)建過進(jìn)程的ProcessRecord
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (app != null &amp;&amp; app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    //啟動(dòng)服務(wù)
                   realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                }
            }
        }
        //如果service所在的進(jìn)程未啟動(dòng),通過AMS啟動(dòng)該進(jìn)程,可以參考應(yīng)用進(jìn)程的啟動(dòng)流程
          if (app == null &amp;&amp; !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {;
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
        //等待進(jìn)程啟動(dòng)完畢重啟啟動(dòng)
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
		...
        return null;
    }
7、ActiveService.realStartServiceLocked
   private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        //將ProcessRecord設(shè)置給ServiceRecord
        r.setProcess(app);
		//登記當(dāng)ServiceRecord到ProcessRecordd的數(shù)組mServices,表示Service已經(jīng)啟動(dòng)(實(shí)際未啟動(dòng))
        final boolean newService = app.startService(r);
        boolean created = false;
        try {
			...
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());
          	...
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app, "Died when creating service");
            throw e;
        } 
        //會(huì)調(diào)用Service的onStartCommand函數(shù)
         sendServiceArgsLocked(r, execInFg, true);
        ...
    }

通過ProcessRecord對象的IApplicationThread引用,通過Binder機(jī)制調(diào)用了應(yīng)用程序的ApplicationThreadscheduleCreateService函數(shù)。

8、ApplicationThread.scheduleCreateService

ServiceInfo等相關(guān)信息封裝到CreateServiceData中,并發(fā)送給ActivityThreadH類型的mH對象。

public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;
    s.compatInfo = compatInfo;
    sendMessage(H.CREATE_SERVICE, s);
}
9、H.handleMesssage

調(diào)用了ActivityThreadhandleCreateService函數(shù)。

case CREATE_SERVICE:
    handleCreateService((CreateServiceData)msg.obj);
    break;
10、ActivityThread.handleCreateService
    private void handleCreateService(CreateServiceData data) {
        ...
        //獲取當(dāng)前應(yīng)用的描述信息LoadedApk
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
           //創(chuàng)建Service的上下問文
           ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
           //獲取當(dāng)前應(yīng)用Applcation對象
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //通過反射創(chuàng)建Service對象
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
           //初始化資源
            context.getResources().addLoaders(
                    app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
		   //context 與service相互綁定
            context.setOuterContext(service);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //調(diào)用Service的生命周期onCreate函數(shù),意味Service創(chuàng)建完畢
            service.onCreate();
            //緩存Service
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

通過ContextImpl.createAppContext創(chuàng)建Service的上下文context,通過packageInfo.getAppFactory().instantiateService反射獲得當(dāng)前Service對象service,將contextservice相互綁定。然后調(diào)用service.onCreate。至此,Service創(chuàng)建完畢。

二、Service的綁定

1、 ContextImpl.bindService
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
	//系統(tǒng)進(jìn)程調(diào)用綁定服務(wù)或發(fā)送廣播都會(huì)發(fā)出警告
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
            getUser());
}
2、ContextImpl.bindServiceCommon

在分析一,主要判斷入?yún)?code>Executor executor或UserHandle user哪個(gè)為null,總有一個(gè)為null,但最終都是調(diào)用了LoadedApkgetServiceDispatcherCommon函數(shù)來獲取ServiceDispathcer類型sd。影響只是回調(diào)代碼是在主線程執(zhí)行,還是線程池。這里傳入ActivityThreadH對象,意味著后續(xù)連接成功回調(diào)onServiceConnected是在主線程。

分析二:通過Binder機(jī)制調(diào)用AMSbindIsolatedService函數(shù)。

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
        String instanceName, Handler handler, Executor executor, UserHandle user) {
    // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
    IServiceConnection sd;
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (handler != null && executor != null) {
        throw new IllegalArgumentException("Handler and Executor both supplied");
    }
    if (mPackageInfo != null) {
        if (executor != null) {//分析一:無論哪個(gè)分支,都是獲得ServiceConnect的本地引用sd,兩者最終都是
        //調(diào)用LoadedApk的getServiceDispatcherCommon
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
        } else {
            //正常使用走這個(gè)分支
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        }
    } else {
        throw new RuntimeException("Not supported in system context");
    }
    //檢查compant and package is null ?
    validateServiceIntent(service);
    try {
        IBinder token = getActivityToken();
        if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                && mPackageInfo.getApplicationInfo().targetSdkVersion
                < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            flags |= BIND_WAIVE_PRIORITY;
        }
        service.prepareToLeaveProcess(this);
        //分析二:調(diào)用AMS.bindIsolatedService
        int res = ActivityManager.getService().bindIsolatedService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
        if (res < 0) {
            throw new SecurityException(
                    "Not allowed to bind to service " + service);
        }
        return res != 0;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

IServiceConnection連接的創(chuàng)建會(huì)先從緩存中獲取,避免每次都要新建。分析一:通過executorhandler創(chuàng)建ServiceDispatcher類型的sd,含有靜態(tài)內(nèi)部類InnerConnection的引用mIServiceConnection。繼承自IServiceConnection.Stub,也就是InnerConnection是實(shí)現(xiàn)者,遠(yuǎn)程調(diào)用代理在其他進(jìn)程,例如SystemServer進(jìn)程中的ActiveService。

private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
        Context context, Handler handler, Executor executor, int flags) {
    synchronized (mServices) {
        LoadedApk.ServiceDispatcher sd = null;
        //從緩存獲取
        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
        if (map != null) {
            sd = map.get(c);
        }
        if (sd == null) {
        	//分析一:通過executor或handler創(chuàng)建ServiceDispatcher
            if (executor != null) {
                sd = new ServiceDispatcher(c, context, executor, flags);
            } else {
                sd = new ServiceDispatcher(c, context, handler, flags);
            }
            if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
            if (map == null) {
                map = new ArrayMap<>();
                mServices.put(context, map);
            }
            map.put(c, sd);
        } else {
            sd.validate(context, handler, executor);
        }
        return sd.getIServiceConnection();
    }
}
3、AMS.bindIsolatedService

AMS經(jīng)過兩次重載函數(shù)bindIsolatedService調(diào)用,簡單檢查相關(guān)合法性。然后調(diào)用ActiveService類型的mServicebindServiceLocked函數(shù)。

4、ActiveService.bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, final IServiceConnection connection, int flags,
        String instanceName, String callingPackage, final int userId)
        throws TransactionTooLargeException {
    //發(fā)起綁定service的app進(jìn)程描述
    final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
    ...
    ServiceLookupResult res =
        retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
                Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
                callerFg, isBindExternal, allowInstant);
    ...
    ServiceRecord s = res.record;
    ...
        //描述Service和應(yīng)用程序進(jìn)程之間的關(guān)聯(lián),內(nèi)部維護(hù)Service、進(jìn)程、IntentFilter以及所有綁定信息。
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        //描述應(yīng)用程序與service建立的一次通信(綁定)
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent,
                callerApp.uid, callerApp.processName, callingPackage);
        IBinder binder = connection.asBinder();
        s.addConnection(binder, c);
        b.connections.add(c);
        if (activity != null) {
            activity.addConnection(c);
        }
        b.client.connections.add(c);
        c.startAssociationIfNeeded();
        ...
        //啟動(dòng)Service,可以參考Service的啟動(dòng)
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                    permissionsReviewRequired) != null) {
                return 0;
            }
        }
        ...
        //表示Service已啟動(dòng),且已返回binder,可以通過binder訪問接口
        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, false);
            } catch (Exception e) {
                Slog.w(TAG, "Failure sending service " + s.shortInstanceName
                        + " to connection " + c.conn.asBinder()
                        + " (in " + c.binding.client.processName + ")", e);
            }
            //第一個(gè)綁定該Service的進(jìn)程,且要重綁
            if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                requestServiceBindingLocked(s, b.intent, callerFg, true);
            }
        } else if (!b.intent.requested) {//首次綁定,執(zhí)行此次
            requestServiceBindingLocked(s, b.intent, callerFg, false);
        }
        ...
}

AppBindRecord 描述應(yīng)用程序進(jìn)程和Service的關(guān)聯(lián),包括誰綁定了ServiceProcessRecord,綁定信息IntentBindRecord,當(dāng)前服務(wù)ServiceRecord,當(dāng)前應(yīng)用進(jìn)程的所有連接記錄connections

5、requestServiceBindingLocked

調(diào)用了ApplicationThreadscheduleBindService函數(shù)。

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
           ...
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.getReportedProcState());
           ...
}
6、ApplicationThread.scheduleBindService

將數(shù)據(jù)封裝 BindServiceData,發(fā)送個(gè)ActivityThread的H類型的mH處理。

public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) {
    updateProcessState(processState, false);
    BindServiceData s = new BindServiceData();
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;
    sendMessage(H.BIND_SERVICE, s);
}
7 、 H.handleMessage
case BIND_SERVICE:
    handleBindService((BindServiceData)msg.obj);
8、ActivityThread.handleBindService

handleBindService函數(shù)有兩個(gè)分支,即是否重新綁定。

如果當(dāng)前進(jìn)程第一個(gè)與Service綁定,且調(diào)用過了onUbBinder方法,那么這里的data.rebind將為true,直接執(zhí)行ServiceonRebind函數(shù)即可。另外一種就是沒有綁定過,那么需要執(zhí)行ServiceonBind函數(shù)。然后還要執(zhí)行AMSpublishService函數(shù)。

private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
           ...
            try {
                if (!data.rebind) {
                    IBinder binder = s.onBind(data.intent);
                    ActivityManager.getService().publishService(
                            data.token, data.intent, binder);
                } else {
                    s.onRebind(data.intent);
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        ...
    }
}
9、AMS.publishService
public void publishService(IBinder token, Intent intent, IBinder service) {
    // Refuse possible leaked file descriptors
    if (intent != null &amp;&amp; intent.hasFileDescriptors() == true) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    synchronized(this) {
        if (!(token instanceof ServiceRecord)) {
            throw new IllegalArgumentException("Invalid service token");
        }
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}
10、ActiveService.publishServiceLocked

分析一:可見在第4步bindServiceLocked函數(shù),IntentBindRecord對象的屬性binderrequested、received都是false

ServiceRecord的所有連接記錄connections中,通過intent查找對應(yīng)之前已經(jīng)保存的ConnectionRecord,并調(diào)用其IServiceConnectionconnected函數(shù)。

在第2步的時(shí)候調(diào)用bindServiceCommon函數(shù)時(shí),會(huì)創(chuàng)建ServiceDispatcher時(shí),內(nèi)部持有InnerConnection實(shí)例,這里的IServiceConnection代理引用指向該InnerConnection實(shí)例,這里會(huì)調(diào)用其connected函數(shù)。

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null &amp;&amp; !b.received) {//分析1
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    ArrayMap&lt;IBinder, ArrayList&lt;ConnectionRecord&gt;&gt; connections = r.getConnections();
                    for (int conni = connections.size() - 1; conni &gt;= 0; conni--) {
                        ArrayList&lt;ConnectionRecord&gt; clist = connections.valueAt(conni);
                        for (int i=0; i&lt;clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
							 ...
                                continue;
                            }
                            ...
                            try {
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                                Slog.w(TAG, "Failure sending service " + r.shortInstanceName
                                      + " to connection " + c.conn.asBinder()
                                      + " (in " + c.binding.client.processName + ")", e);
                            }
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
11、InnerConnection.connected
private static class InnerConnection extends IServiceConnection.Stub {
    @UnsupportedAppUsage
    final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
    InnerConnection(LoadedApk.ServiceDispatcher sd) {
        mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
    }
    public void connected(ComponentName name, IBinder service, boolean dead)
            throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service, dead);
        }
    }
}
12、ServiceDispatcher.connected

這里調(diào)用了 mActivityThread.post(new RunConnection(name, service, 0, dead)),執(zhí)行RunConnectionrun函數(shù)。這里的話run函數(shù)執(zhí)行代碼又回到了應(yīng)用進(jìn)程的主線程。

public void connected(ComponentName name, IBinder service, boolean dead) {
    if (mActivityExecutor != null) {
        mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
    } else if (mActivityThread != null) {
        mActivityThread.post(new RunConnection(name, service, 0, dead));
    } else {
        doConnected(name, service, dead);
    }
}
13、RunConnection.run

RunConnectionServiceDispatcher的內(nèi)部類,這里執(zhí)行SDdoConnected函數(shù)。

public void run() {
    if (mCommand == 0) {
        doConnected(mName, mService, mDead);
    } else if (mCommand == 1) {
        doDeath(mName, mService);
    }
}
14、ServiceDispatcher.doConnected

這里調(diào)用了ServiceConnection對象的onServiceConnected函數(shù),也就是我們發(fā)起綁定,調(diào)用context.bindService的參數(shù)。

public void doConnected(ComponentName name, IBinder service, boolean dead) {
        ...
        mConnection.onServiceConnected(name, service);
        ...
}

到此,Service的綁定流程分析完畢。

三、Service的Context

在第一節(jié)Service的啟動(dòng)流程最后函數(shù)調(diào)用了ActivityThreadhandleCreateService函數(shù)。

    private void handleCreateService(CreateServiceData data) {
        unscheduleGcIdler();
		//應(yīng)用的描述信息
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
			//分析一
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
            context.getResources().addLoaders(
                    app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
			//分析二
            context.setOuterContext(service);
            //分析三
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

分析一:通過ContextImpl的靜態(tài)函數(shù)createAppContext返回了一個(gè)ContextImpl類型的contextcreateAppContext又調(diào)用了重載函數(shù)createAppContext。直接新建了ContextImpl實(shí)例context,構(gòu)造函數(shù)傳遞了ActivityThread類型的mainThread和LoadedApk類型的packageInfo。并給context設(shè)置了資源環(huán)境和是否Syetem屬性。

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    return createAppContext(mainThread, packageInfo, null);
}
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
        String opPackageName) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
            0, null, opPackageName);
    context.setResources(packageInfo.getResources());
    context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context);
    return context;
}

ContextImpl類有一個(gè)Context類型的mOuterContext屬性,在構(gòu)造函數(shù)時(shí)指向了自己。

回到handleCreateService函數(shù)的分析二,在創(chuàng)建好Service對象service之后,將service作為參數(shù)傳遞給了context.setOuterContext函數(shù)。Service本身繼承自ContextWrapper,ContextWrapper又是Context的子類。這時(shí)候的setOuterContext函數(shù)將service設(shè)置給了contextmOuterContext屬性。意味著當(dāng)前上下文context持有當(dāng)前新建的service引用。

在分析三,調(diào)用了service.attach函數(shù),context并作為第一個(gè)參數(shù)被傳入。attach函數(shù)又調(diào)用了attachBaseContext函數(shù)。

public final void attach(
        Context context,
        ActivityThread thread, String className, IBinder token,
        Application application, Object activityManager) {
    attachBaseContext(context);
    mThread = thread; 
    mClassName = className;
    mToken = token;
    mApplication = application;
    mActivityManager = (IActivityManager)activityManager;
    mStartCompatibility = getApplicationInfo().targetSdkVersion
            &lt; Build.VERSION_CODES.ECLAIR;
    setContentCaptureOptions(application.getContentCaptureOptions());
}

attachBaseContext調(diào)用了父類ContextWrapperattachBaseContext函數(shù)

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(newBase);
    if (newBase != null) {
        newBase.setContentCaptureOptions(getContentCaptureOptions());
    }
}

ContextWrapper將一路傳遞過來的上下文base設(shè)置給你了mBase屬性。

protected void attachBaseContext(Context base) {
    if (mBase != null) {
        throw new IllegalStateException("Base context already set");
    }
    mBase = base;
}

也就是說,我們在啟動(dòng)Service時(shí),會(huì)同時(shí)創(chuàng)建Service的上下文context,并將其存儲(chǔ)到Service的父類ContextWrappermBases屬性中,同時(shí)context也會(huì)有當(dāng)前Service引用,存儲(chǔ)在mOuterContext變量中。

關(guān)于“Android Service啟動(dòng)綁定流程是什么”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Android Service啟動(dòng)綁定流程是什么”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI