android中service的两种实现方法(android中service的实现方法)

1:前言

Service是Android中的四大组件之一,日常开发中我们经常会使用startService之类的方法来启动Service,那这个方法调用的底层原理是什么呢?Android系统是如何启动起来Service的呢?本文我们从源码出发,介绍一下Android中的Service是如何启动Service的,本文的结构如下:

2:源码分析

2.1:ContextImpl.startService&startForegroundService:应用层调用的入口

我们调用
   startService/startForegroundService之后,会调用到android.app.ContextImpl#
   startService/startForegroundService:

class ContextImpl extends Context {  
    @Override
    public ComponentName startService(Intent service) {
        return startServiceCommon(service, false, mUser);
    }
    @Override
    public ComponentName startForegroundService(Intent service) {
        return startServiceCommon(service, true, mUser);
    }

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
         ...
    }
}

可以看到,startService和startForegroundService最终调用的都是startServiceCommon这个方法,唯一不同的是第二个参数requireForeground的值不一样,用来标识当前Service是否是前台Serivice,我们来看startServiceCommon的具体实现:

class ContextImpl extends Context {  
   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(), getAttributionTag(), user.getIdentifier());
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException(
                            "Not allowed to start service "   service
                              " without permission "   cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(
                            "Unable to start service "   service
                              ": "   cn.getClassName());
                } else if (cn.getPackageName().equals("?")) {
                    throw new IllegalStateException(
                            "Not allowed to start service "   service   ": "   cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

可以看到,核心是调用到了
   ActivityManager.getService().startService()方法进行Service的启动,即AMS中,我们来看一下AMS中是如何启动Service的.

2.2:ActivityManagerService.startService:执行前置判断,满足启动service的条件的话触发真正startService的逻辑

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
      final ActiveServices mServices;

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

可以看到,最终调用到了
   ActiveServices.startServiceLocked()中:

//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            @Nullable String callingFeatureId, final int userId)
            throws TransactionTooLargeException {
        return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
                callingPackage, callingFeatureId, userId, false);
    }

      ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            @Nullable String callingFeatureId, final int userId,
            boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
          /**
          *对当前Service的启动进行判断,看下Service启动的限制(比如权限、前后台等是否满足)
          **/
          ...
        //启动Service
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        if (!r.mAllowWhileInUsePermissionInFgs) {
            r.mAllowWhileInUsePermissionInFgs =
                    shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid,
                            callingUid, service, r, allowBackgroundActivityStarts);
        }
        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);
        ...
        return r.name;
    }
}

核心是调用到了
   ActiveServices.bringUpServiceLocked.

2.3:ActiveServices.bringUpServiceLocked:根据进程&线程是否存在执行不同操作

//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
       private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
             //如果进程和线程已经不为空,说明该Service已经create了,直接调用sendServiceArgsLocked
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        ...
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
        ProcessRecord app;
        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
           //如果进程已经在了,调用realStartServiceLocked进行start service
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service "   r.shortInstanceName, e);
                }
                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } 
        // 如果进程还没启动,调用mAm.startProcessLocked启动进程
        if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
              //埋下异常
              bringDownServiceLocked(r);
              ...
            }
        }
                //将当前ServiceRecord加到mPendingServices里,
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
        ...
    }
}

在《Android的进程》一文中我们介绍过,最终进程起来之后会执行
   ActivityManagerService.attachApplication-->
   ActivityManagerService.attachApplicationLocked:

public class ActivityManagerService extends IActivityManager.Stub{
        public ActivityTaskManagerInternal mAtmInternal;
        final ActiveServices mServices;
        private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
                    int pid, int callingUid, long startSeq) {
                     boolean badApp = false;
                boolean didSomething = false;
                // 先尝试启动Activity
                if (normalMode) {
                    try {
                        didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
                    } catch (Exception e) {
                        Slog.wtf(TAG, "Exception thrown launching activities in "   app, e);
                        badApp = true;
                    }
                }
                //Activity启动没问题,尝试启动Service
                if (!badApp) {
                    try {
                        didSomething |= mServices.attachApplicationLocked(app, processName);

                    } catch (Exception e) {
                        Slog.wtf(TAG, "Exception thrown starting services in "   app, e);
                        badApp = true;
                    }
                }
        }
}

