Service启动流程

先来一张不专业的时序图


Service启动流程.png

基于源码9.0

比如我们在Activity中要启动Service,我们要调用Context的startService方法,这是一个抽象方法,ContextWrapper类继承了Context类实现了startService方法。

public abstract ComponentName startService(Intent service);

ContextWrapper的startService方法。

@Override
 public ComponentName startService(Intent service) {
      //调用mBase的startService方法
      return mBase.startService(service);
}

方法内部调用了mBase的startService方法。mBase的声明类型是Context,运行时类型是一个ContextImpl对象。可以参考从点击桌面应用图标到MainActivity的onResume过程分析文章。

ContextImpl的startService方法

@Override
public ComponentName startService(Intent service) {
    //...
    //调用startServiceCommon方法
    return startServiceCommon(service, false, mUser);
}

ContextImpl的startServiceCommon方法。

private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        //调用ActivityManagerService的startService方法
        ComponentName cn = ActivityManager.getService().startService(mMainThread.getApplicationThread(),
            service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
            getOpPackageName(), user.getIdentifier());
        //...
        return cn;
    } catch(RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

ContextImpl的startService方法内部调用了ActivityManagerService的startService方法来启动Service。

ActivityManagerService的startService方法

@Override
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground,
    String callingPackage, int userId) throws TransactionTooLargeException {
    //...
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
            //注释1. 调用ActiveServices的startServiceLocked方法
            res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid,
                requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

在注释1处,调用了 mServices 的startServiceLocked方法。 mServices的类型是ActiveServices。

ActiveServices的startServiceLocked方法

ComponentName startServiceLocked(IApplicationThread caller, Intent service, 
String resolvedType, int callingPid, int callingUid, boolean fgRequired, 
String callingPackage, final int userId) throws TransactionTooLargeException {
     //...
     //注释2
     ServiceLookupResult res =retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
   //...
   //注释3
   ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
   return cmp;
}

在注释2处,调用retrieveServiceLocked来查找是否有目标service对应的ServiceRecord,查找时先在本地的ServiceMap中查询,如果没有找到,就会调用PackageManagerService去获取目标service对应的信息,并封装到ServiceRecord中,最后将ServiceRecord封装为ServiceLookupResult返回。

继续往下走注释3处,调用了ActiveServices的startServiceInnerLocked方法

ActiveServices的startServiceInnerLocked方法

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg,
    boolean addToStarting) throws TransactionTooLargeException {
    ServiceState stracker = r.getTracker();
    //...
    //注释4,调用bringUpServiceLocked方法
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    if(error != null) {
        return new ComponentName("!!", error);
    }
    //...
    return r.name;
}

ActiveServices的bringUpServiceLocked方法

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
    boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
    //...
    ProcessRecord app;
    if(!isolated) {
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        //注释4,如果要启动的Service所在的进程存在
        if(app != null && app.thread != null) {
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode,
                    mAm.mProcessStats);
                //注释5,调用realStartServiceLocked方法
                realStartServiceLocked(r, app, execInFg);
                return null;
            } catch(TransactionTooLargeException e) {
                throw e;
            } catch(RemoteException e) {
                Slog.w(TAG, "Exception when starting service " + r.shortName, e);
            }
        }
    }
    //...
    //注释6,如果要启动的Service所在的进程不存在,先启动进程
    if(app == null && !permissionsReviewRequired) {
        //注释7
        if((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                hostingType, r.name, false, isolated, false)) == null) {
            //...
        }
        //...
    }
    //...
}

在注释4处,如果要启动的Service所在的进程存在,那么直接调用realStartServiceLocked方法启动目标service。如果要启动的Service所在的进程不存在,那么在注释7处先调用ActivityManagerService的startProcessLocked启动进程。这里我们暂时只看启动的Service所在的进程存在的情况。

ActiveServices的realStartServiceLocked方法

 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
   //...
   //注释8-1处,调用 bumpServiceExecutingLocked 方法,内部会通过一个异步线程的Handler来延迟发送一个消息,用来检测Service的生命周期方法是否执行超时了。
   bumpServiceExecutingLocked(r, execInFg, "create");
  //注释8处,调用ApplicationThread的scheduleCreateService方法
   app.thread.scheduleCreateService(r, r.serviceInfo,
                 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
   //...
   //注释9,
   sendServiceArgsLocked(r, execInFg, true);

}

