1. 程式人生 > >Android 中 startService()啟動service的過程分析

Android 中 startService()啟動service的過程分析

通過分析點選android桌面app圖示啟動應用程式的過程這篇文章,我們瞭解啟動activity的過程,再來分析啟動android的另一個元件service的過程就比較容易了.因為流程差不多.

現在假設應用程式有一個activity和一個service,然後在activity中通過startService()啟動service,清單檔案中service的process屬性沒有設定.也就是activity和service在一個程序中.

startService()這個方法是Activty的父類ContextWrapper中的.

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

 public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
這裡mBase變數是ContextImpl型別,是在建立activity的時候,new 一個ContextImpl物件,賦值給activity的.

frameworks/base/core/java/android/app/ActivityThread.java

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
   .....
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);//建立contextImpl
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
          .....
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);//傳進去

             .....
        return activity;
    }

好了繼續:

第一步:frameworks/base/core/java/android/app/ContextImpl.java

  public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceAsUser(service, mUser);
    }

    @Override
    public ComponentName startServiceAsUser(Intent service, UserHandle user) {
        try {
            service.setAllowFds(false);
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
           ....
            return cn;
        } catch (RemoteException e) {
            return null;
        }
    }

這裡通過Binder通訊,呼叫到ActivityManagerService的啟動service方法.

mMainThread.getApplicationThread()是ApplicationThread型別的mAppThread物件,ApplicationThread其實是Binder型別.是用來和ActivityManagerService程序間通訊的,它是在ActivityThread類中建立的.

service.resolveTypeIfNeeded(getContentResolver())獲取這個intent的MIME型別,這裡假設沒有設定MIME型別  即AndroidManifest.xml沒有設定Service的MIME型別,所以這裡返回null.

第二步:

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

 public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeInt(userId);
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        ComponentName res = ComponentName.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return res;
    }

通過Binder驅動
 case START_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            int userId = data.readInt();
            ComponentName cn = startService(app, service, resolvedType, userId);
            reply.writeNoException();
            ComponentName.writeToParcel(cn, reply);
            return true;
        }

上面就呼叫到了ActivityManagerService中.

第三步:startService().

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java.

 public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) {
      .....
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            checkValidCaller(callingUid, userId);
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

第四步:startServiceLocked().

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

ComponentName startServiceLocked(IApplicationThread caller,
            Intent service, String resolvedType,
            int callingPid, int callingUid, int userId) {
    ....
        if (caller != null) {
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {
           .....
            }
        }

        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    callingPid, callingUid, userId, true);
        if (res == null) {
           ...
        }
        if (res.record == null) {
          ...
        }
        ServiceRecord r = res.record;
    ......
        String error = bringUpServiceLocked(r, service.getFlags(), false);
  ....
        return r.name;
    }
 函式首先通過retrieveServiceLocked來解析service這個Intent,就是解析我們在AndroidManifest.xml定義的Service標籤的intent-filter相關內容,然後將解析結果放在res.record中.
第五步:bringUpServiceLocked().ActiveServices.java中
private final String bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean whileRestarting) {
       ....
        if (r.app != null && r.app.thread != null) {
       ...
        }
.....
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);//這裡獲取不為空,因為該service所在的程序已經啟動起來了
           ....
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName);
                    realStartServiceLocked(r, app);
                    return null;
                } catch (RemoteException e) {
                  ...
                }
.....
            }
        } else {
      ...
        }

      ....
        return null;
    }
這裡service所在的程序已經啟動起來了,所以接下來直接在這個程序中啟動service.

第六步:realStartServiceLocked().ActiveServices.java中

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app) throws RemoteException {
     ...
        try {
        ....
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));//去建立service
            r.postNotification();
            created = true;
        } finally {
          ...
        }
.....
        sendServiceArgsLocked(r, true);
    }
首先看scheduleCreateService方法,
第七步:scheduleCreateService().

frameworks/base/core/java/android/app/ApplicationThreadNative.java檔案中,這裡又是Binder程序間通訊了.

  public final void scheduleCreateService(IBinder token, ServiceInfo info,
            CompatibilityInfo compatInfo) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        info.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

經過Binder驅動
 case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
            CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
            scheduleCreateService(token, info, compatInfo);
            return true;
        }

這樣就呼叫到了應用程式中了

第八步:scheduleCreateService().

在frameworks/base/core/java/android/app/ActivityThread.java中

 public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo) {
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;

            queueOrSendMessage(H.CREATE_SERVICE, s);
        }

第九步:queueOrSendMessage().

在frameworks/base/core/java/android/app/ActivityThread.java中

 private void queueOrSendMessage(int what, Object obj) {
        queueOrSendMessage(what, obj, 0, 0);
    }
    private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
        synchronized (this) {
            if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
                + ": " + arg1 + " / " + obj);
            Message msg = Message.obtain();
            msg.what = what;
            msg.obj = obj;
            msg.arg1 = arg1;
            msg.arg2 = arg2;
            mH.sendMessage(msg);
        }
    }

第十步:handleCreateService().

在frameworks/base/core/java/android/app/ActivityThread.java中

case CREATE_SERVICE:
                  ...
                    handleCreateService((CreateServiceData)msg.obj);
                  ...
                    break;
private void handleCreateService(CreateServiceData data) {
    ...
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();//建立一個service例項
        } catch (Exception e) {
          ...
        }

        try {
         ...
            ContextImpl context = new ContextImpl();
            context.init(packageInfo, null, this);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            context.setOuterContext(service);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            service.onCreate();//回撥service的onCreat()方法
            mServices.put(data.token, service);
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, 0, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
        } catch (Exception e) {
           ...
        }
    }

service.onCreate()這個方法最終會回撥service的oncreate()方法,這個大家應該熟悉.這裡service就建立起來了

接下來回到第六步,另外一個方法sendServiceArgsLocked();

第十一步:sendServiceArgsLocked().

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

private final void sendServiceArgsLocked(ServiceRecord r,
            boolean oomAdjusted) {
       .....
                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
        ....
    }

這裡通過Binder通訊到應用程式中去了,

這裡我就省略中間的幾步了,和第七步類似.

第十二步:sendServiceArgsLocked().

在frameworks/base/core/java/android/app/ActivityThread.java中

 public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
            int flags ,Intent args) {
            ServiceArgsData s = new ServiceArgsData();
            s.token = token;
            s.taskRemoved = taskRemoved;
            s.startId = startId;
            s.flags = flags;
            s.args = args;

            queueOrSendMessage(H.SERVICE_ARGS, s);
        }

這裡省略中間訊息傳送的幾個步驟,和第九步類似.

第十三步:handleServiceArgs().

在frameworks/base/core/java/android/app/ActivityThread.java中

 private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
             ...
                if (!data.taskRemoved) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
          .....
    }
s.onStartCommand()這個方法會先回調service的onStart()方法,這樣onStart()和onStartCommand()就被相繼呼叫了,這兩個回撥大家應該也熟悉吧.

這就是啟動service的過程的了.