可以看到,先启动了Activity,如果Activity的启动过程中没有出错,就启动Service即调用
   ActiveServices.attachApplicationLocked.

2.4:ActiveServices.attachApplicationLocked:进程启动完成,继续启动service

public final class ActiveServices {
            boolean attachApplicationLocked(ProcessRecord proc, String processName){
        boolean didSomething = false;
        // Collect any services that are waiting for this process to come up.
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i  ) {
                    sr = mPendingServices.get(i);
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }
                    mPendingServices.remove(i);
                    i--;
                    proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
                            mAm.mProcessStats);
                    //核心操作是调用realStartServiceLocked
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                    if (!isServiceNeededLocked(sr, false, false)) {
                        // We were waiting for this service to start, but it is actually no
                        // longer needed.  This could happen because bringDownServiceIfNeeded
                        // won't bring down a service that is pending...  so now the pending
                        // is done, so let's drop it.
                        bringDownServiceLocked(sr);
                    }
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception in new application when starting service "
                          sr.shortInstanceName, e);
                throw e;
            }
        }
        // Also, if there are any services that are waiting to restart and
        // would run in this process, now is a good time to start them.  It would
        // be weird to bring up the process but arbitrarily not let the services
        // run at this point just because their restart time hasn't come up.
        if (mRestartingServices.size() >0) {
            ServiceRecord sr;
            for (int i=0; i<mRestartingServices.size(); i  ) {
                sr = mRestartingServices.get(i);
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                        || !processName.equals(sr.processName))) {
                    continue;
                }
                mAm.mHandler.removeCallbacks(sr.restarter);
                mAm.mHandler.post(sr.restarter);
            }
        }
        return didSomething;
    }

}

可以看到最终调用到了realStartServiceLocked.

2.5:ActiveServices.realStartServiceLocked:先埋炸弹,然后触发service启动

public final class ActiveServices {
        /**
     * Note the name of this method should not be confused with the started services concept.
     * The "start" here means bring up the instance in the client, and this method is called
     * from bindService() as well.
     */
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (DEBUG_MU)
            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = "   r.appInfo.uid
                      ", ProcessRecord.uid = "   app.uid);
        r.setProcess(app);
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
                //调用ProcessRecord.startService,实质是将此处的ServiceRecord add到ProcessRecord.mServices中
        final boolean newService = app.startService(r);
          //埋下ANR炸弹
        bumpServiceExecutingLocked(r, execInFg, "create");
        //调整进程的优先级
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
        boolean created = false;
           ...
           //最终触发service.onCreate
          app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());
          ...
         //bind service
        requestServiceBindingsLocked(r, execInFg);
        updateServiceClientActivitiesLocked(app, null, true);
        if (newService && created) {
            app.addBoundClientUidsOfNewService(r);
        }
        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null, 0));
        }
                //拉起timeout,最终调用Service.onStartCommand
        sendServiceArgsLocked(r, execInFg, true);
        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): "   r);
            getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }
        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                        "Applying delayed stop (from start): "   r);
                stopServiceLocked(r);
            }
        }
    }

2.6:ActiveServices.bumpServiceExecutingLocked:埋下ANR炸弹(SERVICE_TIMEOUT_MSG)

public final class ActiveServices {
      // How long we wait for a service to finish executing.
    static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
    // How long we wait for a service to finish executing.
    static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

    // How long the startForegroundService() grace period is to get around to
    // calling startForeground() before we ANR   stop it.
    static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;

