Service启动源码分析

作者: 拔萝卜占坑 | 来源:发表于2019-02-22 23:24 被阅读5次

    开启服务

    这里只讲解主要流程和方法

        private ComponentName startServiceCommon(Intent service, UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess();
                ComponentName cn = ActivityManagerNative.getDefault().startService(
                    mMainThread.getApplicationThread(), service,
                    service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
                ...
                return cn;
            } catch (RemoteException e) {
                return null;
            }
        }
    
    • getDefault()
    static public IActivityManager getDefault() {
        return gDefault.get();
     }
                                    
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
             ...
            IActivityManager am = asInterface(b);
            ...
            return am;
        }
    };
                                                            
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
         }
        //这里queryLocalInterface执行返回的是null,所以会执行return new ActivityManagerProxy(obj);
        IActivityManager in =
             (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
         }
        return new ActivityManagerProxy(obj);
     } 
    
    • ActivityManagerNative
      开启服务其实是跨进程的,这里用到Binder机制来实现跨进程通信
    class ActivityManagerProxy implements IActivityManager {  
        ......            
        public ComponentName startService(IApplicationThread caller, Intent service,  
                    String resolvedType) 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);  
            mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);  //mRemote是ServiceManager.getService("activity") -- ActivityManagerService;
             reply.readException();  
             ComponentName res = ComponentName.readFromParcel(reply);  
             data.recycle();  
             reply.recycle();  
             return res;  
        }     
          ......  
    }
    
    • ActivityManagerService
      经过上面的Binder,会执行到ActivityManagerService的startService方法来
    public final class ActivityManagerService extends ActivityManagerNative  
                                       implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {        
         ......       
        public ComponentName startService(IApplicationThread caller, Intent service,  
                        String resolvedType) {        
             ...
            ComponentName res = startServiceLocked(caller, service,  
                              resolvedType, callingPid, callingUid);  
            Binder.restoreCallingIdentity(origId);  
                          return res;  
          }  
        }  
     ......    
    }
    
    class ActiveServices implements IActivityManager {  
        ......   
        ComponentName startServiceLocked(IApplicationThread caller,Intent service, String resolvedType,int callingPid, int callingUid, int userId) {
            ......
            return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        }
    }
    
    • bringUpServiceLocked
    private final String bringUpServiceLocked(ServiceRecord r,int intentFlags, boolean execInFg, boolean whileRestarting) {
                
        //如果该Service已经启动。
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
         //如果正在等待被重新启动,那么什么也不做。
        if (!whileRestarting && r.restartDelay > 0) {
             return null;
        }
                    
                    
        //清除等待被重新启动的状态。
        if (mRestartingServices.remove(r)) {
            r.resetRestartCounter();
            clearRestartingIfNeededLocked(r);
        }
        //因为我们马上就要启动该Service,因此去掉它的延时属性。
        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);
                 getServiceMap(r.userId).mDelayedStartList.remove(r);
                 r.delayed = false;
             } 
            // Make sure that the user who owns this service is started.  If not,
            // we don't want to allow it to run.
            //确保拥有该服务的用户是已经被启动,如果没有,说明我将不想要它运行
               //个人看源码,这里处理通过绑定服务方式启动Service的处理
              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 is now being launched, its package can't be stopped.
                    /**
                        (个人理解)
                        设置包的状态,如果是将要被启动,那么包的状态不能是停止,默认包状态是停止,系统有些广播在应用安装后在没有运行过的情况下接收不到广播,原因应该也是因为包的状态是停止,
                        所以,当应用运行时,不管启动四大组件的那个一个,都会设置新的包状态。设置包状态过程会写入文件保存。
                        
                    */
                    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);
                    }    
                    
                    
                    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;//我决定flags就是配置文件里面的android:属性
                    final String procName = r.processName;
                    ProcessRecord app;
                    //如果不是运行在独立的进程。
                    if (!isolated) {
                        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
                        if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                                    + " app=" + app);
                                    
                        //如果该进程已经启动,那么调用realStartServiceLocked方法            
                        if (app != null && app.thread != null) {
                            try {
                                app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                                realStartServiceLocked(r, app, execInFg);
                                return null;
                            } catch (RemoteException e) {
                                Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                            }
    
                            // If a dead object exception was thrown -- fall through to
                            // restart the application.
                        }
                    } else {
                        // If this service runs in an isolated process, then each time
                        // we call startProcessLocked() we will get a new isolated
                        // process, starting another process if we are currently waiting
                        // for a previous process to come up.  To deal with this, we store
                        // in the service any current isolated process it is running in or
                        // waiting to have come up.
                        app = r.isolatedProc;
                    }        
                    
                    //如果该Service所对应的进程没有启动,那么首先启动该进程。
                    //比如启动的Service在单独的进程,该进程肯定没有被启动,那么系统会给该Service单独fork一个进程处理。
                    if (app == null) {
                        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;
                        }
                    }
                    //将该ServiceRecord加入到等待的集合当中,等到新的进程启动之后,再去启动它。
                    if (!mPendingServices.contains(r)) {
                        mPendingServices.add(r);
                    }                                   
                
                ......
              }
    
    • realStartServiceLocked
    private final void realStartServiceLocked(ServiceRecord r,  
                        ProcessRecord app) throws RemoteException {               
        ......  
        r.app = app;  
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
        app.services.add(r);          
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();                 
        ......  
         try {  
            ......  
             //通知应用端创建Service对象。
            app.thread.scheduleCreateService(r, r.serviceInfo);   
            ......  
        } finally {  
            ......  
        }  
            ......  
     }
    
    • bumpServiceExecutingLocked
    if (r.executeNesting == 0) {
        r.executeFg = fg;
        ProcessStats.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 (r.app.executingServices.size() == 1) {
                scheduleServiceTimeoutLocked(r.app);
            }
        }
    } else if (r.app != null && fg && !r.app.execServicesFg) {
        r.app.execServicesFg = true;
        scheduleServiceTimeoutLocked(r.app);
    }              
                            
    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
         if (proc.executingServices.size() == 0 || proc.thread == null) {
                return;
        }
        long now = SystemClock.uptimeMillis();
        Message msg = mAm.mHandler.obtainMessage(
                                            ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
         mAm.mHandler.sendMessageAtTime(msg,
        proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
    }           
                                
    mAm.mHandler是MainHandler对象
                                
        case SERVICE_TIMEOUT_MSG: {
            if (mDidDexOpt) {
                     mDidDexOpt = false;
                     Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
                      nmsg.obj = msg.obj;
                      mHandler.sendMessageDelayed(nmsg, ActiveServices.SERVICE_TIMEOUT);
                                return;
                            }
                            mServices.serviceTimeout((ProcessRecord)msg.obj);
                        } break;         
                        void serviceTimeout(ProcessRecord proc) {  
                            ......
                            if (timeout != null && mAm.mLruProcesses.contains(proc)) {
                                Slog.w(TAG, "Timeout executing service: " + timeout);
                                anrMessage = "Executing service " + timeout.shortName;
                            } else {
                                Message msg = mAm.mHandler.obtainMessage(
                                        ActivityManagerService.SERVICE_TIMEOUT_MSG);
                                msg.obj = proc;
                                mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg
                                        ? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));
                            }
                                }
                                if (anrMessage != null) {
                                    mAm.appNotResponding(proc, null, null, false, anrMessage);
                                }                       
                        }                               
                                
    
    • scheduleServiceArgs
    private class ApplicationThread extends ApplicationThreadNative {
    
         public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
                            int flags ,Intent args) {
            ServiceArgsData s = new ServiceArgsData();
            s.token = token;
            s.taskRemoved = taskRemoved;
            s.startId = startId;
            s.flags = flags;
            s.args = args;
            sendMessage(H.SERVICE_ARGS, s);
        }
                        
        //ActivityThread
                    case SERVICE_ARGS:
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
                        handleServiceArgs((ServiceArgsData)msg.obj);
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        break;                  
                   }            
                */
               sendServiceArgsLocked(r, execInFg, true);
              
                ......  
              
            }
    
    • ApplicationThreadNative
        public final void scheduleCreateService(IBinder token, ServiceInfo info,
                CompatibilityInfo compatInfo, int processState) throws RemoteException {
            Parcel data = Parcel.obtain();
            data.writeInterfaceToken(IApplicationThread.descriptor);
            data.writeStrongBinder(token);
            info.writeToParcel(data, 0);
            compatInfo.writeToParcel(data, 0);
            data.writeInt(processState);
            mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                    IBinder.FLAG_ONEWAY);
            data.recycle();
        }
    
    • ActivityThread
            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();  //如果后台将要进行gc回收,那么这个函数将从任务队列里面移除gc回收任务。
    
                    //得到APK相关信息
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
            try {
                //利用反射创建我们需要启动的Service对象。
                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);
                            
                            /**
                                    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
                                    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
                                    return new ContextImpl(null, mainThread,packageInfo, null, null, false, null, null);
                                    }
                            */
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
    
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                
                /**
                    关键函数:Service :attach
                            public final void attach(
                                    Context context,
                                    ActivityThread thread, String className, IBinder token,
                                    Application application, Object activityManager) {
                                attachBaseContext(context);
                                mThread = thread;           // NOTE:  unused - remove?
                                mClassName = className;
                                mToken = token;
                                mApplication = application;
                                mActivityManager = (IActivityManager)activityManager;
                                mStartCompatibility = getApplicationInfo().targetSdkVersion
                                        < Build.VERSION_CODES.ECLAIR;
                            }  
                            
                            protected void attachBaseContext(Context base) {
                                if (mBase != null) {
                                    throw new IllegalStateException("Base context already set");
                                }
                                mBase = base;
                            }       
                            mBase:ContextImpl对象,开启一个新的Activity,Service等对话创建一个ContextImpl对象,里面封装了启动Activity,Service的方法。                      
                */
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManagerNative.getDefault());
                        
                //执行Service的onCreate方法。       
                service.onCreate();
                //使用token存储Service对象
                mServices.put(data.token, service);
                try {
                    
                    /**
                        //Retrieve the system's default/global activity manager
                        //其实返回的是:ActivityManagerService对象
                                static public IActivityManager getDefault() {
                                    return gDefault.get();
                                }     
                                
                                            
                    */
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, 0, 0, 0);
                } catch (RemoteException e) {
                    // nothing to do.
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    
    • serviceDoneExecutingLocked
            private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
                boolean finishing) {
                    
                    ......
                    
                    //如果沒有执行的服务,这移除消息
                    if (r.app.executingServices.size() == 0) {
                        if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
                                "No more executingServices of " + r.shortName);
                        mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
                    } else if (r.executeFg) {
                        // Need to re-evaluate whether the app still needs to be in the foreground.
                        for (int i=r.app.executingServices.size()-1; i>=0; i--) {
                            if (r.app.executingServices.valueAt(i).executeFg) {
                                r.app.execServicesFg = true;
                                break;
                            }
                        }
                    }     
                            
                ......  
            }
    
    • 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();
                    }
                    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 {
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, 1, data.startId, res);
                    } catch (RemoteException e) {
                        // nothing to do.
                    }
                    ensureJitEnabled();
                } catch (Exception e) {
                    if (!mInstrumentation.onException(s, e)) {
                        throw new RuntimeException(
                                "Unable to start service " + s
                                + " with " + data.args + ": " + e.toString(), e);
                    }
                }
            }
            
          }
    
    • 补充
      ServiceManager
    private void startBootstrapServices() {     
         ...... 
         // Set up the Application instance for the system process and get started.
         mActivityManagerService.setSystemProcess();        
     }
    

    ActivityManagerService

     public void setSystemProcess() {       
        ......          
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
        ......
     }
    

    相关文章

      网友评论

        本文标题:Service启动源码分析

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