binderService()方法的調用過程

bindService()在綁定Service主要經歷一下幾個過程:

  • Activity向ActivityManagerService發送一個綁定xxxService組件的進程間的請求。
  • ActivityManagerService在接到請求後檢查運行XXXService組件的進程是否處於運行狀態,如果沒有運行就啓動這個進程。
  • 在運行XXXService的進程啓動後,ActivityManagerService就請求它返回一個Binder的本地(代理)對象,以便於Activity通過這個Binder對象和Service建立連接。
  • AMS將從XXXService中獲得本地(代理)Binder對象發送給Activity。
  • Activity在獲得Binder對象後就可以去訪問XXXService中實現的接口。

Service實例

我通過一個AnimalService的實例來分析bindService()的過程。首先通過AIDL定義服務接口:

package com.cike.firstkotlin;

import com.cike.firstkotlin.model.Animal;
// Declare any non-default types here with import statements
//定義動物管理接口
interface IAnimalManager {
    //添加動物
    void addAnimal(in Animal animal);
    //獲取動物列表
    List<Animal> getAnimals();
}

Animal類的定義如下:


import android.os.Parcel
import android.os.Parcelable

open class Animal(val name : String) : Parcelable {
    constructor(parcel: Parcel) : this(parcel.readString())

    override fun writeToParcel(p0: Parcel?, p1: Int) {
        if (p0 != null) {
            p0.writeString(name);
        }
    }

    override fun describeContents(): Int {
        return 0;
    }

    companion object CREATOR : Parcelable.Creator<Animal> {
        override fun createFromParcel(parcel: Parcel): Animal {
            return Animal(parcel)
        }

        override fun newArray(size: Int): Array<Animal?> {
            return arrayOfNulls(size)
        }
    }
}

實現了IAnimalManager接口的Service的內容:

package com.cike.firstkotlin.activity

import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.cike.firstkotlin.IAnimalManager
import com.cike.firstkotlin.model.Animal

class AnimalManagerService : Service() {
    val store : MutableList<Animal> = ArrayList<Animal>()

    override fun onBind(p0: Intent?): IBinder? {
        println(this.toString() + "onBind()")
        return  object : IAnimalManager.Stub() {
            override fun getAnimals(): MutableList<Animal> {
                return store
            }

            override fun addAnimal(animal: Animal?) {
                if(animal != null)  {
                    store.add(animal)
                }
                println( "有多少動物:${store?.size} 新添加的動物是${animal?.name}")
            }
        }
    }
}

在MainActivty中綁定服務:

    //創建ServiceConnection對象
    object mServiceConnection : ServiceConnection {
        var animalMS: IAnimalManager? = null

        override fun onServiceDisconnected(p0: ComponentName?) {
            animalMS = null
        }

        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            animalMS = IAnimalManager.Stub.asInterface(p1)
        }
    }
    
    val bindIntent = Intent()
        bindIntent.setClass(this, AnimalManagerService::class.java)
        //綁定AnimalManagerService服務
        bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE)

先從Activity的bindService()方法開始分析。Activity繼承自ContextWrapper類bindService()方法就定義在這裏:

.../aosp/frameworks/base/core/java/android/content/ContextWrapper.java

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
            //這裏的mBase實際上是ContextImpl的實例
        return mBase.bindService(service, conn, flags);
    }

在bindService()方法中直接調用了mBase的bindService()方法,這裏的mBase是ContextImpl的實例,所以調用了ContextImpl的bindService():

.../aosp/frameworks/base/core/java/android/app/ContextImpl.java
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        //交給bindServiceCommon()繼續處理
        return bindServiceCommon(service, conn, flags, Process.myUserHandle());
    }
    
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            UserHandle user) {
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            //1.IServiceConnection服務的本地Binder對象
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        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();
            //調用ActivityManagerProxy的bindService()方法
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
    }

在註解1.處mPackageInfo是一個LoadedApk的對象,在LoadedApk中存儲了當前應用的信息(如應用androidMainfase.xml解析後的信息)。這裏通過mPackageInfo.getServiceDispatcher(conn,getOuterContext(),mMainThread.getHandler(), flags)獲取了一個InnerConnection類對象。InnerConnection類繼承自IServiceConnection.Stub類,是接口IServiceConnection的Binder的本地通信對象。IServiceConnection接口是在IServicConnection.aidl中定義。