        private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
        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) {
                      //启动延迟炸弹(触发ANR)
                    scheduleServiceTimeoutLocked(r.app);
                }
            }
        } else if (r.app != null && fg && !r.app.execServicesFg) {
            r.app.execServicesFg = true;
            if (timeoutNeeded) {
                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;
             //前台Service延迟SERVICE_TIMEOUT(20s),后台Service延迟SERVICE_BACKGROUND_TIMEOUT(200s)
        mAm.mHandler.sendMessageDelayed(msg,
                proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
    }
}

2.7:ActivityThread.scheduleCreateService:触发Service.onCreate

可以看到这里主要是发送了一个CREATE_SERVICE的Message消息:

//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler 
    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);
    }

     public void handleMessage(Message msg) {
         ...
        case CREATE_SERVICE:
             handleCreateService((CreateServiceData)msg.obj);
             break;
     ...
   }
   public static final int SERVICE_DONE_EXECUTING_ANON = 0;
   @UnsupportedAppUsage
    private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
              //实例化Service的对象
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
            // Service resources must be initialized with the same loaders as the application
            // context.
            context.getResources().addLoaders(
                    app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
            context.setOuterContext(service);
              //调用Service.attach
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
              //调用Service.onCreate
            service.onCreate();
            mServices.put(data.token, service);
          //通知ActivityManagerService,Service启动完成,拆除预埋的炸弹,调整进程优先级
                       ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (Exception e) {
        }
    }
}
//frameworks/base/core/java/android/app/AppComponentFactory.java
class AppComponentFactory{
    public @NonNull Service instantiateService(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Service) cl.loadClass(className).newInstance();
    }
}

2.8:ActivityManagerService.serviceDoneExecuting:拆除预埋的炸弹

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
      final ActiveServices mServices;
      public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                Slog.e(TAG, "serviceDoneExecuting: Invalid service token="   token);
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
        }
    }
}

最终调用到了
   ActiveServices.serviceDoneExecutingLocked:

//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
        void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
          if (r != null) {
          ...
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
        }
    }

      private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
            boolean finishing) {
          //拆除预埋的SERVICE_TIMEOUT_MSG炸弹
            mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
          //调整进程优先级
           mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
      }
}

2.9:ActiveServices.sendServiceArgsLocked:启动延迟任务,埋下ANR和崩溃炸弹、触发onstartCommand

public final class ActiveServices {
      final ActivityManagerService mAm;

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
                boolean oomAdjusted) throws TransactionTooLargeException {
            final int N = r.pendingStarts.size();
            if (N == 0) {
                return;
            }
            ArrayListargs = new ArrayList<>();
            while (r.pendingStarts.size() > 0) {
                ServiceRecord.StartItem si = r.pendingStarts.remove(0);
                //核心操作,埋下ANR炸弹,上面介绍过了
                bumpServiceExecutingLocked(r, execInFg, "start");
                if (!oomAdjusted) {
                    oomAdjusted = true;
                    //更新进程优先级
                    mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
                }
                if (r.fgRequired && !r.fgWaiting) {
                    if (!r.isForeground) {
                      //对于前台Service,启动延迟任务,检测Service调用了startForeground,否则会崩溃
                        scheduleServiceForegroundTransitionTimeoutLocked(r);
                    } else {
                        r.fgRequired = false;
                    }
                }
                int flags = 0;
                if (si.deliveryCount > 1) {
                    flags |= Service.START_FLAG_RETRY;
                }
                if (si.doneExecutingCount > 0) {
                    flags |= Service.START_FLAG_REDELIVERY;
                }
                args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
            }
            ParceledListSliceslice = new ParceledListSlice<>(args);
            slice.setInlineCountLimit(4);
            Exception caughtException = null;
            try {
              //调用ActivityThread.scheduleServiceArgs,最终执行Service.onstartCommand
                r.app.thread.scheduleServiceArgs(r, slice);
            }
        }
        // How long the startForegroundService() grace period is to get around to
        // calling startForeground() before we ANR   stop it.
        static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
        void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
            if (r.app.executingServices.size() == 0 || r.app.thread == null) {
                return;
            }
            Message msg = mAm.mHandler.obtainMessage(
                    ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
            msg.obj = r;
            r.fgWaiting = true;
          //延迟10s发送,埋下崩溃炸弹
            mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT);
        }
}

