JobScheduler5.0源码分析

0.JobScheduler执行代码

mJobScheduler=(JobScheduler)getSystemService(Context.JOB_SCHEDULER_SERVICE);
mJobInfo=new JobInfo.Builder(i,mComponentName).setMinimumLatency(5*1000).build();
mJobScheduler.schedule(mJobInfo);

这里写图片描述

1.创建服务

1.1 SystemServer代码

上图提到,我们可以从zygote进程孵化一个新的系统服务进程,也叫做SystemServer。这里我们可以先找到main函数,看下他是如何创建一系列的系统子服务的:

/**
 * The main entry point from zygote.
 */
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {

    //启动服务
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();//启动系统级服务
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }
}

private void startOtherServices() {

     mSystemServiceManager.startService(JobSchedulerService.class);

}

1.2 SystemServiceManager代码

上一节我们看到JobSchedulerService远程服务已经被启动了,如何启动呢,实际上是通过反射JobSchedulerService该类并调用该类的构造器初始化的:

public <T extends SystemService> T startService(Class<T> serviceClass) {
    final String name = serviceClass.getName();

    final T service;
    try {
        Constructor<T> constructor = serviceClass.getConstructor(Context.class);
        service = constructor.newInstance(mContext);
    } catch (InstantiationException ex) {
        throw new RuntimeException("Failed to create service " + name
                + ": service could not be instantiated", ex);
    }  

    mServices.add(service);

    return service;
}

1.3 JobSchedulerService远程服务代码

接下来我们看看他们是如何初始化:

public class JobSchedulerService extends com.android.server.SystemService
    implements StateChangedListener, JobCompletedListener {

    public JobSchedulerService(Context context) {
        super(context);
        // 初始化所有的控制器(每个JobInfo都会创建一系列的约束,必须免费的网络,系统空闲,时间 电量约束等等)
        mControllers = new ArrayList<StateController>();
        mControllers.add(ConnectivityController.get(this));
        mControllers.add(TimeController.get(this));
        mControllers.add(IdleController.get(this));
        mControllers.add(BatteryController.get(this));

         //操作任务逻辑的处理器
        mHandler = new JobHandler(context.getMainLooper());
        //远程服务的代理对象 很重要 至此!!!进程一服务端我们已经分析完毕
        mJobSchedulerStub = new JobSchedulerStub();
        // 读取任务进度的持久化文件 /system/job/jobs.xml
        mJobs = JobStore.initAndGet(this);
    }

}

2.关联服务

还记得我们调用代码的顺序吗,当我们获取服务后,我们会调用如下代码:

mJobScheduler.schedule(mJobInfo);   

此刻通过进程二服务端的图你会发现,JobScheduer是一个抽象类,而它还有一个子类实现。当我们调用schedule方法的时候,子类通过代理调用了服务端的schedule():

public abstract class JobScheduler {}

public class JobSchedulerImpl extends JobScheduler {

    IJobScheduler mBinder;

    /* package */ JobSchedulerImpl(IJobScheduler binder) {
        mBinder = binder;
    }

    @Override
    public int schedule(JobInfo job) {
        try {
            return mBinder.schedule(job);
        } catch (RemoteException e) {
            return JobScheduler.RESULT_FAILURE;
        }
    }

    ...

}

回到进程一服务端查看JobSchedulerStub代理是如何处理的:

@Override
public int schedule(JobInfo job) throws RemoteException {

    ...
    try {
        //调用JobSchedulerService的schedule(job, uid)
        return JobSchedulerService.this.schedule(job, uid);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

public class JobSchedulerService{

    public int schedule(JobInfo job, int uId) {
        //1.封装任务为JobStatus
        JobStatus jobStatus = new JobStatus(job, uId);
        //2.如果之前任务已经存在 替换
        cancelJob(uId, job.getId());
        //3.开始跟踪任务 我们之前说过 JobInfo会携带各种约束,这里根据各种约束开始跟踪任务,会调用到约束的maybeStartTrackingJob()。
        startTrackingJob(jobStatus);
        //4.检查是否需要马上执行任务。
        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
        return JobScheduler.RESULT_SUCCESS;
    }
}

3.触发任务回调

之前我们提到,在创建JobInfo必须设置约束才可以。那么服务端也创建了一些列控制器来跟踪任务的状态。这个我们在JobScheduler创建的时候已经提过了。他们有个共同的父类StateController。

public abstract class StateController {
    //开始跟踪任务
    public abstract void maybeStartTrackingJob(JobStatus jobStatus);
    //结束跟踪任务
    public abstract void maybeStopTrackingJob(JobStatus jobStatus);

    public abstract void dumpControllerState(PrintWriter pw);

}

以第一个子类ConnectivityController为例他是通过get静态方式初始化的:

public class ConnectivityController extends StateController implements
        ConnectivityManager.OnNetworkActiveListener {

    public static ConnectivityController get(JobSchedulerService jms) {
        synchronized (sCreationLock) {
            if (mSingleton == null) {
                mSingleton = new ConnectivityController(jms, jms.getContext());
            }
            return mSingleton;
        }
    }

    private ConnectivityController(StateChangedListener stateChangedListener, Context context) {
        super(stateChangedListener, context);
        // Register connectivity changed BR.
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiverAsUser(
                mConnectivityChangedReceiver, UserHandle.ALL, intentFilter, null, null);
        ConnectivityService cs =
                (ConnectivityService)ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        if (cs != null) {
            if (cs.getActiveNetworkInfo() != null) {
                mNetworkConnected = cs.getActiveNetworkInfo().isConnected();
            }
            mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered();
        }
    }

}

上面的代码完成了如下几件事:

  1. 传入当前的StateChangedListener状态改变监听器,并且JobSchedulerService已经实现了该监听器。也就是说如果网络改变了可以通过该监听器回调给JobSchedulerService。
  2. 注册了一个叫做ConnectivityChangedReceiver广播接收者。当网络改变的时候就会调用该方法。

    class ConnectivityChangedReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            final String action = intent.getAction();
            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
    
                    //获取网络的类型...
                if (activeNetwork == null) {
                    ...
                    updateTrackedJobs(userid);
                } else if (activeNetwork.getType() == networkType) {
                    ...
                    updateTrackedJobs(userid);
                }
            } 
        }
    };
    
    private void updateTrackedJobs(int userId) {
        synchronized (mTrackedJobs) {
            //... 如果网络改变了 则通过监听器告诉JobSchedulerService
            if (changed) {
                mStateChangedListener.onControllerStateChanged();
            }
        }
    }
    

