美文网首页随笔-生活工作点滴
Android源码学习-Service启动流程浅析(Androi

Android源码学习-Service启动流程浅析(Androi

作者: m1Ku | 来源:发表于2019-07-05 17:52 被阅读4次

介绍

Service的工作状态分为启动状态和绑定状态,启动状态主要用于后台计算,绑定状态可以用于其他组件和Service的交互。分别看一下这两种状态的启动流程。

Intent serviceIntent = new Intent(this, SampleService.class);
//启动Service
startService(serviceIntent);
//绑定Service
bindService(serviceIntent,mServiceConnection,BIND_AUTO_CREATE);

private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

源码分析

Service启动过程

调用ContextWrapper的startService方法

@Override
public ComponentName startService(Intent service) {
    return mBase.startService(service);
}

mBase是Context的实现类ContextImpl

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        //...
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        //...
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

这里调用了ActivityManagerService的startService方法

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
        //...
  res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
  //...
}

调用ActiveServices的startServiceLocked

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {
    //...
  ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
  return cmp;     
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
                                      boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
  String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
  //...
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
  throws TransactionTooLargeException {
  //...
  realStartServiceLocked(r, app, execInFg);
  //...
}
private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
   //...
  app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
  //...
  sendServiceArgsLocked(r, execInFg, true);
  //...
}

我们又看到了app.thread对象,跟Activity的启动类似的,这里又来到了ApplicationThread中

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

这里也是发送一个启动Service的消息到H,我们直接看对该消息的处理

public void handleMessage(Message msg) {
//...
 case CREATE_SERVICE:
    //...
    handleCreateService((CreateServiceData)msg.obj);
    //...
    break;
}   
private void handleCreateService(CreateServiceData data) {
  //...
  java.lang.ClassLoader cl = packageInfo.getClassLoader();
  service = (Service) cl.loadClass(data.info.name).newInstance();
  //...
  ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
  context.setOuterContext(service);
  Application app = packageInfo.makeApplication(false, mInstrumentation);
  service.attach(context, this, data.info.name, data.token,app,ActivityManager.getService());
  service.onCreate();
  mServices.put(data.token, service);
  //...
}

在handleCreateService方法中,首先使用类加载器创建Service,然后创建了ContextImpl对象,同样的也调用了Service的attach方法为Service中关键参数赋值,最后回调了onCreate方法。

在realStartServiceLocked中sendServiceArgsLocked还会调用ApplicationThread的scheduleServiceArgs方法,最后又调用了handleServiceArgs方法

private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
  //...
    res = s.onStartCommand(data.args, data.flags, data.startId);
  //...
}

在Service启动后,这里又回调了onStartCommand方法,到这里Service启动流程就结束了。

Service绑定流程

@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}

具体实现同样是交给了ContextImpl

@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
            Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
//...
  if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
//...
    int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
//...
}

这里将ServiceConnection对象转换为ServiceDispatcher.InnerConnection,由于服务绑定可能是跨进程的,因此ServiceConnection需要借助Binder让远程服务端回调自己的方法,而ServiceDispatcher.InnerConnection就充当这个角色。

调用ActivityManagerService的bindService

public int bindService(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, int flags, String callingPackage,
                       int userId) throws TransactionTooLargeException {
  //...
   synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
}

调用ActiveServices的bindServiceLocked

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, final IServiceConnection connection, int flags,
        String callingPackage, final int userId) throws TransactionTooLargeException {
        //...
        bringUpServiceLocked(serviceRecord,serviceIntent.getFlags(),callerFg, false, false);                                                                  
        //...
        requestServiceBindingLocked(s, b.intent, callerFg, true);
  //
 }

bringUpServiceLocked启动Service已经分析了,会经过AMS完成Service的创建。这里看requestServiceBindingLocked

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.repProcState);
  //...
}

调用ApplicationThread的scheduleBindService,这里还是发送消息让Handler处理,我们直接看处理的方法

private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        IBinder binder = s.onBind(data.intent);
        ActivityManager.getService().publishService(data.token, data.intent, binder);                          
      //...
   }
  //...
}

这里调用Service的onBind方法,然后调用AMS的publishService

public void publishService(IBinder token, Intent intent, IBinder service) {
    //...
    mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    //...
}

调用ActiveServices的publishServiceLocked

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
  //...
  c.conn.connected(r.name, service, false);
  //...
}

c.conn是ServiceDispatcher.InnerConnection对象

public void connected(ComponentName name, IBinder service, boolean dead)
        throws RemoteException {
    LoadedApk.ServiceDispatcher sd = mDispatcher.get();
    if (sd != null) {
        sd.connected(name, service, dead);
    }
}

调用ServiceDispatcher的connected

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

这里mActivityThread是ActivityThread里的H这个Handler,RunConnection是一个Runnable,他的run方法

public void run() {
    if (mCommand == 0) {
        doConnected(mName, mService, mDead);
    } else if (mCommand == 1) {
        doDeath(mName, mService);
    }
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
//...
    if (service != null) {
        mConnection.onServiceConnected(name, service);
    }
//...
}

最后回到了ServiceConnection的onServiceConnected方法,且他运行在主线程中,这样Service的绑定过程就完成了。

相关文章

网友评论

    本文标题:Android源码学习-Service启动流程浅析(Androi

    本文链接:https://www.haomeiwen.com/subject/gltyhctx.html