首页 > 安全资讯 >

Android 应用五大核心块 --- Service后台服务

12-03-21

Android 应用五大核心块 --- Service后台服务概念:Service:后台服务,用于将一些计算或常用系统通用功能放在一个独立的进程中进行处理,这样主进程可以全力并快速处理界面响应,提高用户体验效果。下面以 ...

Android 应用五大核心块 --- Service后台服务

概念:
Service:后台服务,用于将一些计算或常用系统通用功能放在一个独立的进程中进行处理,这样主进程可以全力并快速处理界面响应,提高用户体验效果。

下面以 packages\apps\Phone 应用举例说明:

编写应用时定义:AndroidManifest.xml
<!-- CDMA Emergency Callback Mode -->
   <service android:name="EmergencyCallbackModeService">
  </service>

EmergencyCallbackModeService.java 中如此定义:
public class EmergencyCallbackModeService extends Service
继承于 android.app.Service 类,重载其父类函数,此Service启动点:

PhoneAppBroadcastReceiver @ PhoneApp.java
// Start Emergency Callback Mode service
if (intent.getBooleanExtra("phoneinECMState", false)) {
    context.startService(new Intent(context,
            EmergencyCallbackModeService.class));
}
                   
ok, 表时Servie服务是利用 startService 函数而利用 Intent 类启动的。


几个类的关系如下:
public abstract class Context

public class ContextImpl extends Context
public class ContextWrapper extends Context


public class ContextThemeWrapper extends ContextWrapper             
public class Activity extends ContextThemeWrapper
 
即Activity继承了ContextWrapper类,而在ContextWrapper类中,实现了startService函数。在ContextWrapper类中,有一个成员变量mBase,它是一个ContextImpl实例,而ContextImpl类和ContextWrapper类一样继承于Context类,ContextWrapper类的startService函数最终过调用ContextImpl类的startService函数来实现。

既然理清楚了这几者关系,下面开始按照代码走一下完整的流程:

=========================主进程调用到ActivityManagerService进程中,完成新进程的创建============
startService @ ContextImpl.java
public ComponentName startService(Intent service) {
    ComponentName cn = ActivityManagerNative.getDefault().startService(
        mMainThread.getApplicationThread(), service,
        service.resolveTypeIfNeeded(getContentResolver()));
}
这里利用Binder进行通讯:
startService @ ActivityManagerNative.java
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
这里是利用 Binder 驱动程序发送请求给报务端,即此时的 mRemote(Binder对象)就是 ActivityManagerService
而ActivityManagerService这边就是等待Client的请求:


startService @ ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType) {

// 利用 Binder 对象获取到 pid,uid 等参数
      final int callingPid = Binder.getCallingPid();
      final int callingUid = Binder.getCallingUid();
      final long origId = Binder.clearCallingIdentity();
      ComponentName res = startServiceLocked(caller, service,
              resolvedType, callingPid, callingUid);
}
caller、service和resolvedType分别对应ActivityManagerProxy.startService传进来的三个参数
-->
这里简单看一下调用逻辑:
startServiceLocked() --> bringUpServiceLocked() --> startProcessLocked:

private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
....
int pid = Process.start("android.app.ActivityThread",
                    mSimpleProcessManagement ? app.processName : null, uid, uid,
                    gids, debugFlags, null);
...
}

start @ Process.java
public static final int start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags,
                              String[] zygoteArgs)
{
if (supportsProcesses()) {
return startViaZygote(processClass, niceName, uid, gid, gids,
                        debugFlags, zygoteArgs);
}else {

// Running in single-process mode
Process.invokeStaticMain(processClass);          
}
}


这里通过函数 openZygoteSocketIfNeeded 与 Zygote Socket 之间进行通讯,fork出一个新的
进程,然后导入 android.app.ActivityThread 线程,执行其main函数。

=========新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息=======

main @ ActivityThread.java
public static final void main(String[] args) {
// 这里设定 Activity 的主 Looper
    Looper.prepareMainLooper();


// 创建 ActivityThread 线程实例www.2cto.com
    ActivityThread thread = new ActivityThread();
   
    thread.attach(false);

    Looper.loop();
}
这里在新的进程中运行了,这里就是用来启动服务的。在Android应用程序中,每一个进程对应一个ActivityThread实例,所以,这个函数会创建一个thread实例,然后调用ActivityThread.attach函数进一步处理。

attach @ ActivityThread.java
private final void attach(boolean system){
...
IActivityManager mgr = ActivityManagerNative.getDefault();

  try {
      mgr.attachApplication(mAppThread);
  } catch (RemoteException ex) {
  }
}

哟,,这里又要调用 ActivityManagerNative ,嗯,根据前面的分析大家应该知道了吧:)
attachApplication @ ActivityManagerNative.java
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
利用 Binder 对象调用到服务端:
attachApplication @ ActivityManagerService.java
attachApplicationLocked

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
// Find any services that should be running in this process...
        if (!badApp && mPendingServices.size() > 0) {
  realStartServiceLocked(sr, app);
        }
}
-->
这里开始时利用mPidsSelfLocked变量将进程的一些信息存入了ServiceRecord类
app.thread.scheduleCreateService(r, r.serviceInfo);
scheduleCreateService @ ApplicationThreadNative.java
public final void scheduleCreateService(IBinder token, ServiceInfo info){
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
}
通过Binder驱动程序回到新进程的ApplicationThread对象中去执行scheduleCreateService函数

============== 从ActivityManagerService进程又回到新进程中,最终将服务启动起来 =============

scheduleCreateService @ ActivityThread.java
public final void scheduleCreateService(IBinder token,
        ServiceInfo info) {
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;

    queueOrSendMessage(H.CREATE_SERVICE, s);
}
通过 Handler 发送消息,在此文件中的 main 函数中调用 Looper.prepareMainLooper(); 表明这是一个Activity 主线程,使用 main looper ,由 Looper.java 中的 loop 进行循环消息处理。

处理消息函数:
handleMessage @ ActivityThread.java
public void handleMessage(Message msg) {
      case CREATE_SERVICE:
          handleCreateService((CreateServiceData)msg.obj);
          break;
      ...
}
-->
private final void handleCreateService(CreateServiceData data) {
Service service = null;

// 通过强制类型转换得到一个Service类实例
    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    service = (Service) cl.loadClass(data.info.name).newInstance();
    ...
    service.onCreate();
}

根据最前面讲的,自己的服务类必须要继承于Service类,那么将运行自已Service的onCreate()函数.
public class EmergencyCallbackModeService extends Service {

@Override
public void onCreate() {
        // Check if it is CDMA phone
...
}

总结如下:
如此Android系统在新进程中启动服务的过程就分析完成,主要经历如下几个主要过程:
1、主进程调用到ActivityManagerService进程中,完成新进程的创建
2、新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息
3、从ActivityManagerService进程又回到新进程中,最终将服务启动起来
其中上面通过三次Binder进程间通讯完成启动过程。

最后以一个简图说明一下:

  


摘自  andyhuabing的专栏 

相关文章
最新文章
热点推荐