2.10:ActivityThread.scheduleServiceArgs:触发onStartcommand

 //frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler 
         public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
            Listlist = 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);
            }
        }
      public void handleMessage(Message msg) {
         ...
        case SERVICE_ARGS:
             handleServiceArgs((ServiceArgsData)msg.obj);
             break;
     ...
   }
    private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        ...
          //调用onStartcommand
          res = s.onStartCommand(data.args, data.flags, data.startId);
            //拆除预埋的炸弹
                 ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            ...
    }
}

核心是发送了一个SERVICE_ARGS的message。

2.11:ActivityManagerService.handleMessage:处理不同的message(炸弹)

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
     final MainHandler mHandler;
   final ActiveServices mServices;
   final class MainHandler extends Handler {
        public MainHandler(Looper looper) {
            super(looper, null, true);
        }
        @Override
        public void handleMessage(Message msg) {
          switch (msg.what) {
                            case SERVICE_TIMEOUT_MSG: {
                        //抛出anr
                        mServices.serviceTimeout((ProcessRecord)msg.obj);
                    } 
                  break;
              case SERVICE_FOREGROUND_TIMEOUT_MSG: {
                        //抛出anr
                        mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
                    } 
                  break;
              case SERVICE_FOREGROUND_CRASH_MSG: {
                  //引发crash,报错Context.startForegroundService() did not then call Service.startForeground() xxx
                    mServices.serviceForegroundCrash(
                        (ProcessRecord) msg.obj, msg.getData().getCharSequence(SERVICE_RECORD_KEY));
                } 
                break;
          }
        }
   }
}

2.12:Service.startFroeground:前台Service必须调用,展示通知,解除崩溃炸弹

对于前台Service,必须在Service启动之后手动调用Service.startFroeground,否则会触发上文中的崩溃炸弹:

//frameworks/base/core/java/android/app/Service.java
public abstract class Service extends ContextWrapper {
      public final void startForeground(int id, Notification notification) {
        try {
            mActivityManager.setServiceForeground(
                    new ComponentName(this, mClassName), mToken, id,
                    notification, 0, FOREGROUND_SERVICE_TYPE_MANIFEST);
        } catch (RemoteException ex) {
        }
    }
}

最终调用到了AMS.setServiceForeground:

 //frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{ 
   final ActiveServices mServices;
  @Override
    public void setServiceForeground(ComponentName className, IBinder token,
            int id, Notification notification, int flags, int foregroundServiceType) {
        synchronized(this) {
            mServices.setServiceForegroundLocked(className, token, id, notification, flags,
                    foregroundServiceType);
        }
    }
}

核心是调用
   ActiveServices.setServiceForegroundLocked.

2.13:ActiveServices.setServiceForegroundLocked:发送通知,取消崩溃