public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
        synchronized (mServices) {
            //ServiceDispatcher類中封裝了InnerConnection、ServiceConnection、Handler等屬性。
            LoadedApk.ServiceDispatcher sd = null;
            /**
            * mServices這個Map以Context爲Key,這裏的context 指的就是Activity. 所以mServices存儲的是當前Activity綁定的service。
            * 1.一個Activity可能會綁定多個Service,所以mServices的key對應的Value是一個集合ArrayMap.
            * 2.做爲Value的ArrayMap以綁定service使用的ServiceConnection爲key,以ServiceDispatcher爲Value
            */
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                sd = map.get(c);
            }
            if (sd == null) {
                /**
                 * c serviceConnection
                 * handler 是應用程序進程ActivityThread中的mH
                 */
                sd = new ServiceDispatcher(c, context, handler, flags);
                if (map == null) {
                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
                    mServices.put(context, map);
                }
                map.put(c, sd);
            } else {
                sd.validate(context, handler);
            }
            return sd.getIServiceConnection();
        }
    }

在LoadedApk的getServiceDispatcher()方法中首先定義了一個ServiceDispatcher類型的對象sd,ServiceDispatcher中封裝了IServiceConnecation的Binder本地對象和ActivityThread的主線程中的Handler–mH(這個Handler在後邊綁定服務時會用到)。然後從mServices變量中獲取ServiceDispatcher實例,mServices是一個以Context爲key,ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>爲value的ArrayMap類型的變量。這裏作爲Key的Context指的就是Activity,用於標示那個Ativity要綁定服務。因爲一個Activity可以綁定多個Service所以Services的Value又使用了一個ArrayMap<ServiceConnection,ServiceDispatcher>。在ServiceDispatcher類中封裝了ServiceConnection的binder通信的本地對象、綁定服務的Activity的主進程的Handler(mH)等信息。在最後通過getIServiceConnection()返回一個IServiceConncection的Binder的本地對象。

我們繼續回到ContextImpl的bindServiceCommon()方法中,通過ActivityManagerNative.getDefault()獲取一個ActivityManagerService的代理對象ServiceManagerProxy,然後調用了代理對象的bindServcie()通過Binder驅動程序將綁定服務調用傳遞給AMS繼續處理。

···/frameworks/base/core/java/android/app/ActivityManagerProxy.java
    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType, IServiceConnection connection,
            int flags,  String callingPackage, int userId) throws RemoteException {
        //創建序列化容器
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        //將參數吸入到Parcel對象data中
        data.writeInterfaceToken(IActivityManager.descriptor);
        //將ApplicationThread的Binder機制的本地對象下入data
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        //將要綁定Activity的token寫入data
        data.writeStrongBinder(token);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        //將InnerConnection的Binder機制中的本地對象下入Data
        data.writeStrongBinder(connection.asBinder());
        data.writeInt(flags);
        data.writeString(callingPackage);
        data.writeInt(userId);
        // 通過binder將請求發送給AMS
        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    }

mRemote.transact(…)方法通過Binder驅動程序最終會調用到ActivityManagerNative.java的onTransact()方法中:

···/frameworks/base/core/java/android/app/ActivityManagerNative.java

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
  switch (code) {
    case BIND_SERVICE_TRANSACTION: {
      data.enforceInterface(IActivityManager.descriptor);
      IBinder b = data.readStrongBinder();
      //在AMP的bindService()中傳入的是ApplicationThread的binder機制的本地對象,
      //此處b爲ApplicationThread的, 轉換後生成即ApplicationThreadProxy對象。
      //我一直不太理解明明傳入的是本地對象爲什麼在AMS中接受時怎麼就轉化爲了代理對象,
      //後來才明白這個轉化過程是在Binder驅動程序中完成的。轉換過程可以看一下Binder機制的文章
      IApplicationThread app = ApplicationThreadNative.asInterface(b);
      IBinder token = data.readStrongBinder();
      Intent service = Intent.CREATOR.createFromParcel(data);
      String resolvedType = data.readString();
      b = data.readStrongBinder();
      int fl = data.readInt();
      String callingPackage = data.readString();
      int userId = data.readInt();
      //生成InnerConnectiond的代理對象
      IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
      //通過bindService()方法繼續處理
      int res = bindService(app, token, service, resolvedType, conn, fl,
              callingPackage, userId);
      reply.writeNoException();
      reply.writeInt(res);
      return true;
    }
    ...
  }
}

