【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | Android 源码在线网址推荐 )

简介: 【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | Android 源码在线网址推荐 )

文章目录

一、JobScheduler 提交任务 schedule 方法源码分析

二、schedule(JobInfo job, int uId) 方法

三、scheduleAsPackage 方法

四、startTrackingJob 方法

五、JobSchedulerService 源码注释



上一篇博客 【Android 电量优化】电量优化 ( JobScheduler | JobService | AsyncTask ) 中使用了 JobScheduler 进行电量优化 , 将消耗电量的操作 , 都在设定的条件下集中执行 , 达到减少唤醒硬件的频率 , 省电的目的 ; 本篇博客中从源码角度分析上述操作的底层原理 ;



推荐代码查看网站 :


https://www.androidos.net.cn/sourcecode ( 推荐 )


http://androidxref.com/






一、JobScheduler 提交任务 schedule 方法源码分析


JobScheduler 的功能依赖 JobSchedulerService 系统服务完成 ;


使用 JobScheduler 对象提交任务的方法 schedule(jobInfo) , 最终跨进程调用的 JobSchedulerService 中的 int schedule(JobInfo job, int uId) 方法 ;






二、schedule(JobInfo job, int uId) 方法


JobSchedulerService 中的 int schedule(JobInfo job, int uId) 方法解析 :



JobScheduler 的提交任务方法 schedule , 最终调用到 int schedule(JobInfo job, int uId) 方法 , 该调用是跨进程调用的 ;


int schedule(JobInfo job, int uId) 方法 是客户端的 JobScheduler 调用 schedule 方法执行后的入口函数 , 提供一个 JobInfo job 任务 ; 如果任务已经被安排 , 那么取消该任务 , 并使用新传入的该 JobInfo job 参数代替原来的任务 ;






三、scheduleAsPackage 方法


在 int schedule(JobInfo job, int uId) 方法中 , 实际调用了 int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId, String tag) 方法 ,


参数说明 :


job 任务信息

uId 任务 id

packageName 包名

userId 用户 id ;

在上述 scheduleAsPackage 方法中 , 进行了一系列的状态判定 , 如包名不能为空 , 当前任务数量没有超过最大值 MAX_JOBS_PER_APP , 如果上述判定通过 , 就调用 void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) 方法 , 该方法用于追踪任务状态 ;






四、startTrackingJob 方法


当我们有一个任务状态对象 , 我们需要插入到 JobStore 时 , 回调 void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) 方法 , 确保所有相关的控制器知道该状态 ;


以下控制器需要知道任务状态 :


ConnectivityController

TimeController

IdleController

BatteryController

AppIdleController

ContentObserverController

DeviceIdleJobsController

这些控制器都封装在 List mControllers 成员变量中 , 该集合是 JobSchedulerService 的成员变量 ;


上述控制器在 public JobSchedulerService(Context context) 构造函数中初始化并放入 mControllers 集合中 ;






五、JobSchedulerService 源码注释