在realStartServiceLocked方法中,注释8-1处,调用 bumpServiceExecutingLocked 方法,内部会通过一个异步线程的Handler来延迟发送一个消息,用来检测Service的生命周期方法是否执行超时了。

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg,
    String why) {
    if(DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING " + why + " of " +
        r + " in app " + r.app);
    else if(DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
        ">>> EXECUTING " + why + " of " + r.shortName);
  PHASE_THIRD_PARTY_APPS_CAN_START too,
   
    boolean timeoutNeeded = true;
   
    long now = SystemClock.uptimeMillis();
    if(r.executeNesting == 0) {
        r.executeFg = fg;
        ServiceState stracker = r.getTracker();
        if(stracker != null) {
            stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(),
                now);
        }
        if(r.app != null) {
            r.app.executingServices.add(r);
            r.app.execServicesFg |= fg;
            if(timeoutNeeded && r.app.executingServices.size() == 1) {
                scheduleServiceTimeoutLocked(r.app);
            }
        }
    } else if(r.app != null && fg && !r.app.execServicesFg) {
        r.app.execServicesFg = true;
        if(timeoutNeeded) {
            //注释1处,调用 scheduleServiceTimeoutLocked方法。
            scheduleServiceTimeoutLocked(r.app);
        }
    }
    r.executeFg |= fg;
    r.executeNesting++;
    r.executingStart = now;
}
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
    if(proc.executingServices.size() == 0 || proc.thread == null) {
        return;
    }
    Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_TIMEOUT_MSG);
    msg.obj = proc;
    //前台服务20秒,后台服务200秒超时。
    mAm.mHandler.sendMessageDelayed(msg, proc.execServicesFg ?
        SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}

如果onCreate方法在20秒内还没有执行完成,最终会执行ActiveServices的 serviceTimeout 方法。就会弹出ANR弹窗。

void serviceTimeout(ProcessRecord proc) {
    //...
    if(anrMessage != null) {
        //调用 AppErrors的  appNotResponding 方法。
        mAm.mAppErrors.appNotResponding(proc, null, null, false, anrMessage);
    }
}

AppErrors 会发送一个 SHOW_NOT_RESPONDING_UI_MSG 消息, ActivityManagerService 收到后,会执行 AppErrors 的 handleShowAnrUi方法。弹出ANR弹窗。

void handleShowAnrUi(Message msg) {
    Dialog dialogToShow = null;
    synchronized(mService) {
            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg
                .obj;
            final ProcessRecord proc = data.proc;
            if(proc == null) {
                Slog.e(TAG, "handleShowAnrUi: proc is null");
                return;
            }
            if(proc.anrDialog != null) {
                Slog.e(TAG, "App already has anr dialog: " + proc);
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                    AppNotRespondingDialog.ALREADY_SHOWING);
                return;
            }
            Intent intent = new Intent("android.intent.action.ANR");
            if(!mService.mProcessesReady) {
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
                    Intent.FLAG_RECEIVER_FOREGROUND);
            }
            mService.broadcastIntentLocked(null, null, intent, null, null,
                0, null, null, null, AppOpsManager.OP_NONE, null, false,
                false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */
            );
            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
            if(mService.canShowErrorDialogs() || showBackground) {
                dialogToShow = new AppNotRespondingDialog(mService,
                    mContext, data);
                proc.anrDialog = dialogToShow;
            } else {
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                    AppNotRespondingDialog.CANT_SHOW);
                // Just kill the app if there is no dialog to be shown.
                mService.killAppAtUsersRequest(proc, null);
            }
        }
        // If we've created a crash dialog, show it without the lock held
    if(dialogToShow != null) {
        dialogToShow.show();
    }
}

有点扯远了。。。回到ActiveServices的realStartServiceLocked方法的注释8处,调用ApplicationThread的scheduleCreateService方法。

ApplicationThread的scheduleCreateService方法

 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);
 }

scheduleCreateService方法最终还是调用了mH.sendMessage(msg)来发送消息,这个过程就是handler发送消息和处理消息的过程,不再详细叙述,我们直接看mH的handleMessage方法即可。(这里插一句,ApplicationThread是ActivityThread的内部类,mH是ActivityThread的一个成员变量)

public void handleMessage(Message msg) {
    switch(msg.what) {
        case CREATE_SERVICE:
            handleCreateService((CreateServiceData) msg.obj);
            break;
    }
}

handleMessage方法内部调用了ActivityThread的handleCreateService方法

ActivityThread的handleCreateService方法

 private void handleCreateService(CreateServiceData data) {
     //...
     LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo,
         data.compatInfo);
     Service service = null;
     try {
         //构建Service对象
         java.lang.ClassLoader cl = packageInfo.getClassLoader();
         service = packageInfo.getAppFactory().instantiateService(cl, data.info
             .name, data.intent);
     } catch(Exception e) {
         //...
     }
     try {
         //创建service的上下文环境
         ContextImpl context = ContextImpl.createAppContext(this,
             packageInfo);
         context.setOuterContext(service);
         Application app = packageInfo.makeApplication(false,
             mInstrumentation);
         //service初始化
         service.attach(context, this, data.info.name, data.token, app,
             ActivityManager.getService());
         //调用service的onCreate方法
         service.onCreate();
         mServices.put(data.token, service);
         
         try {
             //注释1处
             ActivityManager.getService().serviceDoneExecuting(data.token,
                 SERVICE_DONE_EXECUTING_ANON, 0, 0);
         } catch(RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
         //...
     }
 }