這些調用過程都是在需要綁定服務的Activity所在的進程進程中完成的,調用AMS的代理對象的方法後通過Binder機制進入到AMS中繼續處理。真正處理bindService()請求的邏輯在下面:

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        synchronized(this) {
            //調用ActiveService的bindServiceLocked()方法繼續處理
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

在AMS的bindService()中直接調用了ActiveServices類的對象mServices的bindServiceLocked()方法繼續處理。ActiveService類內部封裝了對Service的綁定狀態保存等。具體看一下AtiveServices的bindService():

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags,
            String callingPackage, int userId) throws TransactionTooLargeException {
        
        //通過ApplicationThread獲取需要綁定service的應用是否已經運行
        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) {
            //通過token找到需要綁定服務的activity,這裏使用的是token的標示作用
            activity = ActivityRecord.isInStackLocked(token);
            if (activity == null) {
                Slog.w(TAG, "Binding with unknown activity: " + token);
                return 0;
            }
        }

        ·································
        
        //檢索出需要綁定的Service的ServiceRecord的包裝類;如果ServiceRecord不存在則創建一個新的並被包裝成ServiceLookUpResult對象。
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
        if (res == null) {
            return 0;
        }
        if (res.record == null) {
            return -1;
        }
        //要綁定的ServiceRecord
        ServiceRecord s = res.record;

        final long origId = Binder.clearCallingIdentity();

        try {
            ················

            mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                    s.appInfo.uid, s.name, s.processName);
            //檢索出一個Service和一個App的關聯信息
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            //綁定記錄,這裏邊包含了那個應用進程的那個activity要綁定ServiceRecord的信息
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);
            //connection是IServiceConnection的代理對象
            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();
                //啓動service
                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_SERVICE, "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;
    }

該方法主要功能:

  • 通過AMS的getRecordForAppLocked()方法根據ApplicationThread參數獲取要綁定的service所在的進程是否啓動。
  • 通過retrieveServiceLocked()方法根據Intent檢查或創建Service記錄。
  • 通過retrieveAppBindingLoced()方法檢索出一個Service和要綁定service的app相關的信息,並將這些信息封裝到AppBindRecord中。
  • 創建ConnectionRecord對象用於封裝那個應用綁定那個進程的服務的相關信息。
  • 通過bringUpServiceLocked()方法啓動服務。根據啓動的service是否運行在獨立進程中返回不同的值。如果service運行在獨立進程中則此方法返回值爲null;
  • 在bringUpServiceLocked()方法返回null時(即Service單獨一個進程時)繼續調用requestServiceBindingLocked()方法綁定服務。

在bindServiceLocked()方法中主要用於檢查並創建Service相關的ServiceRecord和要綁定此Service的APP的相關信息,最終調用bringUpServiceLocked()方法啓動服務。

private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting) throws TransactionTooLargeException {
            
        ....................................
        
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;
        //isolated標示Service是不是運行在獨立進程中
        if (!isolated) {
            //獲取ProcessRecord對象。如果app不爲null則說明service要運行的進程已經創建。
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    //重要; 進一步處理
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
            }
        } else {
            app = r.isolatedProc;
        }

        if (app == null) {
            //啓動這個Service所在的進程, 進程創建成功後會返回ProcessRecord
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
                //重啓seivice綁定
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }

        if (!mPendingServices.contains(r)) {
            //將serivice添加到等待啓動隊列中,等進程啓動後再啓動這個Service
            mPendingServices.add(r);
        }

.......................................................

        return null;
    }

bringUpServiceLocked()方法主要功能是通過r.serviceInfo.flags屬性值判斷Service是不是運行在獨立進程中,如果不是運行在獨立進程中則說明要綁定的Service和Activity運行在同一個進程中。如果isolated = false則通過mAm.getProcessRecordLocked()檢查當前進程是否存在,如果存在則調用realStartServiceLocked(r, app, execInFg)方法繼續處理服務啓動的工作。如果要綁定的Service運行在獨立的進程中且這個獨立的進程還沒有運行則調用AMS的startProcessLocked()方法啓動這個進程並讓bringUpServiceLocked()方法返回null。在我分析的場景中將Service設置爲運行在獨立進程中,所以調用startProcessLocked()方法從Zygote進程中fork()出一個新進程同時返回null後繼續回到bindServiceLocked()方法中。