public class JobSchedulerService extends com.android.server.SystemService
        implements StateChangedListener, JobCompletedListener {
    /** 任务的主要集合. */
    final JobStore mJobs;
    /** 控制器集合 , 提醒该 Service 服务区更新任务. */
    List<StateController> mControllers;
    /**
     * 初始化系统服务
     * <p>
     * 子类必须定义一个单参数的构造函数 , 接收 Context context 参数 , 并且传递给父类
     * </p>
     *
     * @param context 系统服务上下文对象
     */
    public JobSchedulerService(Context context) {
        super(context);
        mHandler = new JobHandler(context.getMainLooper());
        mConstants = new Constants(mHandler);
        mJobSchedulerStub = new JobSchedulerStub();
        mJobs = JobStore.initAndGet(this);
        // 创建控制器集合
        // 后续会遍历该集合 , 遍历出的元素会调用 maybeStartTrackingJobLocked 方法
        mControllers = new ArrayList<StateController>();
        // 网络控制器
        mControllers.add(ConnectivityController.get(this));
        mControllers.add(TimeController.get(this));
        mControllers.add(IdleController.get(this));
        // 电量控制器
        mControllers.add(BatteryController.get(this));
        mControllers.add(AppIdleController.get(this));
        mControllers.add(ContentObserverController.get(this));
        mControllers.add(DeviceIdleJobsController.get(this));
    }
    // JobScheduler 的提交任务方法 schedule , 最终调用到该方法
    // 跨进程方式调用 
    // 这是客户端的 JobScheduler 调用 schedule 方法执行后的入口函数 , 提供一个 JobInfo job 任务 ; 
    // 如果任务已经被安排 , 那么取消该任务 , 并使用新传入的该 JobInfo job 参数代替原来的任务 ; 
    public int schedule(JobInfo job, int uId) {
        return scheduleAsPackage(job, uId, null, -1, null);
    }
    // 实际调用的方法 , 传入 JobInfo job 任务信息 , uId 任务 id , packageName 包名 , userId 用户 id , 
    public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId,
            String tag) {
        // 创建任务状态
        JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
  // ... 省略       
        JobStatus toCancel;
        synchronized (mLock) {
            // 判定状态是否合法 , 包名不能为空 , 当前任务数量没有超过最大值 MAX_JOBS_PER_APP
            if (ENFORCE_MAX_JOBS && packageName == null) {
                if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
                    Slog.w(TAG, "Too many jobs for uid " + uId);
                    // 如果多于最大任务数 , 就要抛出异常 
                    throw new IllegalStateException("Apps may not schedule more than "
                                + MAX_JOBS_PER_APP + " distinct jobs");
                }
            }
            toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
            if (toCancel != null) {
                cancelJobImpl(toCancel, jobStatus);
            }
            // 如果上述判定通过 , 就调用该方法 , 该方法用于追踪任务状态 
            startTrackingJob(jobStatus, toCancel);
        }
        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
        return JobScheduler.RESULT_SUCCESS;
    }
    /**
     * 当我们有一个任务状态对象 , 我们需要插入到 JobStore 时 , 回调该方法 , 
     * 确保所有相关的控制器知道它 ;
     */
    private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
        synchronized (mLock) {
          // 将本次调度的任务加入到 JobStore mJobs 集合中
            final boolean update = mJobs.add(jobStatus);
            if (mReadyToRock) {
              // 遍历控制器集合 List<StateController> mControllers
                for (int i = 0; i < mControllers.size(); i++) {
                    StateController controller = mControllers.get(i);
                    if (update) {
                        controller.maybeStopTrackingJobLocked(jobStatus, null, true);
                    }
                    // 调用控制器的 maybeStartTrackingJobLocked 函数 
                    controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
                }
            }
        }
    }
}



该代码路径为 /frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java , 点击链接可跳转查看完整源码 ;