我们看下当某个条件触发。JobSchedulerService是如何处理的:

@Override
public void onControllerStateChanged() {
    mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}

private class JobHandler extends Handler {
    ...
    @Override
    public void handleMessage(Message message) {
        ...
        switch (message.what) {
            case MSG_JOB_EXPIRED:
                synchronized (mJobs) {
                    JobStatus runNow = (JobStatus) message.obj;
                    ...
                    if (runNow != null && !mPendingJobs.contains(runNow)
                            && mJobs.containsJob(runNow)) {
                        mPendingJobs.add(runNow);
                    }
                    queueReadyJobsForExecutionLockedH();
                }
                break;
            case MSG_CHECK_JOB:
                    ...
                maybeQueueReadyJobsForExecutionLockedH();
                break;
        }
        maybeRunPendingJobsH();
        removeMessages(MSG_CHECK_JOB);
    }

}

上面的代码主要执行三个有效的方法:

  1. maybeQueueReadyJobsForExecutionLockedH();//将任务添加到任务待执行列表中
  2. maybeRunPendingJobsH();//将待执行任务列表中的任务执行
  3. removeMessages(MSG_CHECK_JOB);移除当前任务

maybeRunPendingJobsH()是如何关联我们熟悉的JobService的?

private void maybeRunPendingJobsH() {
        synchronized (mJobs) {
            Iterator<JobStatus> it = mPendingJobs.iterator();
            while (it.hasNext()) {
                    //1.拿到等待执行的任务
                JobStatus nextPending = it.next();
                ...
                //2.从执行列表中移除当前任务
                if (!availableContext.executeRunnableJob(nextPending)) {
                    if (DEBUG) {
                        Slog.d(TAG, "Error executing " + nextPending);
                    }
                    //3.从待运行的列表中移除
                    mJobs.remove(nextPending);
                }
                it.remove();
            }
        }
    }

JobServiceContext是如何执行executeRunnableJob(nextPending)去执行任务的,代码如下:

boolean executeRunnableJob(JobStatus job) {
    //构建任务参数
    mParams = new JobParameters(this, job.getJobId(), job.getExtras(),
                !job.isConstraintsSatisfied());
   //绑定我们当初在JobInfo中传入的服务对象。
    boolean binding = mContext.bindServiceAsUser(intent, this,
                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
                new UserHandle(job.getUserId()));
}

绑定JobService服务后,实现了如下:

  1. onBind()被调用,返回代理对象

    public abstract class JobService extends Service {

    IJobService mBinder = new IJobService.Stub() {
        @Override
        public void startJob(JobParameters jobParams) {
            ensureHandler();
            Message m = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams);
            m.sendToTarget();
        }
        @Override
        public void stopJob(JobParameters jobParams) {
            ensureHandler();
            Message m = Message.obtain(mHandler, MSG_STOP_JOB, jobParams);
            m.sendToTarget();
        }
    };
    
    public final IBinder onBind(Intent intent) {
        return mBinder.asBinder();
    }
    

    }

  2. JobServiceContext的onServiceConnected()被调用:

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //内部wake_lock锁在这里。。。
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mRunningJob.getTag());
        mWakeLock.setWorkSource(new WorkSource(mRunningJob.getUid()));
        mWakeLock.setReferenceCounted(false);
        mWakeLock.acquire();
        mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();
    }
    
    
    private class JobServiceHandler extends Handler {
    
        @Override
        public void handleMessage(Message message) {
                //case MSG_SERVICE_BOUND:
            handleServiceBoundH();
        }
    
    
        private void handleServiceBoundH() {
            ...
            //最最最...终启动了onStartJob();
            service.startJob(mParams);
        }
    
    }
    

猜你喜欢

转载自blog.csdn.net/qq285016127/article/details/78822095