在startProcessLocked()方法會從Zygote進程中fork()五一個新的進程,在新進程創建出來後會間接的調用到realStartServiceLocked()方法來啓動服務。下面看看它是怎麼啓動服務的吧。

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        //這個service在那個進程中
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            ...................
            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //重要。通過ApplicationThread從AMS中回到Client。
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);

                // Cleanup.
                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                }

                // Retry.
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }
        //在Service本創建後繼續處理
        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null));
        }

        sendServiceArgsLocked(r, execInFg, true);

        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                        "Applying delayed stop (from start): " + r);
                stopServiceLocked(r);
            }
        }
    }

在realStartServiceLocked()方法中主要有一下幾點:

  • 通過app.thread.scheduleCreateService()方法通知ApplicationThread去創建Service。
  • 通過requestServiceBindingsLocked()方法在Service創建後綁定服務。

在這裏app.thread是AppliactionThreadProxy的對象,調用他的scheduleCreateService()方法會通過Binder通信機制最終調用到ApplicationThread的scheduleCreateService()方法。

.../aosp/frameworks/base/core/java/android/app/ActivityThread.java
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);
        }

在ApplicationThread的scheduleCreateService()方法中痛毆sendMessage()發送東西到mH 的Handler中進一步處理:

.../aosp/frameworks/base/core/java/android/app/ActivityThread.java
private class H extends Handler {
    public void handleMessage(Message msg) {
    
    ..................................
    
        case CREATE_SERVICE:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
            //繼續處理
            handleCreateService((CreateServiceData)msg.obj);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
            .....................
        }
}

在Handler的handleMessage()方法的switch case CREATE_SERVICE分支中直接調用了handleCreateService()方法繼續處理:

.../aosp/frameworks/base/core/java/android/app/ActivityThread.java
private void handleCreateService(CreateServiceData data) {
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            //反射創建Service實例
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {   .............     }
        try {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //調用service的attach()方法
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            //調用onCreate()方法
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

在handleCreateService()方法中有一下重要的點:

  • 通過反射創建Service實例。
  • 通過LoadApk.makeApplication()方法創建Application實例。
  • 調用Service實例的attach()方法和onCreate()方法。
  • 調用ActivityManagerProxy.ServiceDoneExecuting()方法通知AMS服務已經創建完成。

分析到這裏我們已經知道了Service的創建過程,現在我們繼續回到ActiveService的bindServiceLocked()方法中。上邊分析看到bindServiceLocked()方法有兩個要點:一個是realStartServiceLocked()方法(已經分析過了)。現在繼續另外一個要requestServiceBindingLocked()方法:

.../aosp/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
            //如果要綁定的service所以進程不存在直接返回。
        if (r.app == null || r.app.thread == null) {
            return false;
        }
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                //通過ApplicationThread代理對象回到客戶端
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
                ..................................
            } catch (RemoteException e) {
                ..................................
            }
        }
        return true;
    }

requestServiceBindingLocked()方法直接通過ApplicationThread的代理對象ApplicationThreadProxy的scheduleBindService()方法通過Binder通信機制調用到要綁定Service的activity的ApplicationThread的scheduleBindService()方法中;下面的操作就進入了Client端繼續處理:

.../aosp/frameworks/base/core/java/android/app/ActivityThread.java的內部類ApplicationThread中
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);
        }

在ApplicationThread類的scheduleBindService()方法中通過sendMessage()方法發送消息給H類型的mH Handler繼續處理。

.../aosp/frameworks/base/core/java/android/app/ActivityThread.java
private class H extends Handler {
    public static final int BIND_SERVICE = 121;
    public void handleMessage(Message msg) {
    
    .................................
    case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    //具體執行服務綁定
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
    
    .........................
    }

在ActivityThread的H hander的handleMessage()方法中switch BIND_SERVICE:分支中直接調用了handleBindService()方法繼續處理:

.../aosp/frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
    
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        //調用service的onBind()對象
                        IBinder binder = s.onBind(data.intent);
                        //通知AMS服務的onBind()已經執行了
                        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);
                }
            }
        }
    }