目录
相关文章
|
16天前
|
移动开发 安全 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第30天】 在移动开发领域,性能优化始终是关键议题之一。特别是对于Android开发者来说,如何在保证应用流畅性的同时,提升代码的执行效率,已成为不断探索的主题。近年来,Kotlin语言凭借其简洁、安全和实用的特性,在Android开发中得到了广泛的应用。其中,Kotlin协程作为一种新的并发处理机制,为编写异步、非阻塞性的代码提供了强大工具。本文将深入探讨Kotlin协程在Android开发中的应用实践,以及如何通过协程优化应用性能,帮助开发者构建更高效的Android应用。
|
7天前
|
缓存 编解码 安全
探索Android 12的新特性与优化技巧
【6月更文挑战第7天】本文将深入探讨Android 12带来的创新功能和改进,包括用户界面的更新、隐私保护的加强以及性能的提升。同时,我们还将分享一些实用的优化技巧,帮助用户更好地利用这些新特性,提升手机的使用体验。
|
15天前
|
缓存 Android开发 开发者
安卓系统优化:提升手机性能的秘诀
【5月更文挑战第31天】本文将探讨如何通过一系列简单的步骤和技巧,对安卓系统进行优化,以提升手机的性能。我们将从清理无用文件、管理后台应用、调整系统设置等方面入手,帮助你的安卓设备运行更加流畅。
|
15天前
|
JSON Android开发 开发者
构建高效Android应用:采用Kotlin协程优化网络请求
【5月更文挑战第31天】 在移动开发领域,尤其是针对Android平台,网络请求的管理和性能优化一直是开发者关注的焦点。随着Kotlin语言的普及,其提供的协程特性为异步编程提供了全新的解决方案。本文将深入探讨如何利用Kotlin协程来优化Android应用中的网络请求,从而提升应用的响应速度和用户体验。我们将通过具体实例分析协程与传统异步处理方式的差异,并展示如何在现有项目中集成协程进行网络请求优化。
|
17天前
|
存储 缓存 Java
安卓应用性能优化实战
【5月更文挑战第29天】随着智能手机的普及,移动应用已成为人们日常生活中不可或缺的一部分。在众多操作系统中,安卓系统以其开放性和灵活性占据了大量的市场份额。然而,应用的性能问题却时常影响着用户体验。本文将深入探讨针对安卓平台进行应用性能优化的策略与实践,从内存管理到多线程处理,再到布局渲染,旨在为开发者提供全面的优化指导,以期打造出更流畅、高效的安卓应用。
|
17天前
|
编解码 缓存 数据库
构建高效Android应用:从性能优化到用户体验
【5月更文挑战第29天】 在移动开发领域,打造一个流畅且响应迅速的Android应用对于保持用户忠诚度和市场份额至关重要。本文将深入探讨如何通过细致的性能优化措施和关注用户体验设计,来提升Android应用的整体质量。我们将透过代码层面的实践技巧、资源管理和系统机制的优化,以及用户界面和交互设计的改良,共同构建起一个既快速又吸引人的应用程序。
|
18天前
|
缓存 监控 Android开发
构建高效Android应用:从优化布局到提升性能
【5月更文挑战第28天】 随着移动设备的普及,用户对Android应用的性能和响应速度有着越来越高的期待。本文旨在探讨一系列实用的技术和策略,帮助开发者在设计阶段就将性能考量纳入其中,以实现流畅和高效的用户体验。我们将深入分析布局优化、内存管理和多线程处理等关键领域,并提出具体的解决方案和最佳实践,以便开发过程中能够有效地避免常见的性能瓶颈。
|
19天前
|
缓存 移动开发 Android开发
安卓应用性能优化实践
【5月更文挑战第27天】在移动开发领域,应用的性能直接影响用户体验。特别是对于安卓平台,由于设备多样性和应用生态环境的复杂性,性能优化成为了开发者的一项重要任务。本文将探讨针对安卓平台进行应用性能优化的策略与实践,包括内存管理、电池效率以及响应速度提升等方面,旨在为开发人员提供一套实用的性能调优工具和思路。
|
21天前
|
编解码 缓存 Android开发
安卓应用性能优化实践
【5月更文挑战第25天】 在移动开发领域,随着用户对应用响应速度和流畅度要求的不断提高,安卓应用的性能优化已成为开发者不可忽视的重要课题。本文将深入探讨针对安卓平台进行性能优化的策略与实战技巧,包括内存管理、多线程应用、UI渲染效率提升以及电池使用效率优化等方面。通过分析常见的性能瓶颈并提供相应的解决方案,旨在帮助开发者构建更加高效、流畅的安卓应用。
|
21天前
|
缓存 监控 API
安卓应用性能优化实战
【5月更文挑战第25天】本文将深入探讨如何提升安卓应用的性能。我们将从内存管理,电池使用效率,网络请求以及UI渲染等方面进行深度剖析,并提供相应的优化策略和实践方法。无论你是初学者还是有经验的开发者,都能从中学到一些有用的技巧来提升你的安卓应用性能。