//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
    public void setServiceForegroundLocked(ComponentName className, IBinder token,
            int id, Notification notification, int flags, int foregroundServiceType) {
        final int userId = UserHandle.getCallingUserId();
        final long origId = Binder.clearCallingIdentity();
        try {
            ServiceRecord r = findServiceLocked(className, token, userId);
            if (r != null) {
                setServiceForegroundInnerLocked(r, id, notification, flags, foregroundServiceType);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
   /**
     * @param id Notification ID.  Zero === exit foreground state for the given service.
     */
    private void setServiceForegroundInnerLocked(final ServiceRecord r, int id,
            Notification notification, int flags, int foregroundServiceType) {
      //id不可为0
      if (id != 0) {
         //notification不可为空
             if (notification == null) {
                throw new IllegalArgumentException("null notification");
            }
                ...
                if (r.fgRequired) {
                if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Service called startForeground() as required: "   r);
                }
                r.fgRequired = false;
                r.fgWaiting = false;
                alreadyStartedOp = stopProcStatsOp = true;
                  //移除SERVICE_FOREGROUND_TIMEOUT_MSG消息,取消崩溃
                mAm.mHandler.removeMessages(
                        ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
            }
      }
    }
}

3:整个Service启动过程中涉及到的跨进程调用

3.1:ContextImpl -→ AMS:调用方进程→system_server进程

  1. 被调用方法:AMS中的startService()
ActivityManager.getService().startService()

3.2:ActivityThread -→ AMS:service所在进程→system_server进程

  1. 被调用方法:AMS中的attachApplication()
ActivityManager.getService().attachApplication()
  1. 拆除炸弹
ActivityManager.getService().serviceDoneExecuting()

3.3: AMS -→ ActivityThread:system_server进程→service所在进程

  1. 被调用方法:ApplicationThread中的scheduleCreateService()
app.thread.scheduleCreateService()
  1. 被调用方法:ApplicationThread中的scheduleServiceArgs()
app.threadscheduleServiceArgs()

4:总结

基于上述源码的分析,我们可以将Service的整体启动流程总结为下图:

   

Service启动流程图

以上就是Android中Service启动的大致原理,如果觉得有收获,欢迎关注点赞~

5:参考

  1. Android源码
  2. Android service 启动篇之 startService
  3. Android 从进程角度看Service启动流程
(0)

相关推荐

  • 两种win7恢复被删除的文件的方法

    两种win7恢复被删除的文件的方法 一.利用Win7的保护设置来还原 利用Win7的保护设置来还原,是有一定的限制,为了能够清晰的讲解这个方法,小编以一个例子来讲解,比如在桌面上新建一个名为" ...

  • Word2016两种输入在方框里打对勾的方法

    本介绍两种Word2016输入带勾方框效果的方法. 操作方法 01 先讲第一种方法,在空白处定位光标,然后点击红框中的插入. 02 依次选择插入符号,符号,其他符号,如下图所示. 03 按下图指示的位 ...

  • 两种不用快捷键打开Win10运行工具的方法

    win10系统运行工具,大家都不陌生,遇到麻烦时可以找它,但是它在哪里呢?如何打开?很多人使用快捷win+R把它调出来。其实不用快捷键也能找到它。本文介绍两种不用快捷键打开运行工具的方法。 方法一: ...

  • 在 Excel 图表中如何使用两种类型图表?

    在 Excel 图表中如何使用两种类型图表?

  • UG10.0怎么画圆? UG10.0中圆的两种绘制方法

    介绍UG NX10.0草图中圆命令的基本用法 1.首先进入UG草图环境 2.点击“插入”-“曲线”-“圆”命令:或点击工具条上改命令 方法一:圆心和直径定圆 选择“圆心和直径定圆”,在草绘区选取圆心点 ...

  • 两种常见的表单数据存储处理方法

    操作方法 01 对每一表单都编写相应的程序代码  在JSP页面或JavaBean或Servlet中,使用request. getparameter()函数逐一提取表单提交的数据,或编写相应的JavaB ...

  • 鲁大师迷你首页怎么关闭? 鲁大师两种取消弹出迷你新闻页的方法

    如何关闭鲁大师迷你页弹窗?自从安装了鲁大师后,每次开机的时候,鲁大师都会自动弹出迷你页弹窗,很烦人的,那么要怎么彻底关闭鲁大师迷你页弹窗呢.下面看看我是怎么关闭鲁大师弹出的迷你页的. 方法一 1.在开 ...

  • Excel表格中怎么把度分秒转换为度?Excel度分秒转换成度的两种方法介绍

    Excel表格怎么把度分秒转换为度?平时输入度分秒本来就很不方便,有的时候需要用度分秒显示,有的时候又需要转换成度.简直再麻烦不过了,有没有什么简单快速的方法呢?接下来小编就给大家介绍两种Excel度 ...

  • windows7多余的启动菜单两种删除方法

    今天同学更新了个Windows7系统,安装完成以后出现了两个启动菜单。这问题我很早以前也遇到过,貌似安装系统的时候方法不是怎么正确,类似于那种直接在原来系统上之间点击Windows镜像包里面的setu ...

  • Beyond Compare设置制表符大小的两种方法

    方法有以下两种,具体讲解如下: 方法一 在工具菜单下的文本格式对话框进行设置 步骤一 打开Beyond Compare软件,我们会看到在软件上方的有一个"工具"菜单,点击它会弹出下 ...