在handleBindService()方法中主要是調用了Service的onBind()方法然後通過ActivityManagerProxy的publishService()方法通知AMS Service的onBind()方法已經調用可以繼續處理了。下面看一下AMS的publishService():

.../aosp/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            //重要,調用了ActiveServices的publishServiceLocked()方法繼續處理
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

在AMS的publishService()方法中直接調用了ActiveServices的pulishServiceLocked()繼續處理:

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 && !b.received) {
                    b.binder = service;         //service的Binder本地對象
                    b.requested = true;
                    b.received = true;
                    //循環遍歷所有要綁定這個service的進程
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        //在一個進程中可能有多個組件Activity綁定這個service
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
                                ..................................
                                continue;
                            }
                            try {
                                //調用IServiceConnection代理對象的connected()方法
                                c.conn.connected(r.name, service);
                            } catch (Exception e) {}
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

在publishServiceLocked()方法中通過Intent從ServiceRecord中查找出要綁定Service的所用ServiceConnecation。要綁定這個Service的進程可能又多個而每個進程中也可能會用多個組件Activity來綁定這個Service所以這裏用了循環迭代的方式調用ServiceConnection的代理對象ServiceConnectionProxy的connected()方法,通過Binder驅動程序connected()方法最終會調用到本地對象InnerConnection類的connected()方法:

.../aosp/frameworks/base/core/java/android/app/LoadedApk.java
    //IServiceConnection的binder本地對象。
        private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
            
            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }
            //通過binder驅動程序調用到這裏
            public void connected(ComponentName name, IBinder service) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service);
                }
            }
        }

在InnerConnection的connected()方法中直接調用了ServiceDispatcher的connected()方法:

.../aosp/frameworks/base/core/java/android/app/LoadedApk.java內部類的ServiceDispatcher類
public void connected(ComponentName name, IBinder service) {
            //這個的mActivityThread即使ActivityThread中穿件H handler 
            if (mActivityThread != null) {
                //向H handler發送一個Runable對象RunConnection
                mActivityThread.post(new RunConnection(name, service, 0));
            } else {
                doConnected(name, service);
            }
        }

在ServiceDispatcher的connected()方法中mAtivityThread指的就是ActivityThread中的H handler.這裏直接向Handler中發送了一個RunConnection類型的runable。

private final class RunConnection implements Runnable {
            RunConnection(ComponentName name, IBinder service, int command) {
                mName = name;
                mService = service;
                mCommand = command;
            }

            public void run() {
                if (mCommand == 0) {
                //根據ServiceDispatcher的connected()方法中構建RunConnection時傳入的參數command = 0
                //所以會執行doConnected()方法
                    doConnected(mName, mService);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

            final ComponentName mName;
            final IBinder mService;
            final int mCommand;
        }

在RunConnection的run()方法通過屬性mCommand = 0,這裏會繼續執行doConnected()方法:

public void doConnected(ComponentName name, IBinder service) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
                if (mForgotten) {
                    return;
                }
                old = mActiveConnections.get(name);
                if (old != null && old.binder == service) { 
                    return;
                }

                if (service != null) {
                    // A new service is being connected... set it all up.
                    mDied = false;
                    info = new ConnectionInfo();
                    info.binder = service;
                    //設置service死亡監聽
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
                        service.linkToDeath(info.deathMonitor, 0);
                        //將ServiceConnection保存
                        mActiveConnections.put(name, info);
                    } catch (RemoteException e) {
                        // This service was dead before we got it...  just
                        // don't do anything with it.
                        mActiveConnections.remove(name);
                        return;
                    }

                } else {
                    // The named service is being disconnected... clean up.
                    mActiveConnections.remove(name);
                }

                if (old != null) {
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
            }

            // If there was an old service, it is not disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            // If there is a new service, it is now connected.
            if (service != null) {
                //調用ServiceConnection的onServiceConnected()方法
                mConnection.onServiceConnected(name, service);
            }
        }

在doConnect()方法中首先檢查有沒有舊的ServiceConnection的信息,如果有則終止服務並通知綁定此service的activiy已經終止了。然後最後調用mConnection.onServiceConnected()。onServiceConnected()方法的實現就是我們在綁定服務時創建的。
到此bindService()的過程已經全部完成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章