Service源码解析

来源:互联网 发布:数据人生txt全集下载 编辑:程序博客网 时间:2024/06/04 19:20

理解Service

Service是Android四大组件之一。在一般的App开发场景中,它的存在往往是为了保证App切换到后台后,仍然具备处理数据的能力。Service实现了一套异步的跨进程通信模型,通过Binder机制,Service可以优雅的屏蔽跨进程调用的复杂性。一般来说,一个普通的Service运行在当前进程的主线程中,也就是说,如果不开辟线程,把耗时的操作直接甩在Service,那么系统就会赏你一个ANR(application Not Responding)警告。当然,为了方便做耗时操作,SDK层也提供了IntentService,它开辟了一个Work Thread来顺序处理耗时请求,从而避免了阻塞主进程。

Service的本质

Service家族的体系如图所示:

ServiceContext的子类,因此具备了资源访问组件调用的能力,除此之外,它还具有独立的生命周期

运行环境分类,Service可分为:

  • 前台Service
  • 后台Service

前台Service:

通过调用 Service.startForeground(int id, Notification notification) 可以使一个后台Service成为前台Service,并与一个Notification绑定,显示在通知栏。前台Service与后台Service相比,它所在的进程具有更高的优先级,在内存不足时更不容易被系统Kill。

后台Service:

后台Service是指当前没有显示任何界面的Service,处于非前台的Service皆为后台Service,后台Service的优先级低于前台Service,因此在低内存的时候,系统会优先杀掉后台Service。

Service的本身只是一个空壳,它是由系统来维护和管理的。因此想要弄清楚Service的工作原理,就得分析它的启动流程。

Service启动流程分析

Service在客户端的启动入口位于 ContextImpl.startService(Intent intent),因此我们从它入手。