在这个方法中创建了service的实例,创建service的上下文环境,调用service的attach方法来初始化service。并调用了service的onCreate方法了,到这里service已经启动了,那么Service的onStartCommond方法是在哪里调用的呢?在探究之前我们注意一下上面方法的注释1处。

try {
    //注释1处
    ActivityManager.getService().serviceDoneExecuting(data.token,
        SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch(RemoteException e) {
    throw e.rethrowFromSystemServer();
}

调用 ActivityManagerService 的 serviceDoneExecuting 方法,内部会调用 ActiveServices 的 serviceDoneExecutingLocked 方法。 移除掉超时检测的message。

void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
    boolean inDestroying = mDestroyingServices.contains(r);
    if(r != null) {
        //...
        final long origId = Binder.clearCallingIdentity();
        //调用 serviceDoneExecutingLocked 方法。
        serviceDoneExecutingLocked(r, inDestroying, inDestroying);
        Binder.restoreCallingIdentity(origId);
    }
}
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
    boolean finishing) {
   //...
    r.executeNesting--;
    if(r.executeNesting <= 0) {
        if(r.app != null) {
            r.app.execServicesFg = false;
            r.app.executingServices.remove(r);
            if(r.app.executingServices.size() == 0) {
          //移除超时检测的message。      
          mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG,
                    r.app);
            } else if(r.executeFg) {
                // Need to re-evaluate whether the app still needs to be in the foreground.
                for(int i = r.app.executingServices.size() - 1; i >= 0; i--) {
                    if(r.app.executingServices.valueAt(i).executeFg) {
                        r.app.execServicesFg = true;
                        break;
                    }
                }
            }
           
        }
        r.executeFg = false;
       //...
    }
}

让我们回到ActiveServices的realStartServiceLocked方法中的注释9处,这里内部最终会调用Service的onStartCommand方法。

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
   //...
  //注释8处,调用ApplicationThread的scheduleCreateService方法
   app.thread.scheduleCreateService(r, r.serviceInfo,
                 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
   //...
   //注释9处
   sendServiceArgsLocked(r, execInFg, true);

}

在调用完ApplicationThread的scheduleCreateService方法以后,在注释9处调用了sendServiceArgsLocked方法。

ActiveServices的sendServiceArgsLocked方法

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
    boolean oomAdjusted) throws TransactionTooLargeException {
    //...
    //注释10处,
    bumpServiceExecutingLocked(r, execInFg, "start");
    //注释11处,调用ApplicationThread的scheduleServiceArgs方法
    r.app.thread.scheduleServiceArgs(r, slice);
    //...
}

在注释11处,调用了ApplicationThread的scheduleServiceArgs方法

ApplicationThread的scheduleServiceArgs方法

public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
    List < ServiceStartArgs > list = args.getList();
    for(int i = 0; i < list.size(); i++) {
        ServiceStartArgs ssa = list.get(i);
        ServiceArgsData s = new ServiceArgsData();
        s.token = token;
        s.taskRemoved = ssa.taskRemoved;
        s.startId = ssa.startId;
        s.flags = ssa.flags;
        s.args = ssa.args;
        sendMessage(H.SERVICE_ARGS, s);
    }
}

该方法内部也是调用mH.sendMessage(msg)来发送消息,接下来直接看mH的handleMessage方法即可。

public void handleMessage(Message msg) {
    switch(msg.what) {
        case SERVICE_ARGS:
            //调用ActivityThread的handleServiceArgs方法
            handleServiceArgs((ServiceArgsData) msg.obj);
            break;
    }
}

ActivityThread的handleServiceArgs方法

 private void handleServiceArgs(ServiceArgsData data) {
     Service s = mServices.get(data.token);
     if(s != null) {
         try {
             if(data.args != null) {
                 data.args.setExtrasClassLoader(s.getClassLoader());
                 data.args.prepareToEnterProcess();
             }
             int res;
             if(!data.taskRemoved) {
                 //调用Service的onStartCommand方法
                 res = s.onStartCommand(data.args, data.flags, data.startId);
             }
             try {
                 ActivityManager.getService().serviceDoneExecuting(data.token,
                     SERVICE_DONE_EXECUTING_START, data.startId, res);
             } catch(RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
     }
 }

在这里调用了Service的onStartCommand方法。

结尾:整篇文章看下来感觉需要叙述的地方不多,直接一路看代码就行了,哈哈。

参考

  • 《Android进阶解密》
  • startService的Service启动过程分析
  • Android深入四大组件(二)Service的启动过程

你可能感兴趣的:(Service启动流程)