Service启动过程源码阅读

前言

Service作为四大组件中较常用的组件,通常和各种需要后台执行的业务相关连。Service有两种启动方法startService/bindService,对应的停止操作也分成两种stopService/unbindService,现在来阅读下Android的实现源码深入理解Service的工作原理过程。

startService/StopService分析

startService方法并没有被定义在Activity中,而是定义在ContextImpl这个类里,查看startService源码会发现实际上调用的是startServiceCommon这个方法实现。

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, false, mUser);
}

startServiceCommon方法直接调用了ActivityManager向ActivityManagerService(AMS)服务请求创建新的服务。AMS服务通过mMainThread.getApplicationThread()这个binder对象通知ActivityThread要创建一个新的Service。

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

查看ActivityThread里的H类里处理CREATE_SERVICE消息的回调调用了handleCreateService方法。

private void handleCreateService(CreateServiceData data) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();

    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;

    // 通过反射生成Service对象
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }

    try {
        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);

        // 获取Application对象并且attach到Service中
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());

        // 执行Service的onCreate方法
        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);
        }
    }
}

相比较创建Activity的过程创建Service要简单的多,实现并不复杂,接着ActivityManager.getService().serviceDoneExecuting()通知AMS当前的Service已经启动,这个时候AMS会继续发送SERVICE_ARGS消息过来,H类里的对应处理方法为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();
            }

            // 调用onStartCommand方法
            int res;
            if (!data.taskRemoved) {
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }

            QueuedWork.waitToFinish();

            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            ensureJitEnabled();
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to start service " + s
                        + " with " + data.args + ": " + e.toString(), e);
            }
        }
    }
}

handleServiceArgs方法会调用已经创建启动的Service对象的onStartCommand方法。Service启动过程比起Activity的启动简明了很多,现在来看Service.stopService操作。

@Override
public boolean stopServiceAsUser(Intent service, UserHandle user) {
    return stopServiceCommon(service, user);
}

private boolean stopServiceCommon(Intent service, UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        int res = ActivityManager.getService().stopService(
            mMainThread.getApplicationThread(), service,
            service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
        if (res < 0) {
            throw new SecurityException(
                    "Not allowed to stop service " + service);
        }
        return res != 0;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

stopServiceCommon里也是调用ActivityManager向AMS发送stopService请求,在ActivityThread里查看STOP_SERVICE消息里回调了handleStopService((IBinder)msg.obj);方法。

private void handleStopService(IBinder token) {
    Service s = mServices.remove(token);
    if (s != null) {
        try {
            if (localLOGV) Slog.v(TAG, "Destroying service " + s);
            s.onDestroy();
            s.detachAndCleanUp();
            Context context = s.getBaseContext();
            if (context instanceof ContextImpl) {
                final String who = s.getClassName();
                ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
            }

            QueuedWork.waitToFinish();

            try {
                ActivityManager.getService().serviceDoneExecuting(
                        token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to stop service " + s
                        + ": " + e.toString(), e);
            }
            Slog.i(TAG, "handleStopService: exception for " + token, e);
        }
    } else {
        Slog.i(TAG, "handleStopService: token=" + token + " not found.");
    }
    //Slog.i(TAG, "Running services: " + mServices);
}

handleStopService方法主要调用了Service的onDestroy回调并且通知AMS自己被停止。

bindService/unbindService

ContextImpl里的各种bindService最终调用的是bindServiceCommon这个方法的实现,如果调用过bindService应该知道其中会传递一个ServiceConnection对象,这个对象负责将与服务相关的binder对象返回到客户端。

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
    // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
    IServiceConnection sd;
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (mPackageInfo != null) {
        // 创建服务派发器对象
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, 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(this);

        // 通过ActivityManager向AMS请求绑定到Service
        int res = ActivityManager.getService().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 e.rethrowFromSystemServer();
    }
}

这里使用ServiceDispather对象包装了ServiceConnection对象,并且将ServiceDispatcher对象传递到了AMS端。

ServiceDispatcher(ServiceConnection conn,
                Context context, Handler activityThread, int flags) {
    mIServiceConnection = new InnerConnection(this);
    mConnection = conn;
    mContext = context;
    mActivityThread = activityThread;
    mLocation = new ServiceConnectionLeaked(null);
    mLocation.fillInStackTrace();
    mFlags = flags;
}

ServiceDispatcher对象内部包含了一个InnerConnection也是一个Binder,AMS就是通过这个Binder对象将启动服务的Binder传递回客户端。

private static class InnerConnection extends IServiceConnection.Stub {
    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);
        }
    }
}

在AMS启动后同时会调用ApplicationThread回调通知ActivityThread绑定Service成功,这时后Service对应的binder对象会同时发布到ActivityManagerService里。

private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (DEBUG_SERVICE)
        Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            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);
                }
                ensureJitEnabled();
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to bind to service " + s
                        + " with " + data.intent + ": " + e.toString(), e);
            }
        }
    }
}

当AMS通知connected调用的时候会直接调用ServiceDispatcher.connected方法,这个方法里又会调用doConnected方法,在最后会调用ServiceConnection.onServiceConnected将Service对应的Binder返回到客户端中。

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

    ....
    if (dead) {
        mConnection.onBindingDied(name);
    }
    // If there is a new service, it is now connected.
    if (service != null) {
        mConnection.onServiceConnected(name, service);
    }
}

接着查看unbindService方法直接调用ActivityManager向AMS发送unbindService的请求。

@Override
public void unbindService(ServiceConnection conn) {
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (mPackageInfo != null) {
        IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
                getOuterContext(), conn);
        try {
            ActivityManager.getService().unbindService(sd);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    } else {
        throw new RuntimeException("Not supported in system context");
    }
}

AMS在ApplicationThread返回UNBIND_SERVICE消息,在H的消息回调中调用了handleUnbindService,最后调用Service.onUnbind回调。

private void handleUnbindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            boolean doRebind = s.onUnbind(data.intent);
            try {
                if (doRebind) {
                    ActivityManager.getService().unbindFinished(
                            data.token, data.intent, doRebind);
                } else {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to unbind to service " + s
                        + " with " + data.intent + ": " + e.toString(), e);
            }
        }
    }
}

总结

Service启动过程相对Activity简单了很多,startService直接向ActivityManagerService(AMS)发送启动Service的请求AMS创建了Service内核数据结构之后就发送CREATE_SERVICE通知ActivityThread启动Service,开始执行Service.onCreate方法,执行完成后通知AMS已经启动成功,AMS再发送SERVICE_ARGS回调Service.onStartCommand方法,以后再执行startService都AMS都会只发送SERVICE_ARGS通知,stopService会通过ActivityManager告知AMS Activity要停止,AMS会处理内核里的Activity数据结构,之后在发送SERVICE_STOP通知给ActivityThread,最后调用Service.onDestroy方法。

bindService相对来说又比startService多了一个返回Service的binder对象回调功能。ActivityManager请求bindService是会将ApplicationThread和ServiceDispatcher传递给AMS,AMS首先发送给ActivityThread SERVICE_CREATE通知,Service执行onCreate方法,通知AMS Service创建成功,AMS再发送SERVICE_BIND消息给ActivityThread这时回调onBind方法,再通知AMS绑定操作成功,AMS通过InnerConnection向ServiceDispatcher发送onConnected回调,ServiceDispatcher内部再调用ServiceConnection将Service绑定的binder回调给客户端。unBindService基本和stopService一致,不再赘述。

猜你喜欢

转载自blog.csdn.net/xingzhong128/article/details/80026364