[--> android/app/ContextImpl.java]

   public ComponentName startService(Intent service) {      //如果当前进程是system-server进程,      //调用startService会通过Log打印警告信息。      warnIfCallingFromSystemProcess();      return startServiceCommon(service, mUser);  }

startService 通过调用 startServiceCommon 来完成余下的工作,其代码如下:

private ComponentName startServiceCommon(Intent service, UserHandle user) {      try {          //验证启动目标Service的Intent的合法性          validateServiceIntent(service);          //让Intent为跨进程调用做准备          service.prepareToLeaveProcess();          //调用ActivityManagerNative的startService,          //这实际上是一个远程调用。          ComponentName cn = ActivityManagerNative.getDefault().startService(              mMainThread.getApplicationThread(), service,              service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());          //根据调用结果做对应的处理          if (cn != null) {              if (cn.getPackageName().equals("!")) {                  //不具备调用目标Service的权限                  throw new SecurityException(                          "Not allowed to start service " + service                          + " without permission " + cn.getClassName());              } else if (cn.getPackageName().equals("!!")) {                  // 无法启动目标Service的处理                  throw new SecurityException(                          "Unable to start service " + service                          + ": " + cn.getClassName());              }          }          return cn;      } catch (RemoteException e) {          return null;      }  }
startServiceCommon 首先验证启动目标Service的Intent的合法性,然后调用ActivityManagerNative.startService(...) 来启动Service,最后做了收尾工作。我们接着来到ActivityManagerNative 一探究竟:

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

相信读者看一看代码就清楚,这是一个RPC(Remote Procedure Call)调用,只不过它不是AIDL生成的,而是手工实现的。不过还有个疑问,这里的mRemote是从哪里来的呢?我们定位到取得这个IBinder的位置:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {      protected IActivityManager create() {          IBinder b = ServiceManager.getService("activity");          IActivityManager am = asInterface(b);          return am;      }  };

显然,这个mRemote是通过ServiceManager来维护的,它对应的是ActivityManagerServiceActivityManagerService运行在system-server进程,它实际上是一个进程级别的单例。我们接着分析startService在服务端的实现:

[-->com/android/server/am/ActivityManagerService.java]

 public ComponentName startService(IApplicationThread caller, Intent service,          String resolvedType, int userId) {      enforceNotIsolatedCaller("startService");      // 拒绝包含可能造成内存泄露的文件描述符的Intent      if (service != null && service.hasFileDescriptors() == true) {          throw new IllegalArgumentException("File descriptors passed in Intent");      }      synchronized(this) {          final int callingPid = Binder.getCallingPid();          final int callingUid = Binder.getCallingUid();          final long origId = Binder.clearCallingIdentity();          ComponentName res = mServices.startServiceLocked(caller, service,                  resolvedType, callingPid, callingUid, userId);          Binder.restoreCallingIdentity(origId);          return res;      }  }
ActivityManagerServicestartService被客户端调用后,首先对 Intent 进行检查,然后跳转到调用mServices.startServiceLocked(...)进行余下工作。这里的mService的类型是ActiveServices,它的作用是什么呢?我们来看看这个类包含了哪些函数:


  • ActiveServices的作用显而易见了,它负责处理Service的组件调用维护Service的状态信息。那么startServiceLocked做了哪些事情呢?我们来看代码:

    [-->com/android/server/am/ActiveServices.java]

       ComponentName startServiceLocked(IApplicationThread caller,          Intent service, String resolvedType,          int callingPid, int callingUid, int userId) {      final boolean callerFg;      //检查调用方身份      if (caller != null) {          final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);          //在ActivityManagerService中查询不到调用者,直接抛出异常。          if (callerApp == null) {              throw new SecurityException(                      "Unable to find app for caller " + caller                      + " (pid=" + Binder.getCallingPid()                      + ") when starting service " + service);          }          //判断调用方是前台进程还是后台进程          callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;      } else {          callerFg = true;      }      //检索匹配Service组件信息      ServiceLookupResult res =          retrieveServiceLocked(service, resolvedType,                  callingPid, callingUid, userId, true, callerFg);      //没有匹配到Service组件                  if (res == null) {          return null;      }      if (res.record == null) {          //目标Service组的android:export属性为false          return new ComponentName("!", res.permission != null                  ? res.permission : "private to package");      }      ServiceRecord r = res.record;      if (!mAm.getUserManagerLocked().exists(r.userId)) {          //目标Service组件不存在于任何User          Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId);          return null;      }      //Uri权限检查      NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(              callingUid, r.packageName, service, service.getFlags(), null, r.userId);      //如果目标的Service正在被请求重启,但还未重启,取消这个请求      if (unscheduleServiceRestartLocked(r, callingUid, false)) {          if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);      }      r.lastActivity = SystemClock.uptimeMillis();      r.startRequested = true;      r.delayedStop = false;      r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),              service, neededGrants));      final ServiceMap smap = getServiceMap(r.userId);      boolean addToStarting = false;      if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {          ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);          if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {              if (r.delayed) {                  // 目标Service正在启动中,但还没有启动完成。                  return r.name;              }              if (smap.mStartingBackground.size() >= mMaxStartingBackground) {                  // 该进程有其它组件正在启动,等待它完成后再启动。                  Slog.i(TAG, "Delaying start of: " + r);                  smap.mDelayedStartList.add(r);                  r.delayed = true;                  return r.name;              }              addToStarting = true;          } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {              addToStarting = true;          }       }       return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);  }

    这里解释一下startServiceLocked的工作流程。

    • 检查了调用者的身份,以防止匿名组件攻击
    • 根据客户端传入的数据检索匹配的Service组件信息。
    • 如果检索成功,进一步检查客户端是否有权限调起目标Service。对于在AndroidManifest.xml将 android:export标签设为 false的 Service,只有调用者与目标Service包名相同并且uid相同时才允许调起。
    • 如果目标的Service正在被请求重启,但还未重启,取消这个请求。
    • 如果目标进程已经创建, 但进程有其它组件正在启动,等待它完成后再启动。

在完成以上流程后,它调用了startServiceInnerLocked来完成余下的工作:

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,            ServiceRecord r, boolean callerFg, boolean addToStarting) {        ProcessStats.ServiceState stracker = r.getTracker();        if (stracker != null) {            //跟踪Service的内存消耗            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);        }        r.callStart = false;        synchronized (r.stats.getBatteryStats()) {            //跟踪Service的耗电量            r.stats.startRunningLocked();        }        //通知客户端进程启动Service        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);        if (error != null) {            //启动失败            return new ComponentName("!!", error);        }        if (r.startRequested && addToStarting) {            boolean first = smap.mStartingBackground.size() == 0;            smap.mStartingBackground.add(r);            //设定客户端Service启动超时的时间            r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;            if (first) {                smap.rescheduleDelayedStarts();            }        } else if (callerFg) {            smap.ensureNotStartingBackground(r);        }        return r.name;    }

这个函数中,启动了对Service内存消耗和电量消耗的跟踪,然而到了最关键的一步:调起目标客户端进程来启动Service。它的逻辑实现在 bringUpServiceLocked(...)中,我们来到这个函数:

private final String bringUpServiceLocked(ServiceRecord r,            int intentFlags, boolean execInFg, boolean whileRestarting) {        if (r.app != null && r.app.thread != null) {            //目标Service已经启动            sendServiceArgsLocked(r, execInFg, false);            return null;        }        if (!whileRestarting && r.restartDelay > 0) {            // 如果目标Service正在等待restart完成,什么都不用做,直接返回。            return null;        }        //从正在重启的Service列表中移除目标Service        if (mRestartingServices.remove(r)) {            clearRestartingIfNeededLocked(r);        }        //目标Service不再是delayed状态        if (r.delayed) {           getServiceMap(r.userId).mDelayedStartList.remove(r);            r.delayed = false;        }        // 确保目标Service所属的User处于started状态。        if (mAm.mStartedUsers.get(r.userId) == null) {            String msg = "Unable to launch app "                    + r.appInfo.packageName + "/"                    + r.appInfo.uid + " for service "                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";            Slog.w(TAG, msg);            bringDownServiceLocked(r);            return msg;        }        //Service即将被启动,它所属的Package不能被停止。        try {            AppGlobals.getPackageManager().setPackageStoppedState(                    r.packageName, false, r.userId);        } catch (RemoteException e) {        } catch (IllegalArgumentException e) {            Slog.w(TAG, "Failed trying to unstop package "                    + r.packageName + ": " + e);        }        //检查要启动的Service是否被隔离        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, false);            //目标进程已经创建            if (app != null && app.thread != null) {                try {                    //该进程又多了一个正在运行的Package                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);                    //在客户端创建并启动目标Service                    realStartServiceLocked(r, app, execInFg);                    return null;                } catch (RemoteException e) {                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);                }            }        } else {            app = r.isolatedProc;        }        //目标进程还未创建        if (app == null) {            //通过ActivityManagerService来创建目标进程,调用将阻塞到目标进程创建完成为止            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", r.name, false, isolated, false)) == null) {                //运行到这里说明目标进程创建失败                String msg = "Unable to launch app "                        + r.appInfo.packageName + "/"                        + r.appInfo.uid + " for service "                        + r.intent.getIntent() + ": process is bad";                Slog.w(TAG, msg);                bringDownServiceLocked(r);                return msg;            }            if (isolated) {                r.isolatedProc = app;            }        }        //将目标Service添加到 正在启动Service但未启动完成 的Service列表中        if (!mPendingServices.contains(r)) {            mPendingServices.add(r);        }        if (r.delayedStop) {            r.delayedStop = false;            if (r.startRequested) {                stopServiceLocked(r);            }        }        return null;    }

这个函数又依次做了以下事情:

  • 如果目标Service已经启动,直接sendServiceArgsLocked(...)并返回。
  • 如果目标Service正在被重启,但未重启完成,直接返回。
  • 正在重启的Service列表中移除目标Service。
  • 清除目标Service的delayed状态
  • 如果目标Service所属的User未处于started状态,则不允许启动目标Service。
  • 判断目标Service所处的进程是否已经创建
  • 如果进程已经创建,通过 realStartServiceLocked(...) 通知客户端创建并启动目标Service。
  • 如果进程还未创建,通过 ActivityManagerService的 startProcessLocked(...)来创建目标进程。
  • 将目标Service添加到 正在启动Service但未启动完成 的Service列表中。

故真正创建和启动Service的逻辑在 realStartServiceLocked,我们来到这个函数:

    private final void realStartServiceLocked(ServiceRecord r,            ProcessRecord app, boolean execInFg) throws RemoteException {        if (app.thread == null) {            throw new RemoteException();        }        //填充ServiceRecord        r.app = app;        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();        app.services.add(r);        bumpServiceExecutingLocked(r, execInFg, "create");        mAm.updateLruProcessLocked(app, false, null);        mAm.updateOomAdjLocked();        boolean created = false;        try {            synchronized (r.stats.getBatteryStats()) {                r.stats.startLaunchedLocked();            }            //确保目标App的Dex已经优化完成            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);            //通知客户端的ApplicationThread创建和启动目标Service            app.thread.scheduleCreateService(r, r.serviceInfo,                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                    app.repProcState);            r.postNotification();            created = true;        } catch (DeadObjectException e) {            //在启动Service的过程中,目标进程突然挂了            Slog.w(TAG, "Application dead when creating service " + r);            mAm.appDiedLocked(app);        } finally {            if (!created) {                app.services.remove(r);                r.app = null;                scheduleServiceRestartLocked(r, false);                return;            }        }        //如果Service需要绑定,则绑定目标Service        requestServiceBindingsLocked(r, execInFg);        updateServiceClientActivitiesLocked(app, null, true);        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),                    null, null));        }        //通知客户端ApplicationThread调用目标Service的onStartCommand方法        sendServiceArgsLocked(r, execInFg, true);        if (r.delayed) { getServiceMap(r.userId).mDelayedStartList.remove(r);            r.delayed = false;        }        if (r.delayedStop) {            r.delayedStop = false;            if (r.startRequested) {                stopServiceLocked(r);            }        }    }

代码比较简单,服务端首先填充ServiceRecord中关于目标Service的数据,一切无误后远程调用客户端的scheduleCreateService 函数来创建目标Service。scheduleCreateService 函数位于 android.app.IApplicationThread接口。那么,它又是何物呢?我们来看看这个接口:

[-->androiod/app/IApplicationThread.java]

/** * System private API for communicating with the application.  This is given to * the activity manager by an application  when it starts up, for the activity * manager to tell the application about things it needs to do. */public interface IApplicationThread extends IInterface {    //...}

看注释就很清楚了,它是服务端与客户端通信的桥梁,每一个客户端进程都对应一个IApplicationThread,它的实例会在进程创建后传递到服务端,方便服务端与客户端通信。IApplicationThread接口的部分实现在android.app.ApplicationThreadNative,它仍然是一个抽象类,但是实现了大部分接口中的方法:

[-->androiod/app/ApplicationThreadNative.java]

public abstract class ApplicationThreadNative extends Binder        implements IApplicationThread {       static public IApplicationThread asInterface(IBinder obj) {        if (obj == null) {            return null;        }        IApplicationThread in =            (IApplicationThread) obj.queryLocalInterface(descriptor);        if (in != null) {            return in;        }        return new ApplicationThreadProxy(obj);    }    //...   }

真正完整的是ApplicationThread。它继承了 ApplicationThreadNative ,并实现了所有的抽象方法。它是android.app.ActivityThread 的内部类:

[-->androiod/app/ActivityThread.java]

    public final class ActivityThread {        private class ApplicationThread extends ApplicationThreadNative {            public final void scheduleCreateService(IBinder token,                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {                //...            }            //...        }        //...    }

它的家族体系如图所示:

由前面的分析可知,远程服务端最终会调用 ApplicationThread。scheduleCreateService,那么我们来看看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;            发送请求到Handler            sendMessage(H.CREATE_SERVICE, s);        }

scheduleCreateService中将传递进来的参数包装成了一个CreateServiceData,然后通过sendMessage传递到Handler。 这里的sendMessage的实现如下:

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {        Message msg = Message.obtain();        msg.what = what;        msg.obj = obj;        msg.arg1 = arg1;        msg.arg2 = arg2;        if (async) {            msg.setAsynchronous(true);        }        mH.sendMessage(msg);    }

因此,消息发送到的是ActivityThread中的mHmH的类型为H,继承自Handler:

private class H extends Handler {          public static final int CREATE_SERVICE          = 114;          //...          public void handleMessage(Message msg) {              switch(msg.what) {                case CREATE_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");                    handleCreateService((CreateServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                //...              }          }}

mH收到whatCREATE_SERVICE的Message后,通过 handleCreateService做后续处理:

      private void handleCreateService(CreateServiceData data) {        //停止空闲时自动触发GC的机制        unscheduleGcIdler();        //取得App对应的LoadedApk        LoadedApk packageInfo = getPackageInfoNoCheck(                data.info.applicationInfo, data.compatInfo);        //创建Service                Service service = null;        try {            //通过反射来创建Service实例            java.lang.ClassLoader cl = packageInfo.getClassLoader();            service = (Service) cl.loadClass(data.info.name).newInstance();        } catch (Exception e) {            //...        }        try {            //创建Service的base context            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);            context.setOuterContext(service);            //取得Application            Application app = packageInfo.makeApplication(false, mInstrumentation);            //填充信息到Service            service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());            service.onCreate();            //将创建完成的Service放入mServices这个Map中            mServices.put(data.token, service);            try {               //通知服务端,Service启动完成。                ActivityManagerNative.getDefault().serviceDoneExecuting(                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);            } catch (RemoteException e) {                // nothing to do.            }        } catch (Exception e) {            //...        }    }

代码十分清晰,这个函数做了以下事情:

  • 根据ServiceInfo中的ApplicationInfo取得App对应的LoadedApk。
  • 通过LoadedApk拿到ClassLoader来反射创建目标Service实例。
  • 通过ContextImpl.createAppContext(...)来创建base context。前面分析过,Service继承自ContextWrapper,它的attachBaseContext方法传入的就是这里的context
  • 填充信息到Service,这样Service才能知道自己的身份。
  • 调用Service.onCreate方法。
  • 将创建完成的Service放入mServices这个 Map 中。
  • 通知服务端,Service启动完成。如果前面的过程耗时太长,服务端会认为客户端的Service启动失败。

总结

还记得这句话吗?

Read the fucking source code !!!

本文试图通过对Service启动流程的源码分析来诠释这句话。文章中没有分析bindServiceunbindServicestopService。因为startService的流程与其它三个函数的思想是完全一致的,读者完全可以举一反三。当然,对bindService的机制有兴趣的同学,也可以阅读 Binder 源码分析 这篇文章,理解其中的内容一定会给你带来无尽的收获!



1 0