【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 , 点击链接可跳转查看完整源码 ;



目录
相关文章
|
2月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
226 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
3月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
242 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
9月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
2096 77
|
7月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
450 2
|
7月前
|
缓存 编解码 Android开发
Android内存优化之图片优化
本文主要探讨Android开发中的图片优化问题,包括图片优化的重要性、OOM错误的成因及解决方法、Android支持的图片格式及其特点。同时介绍了图片储存优化的三种方式:尺寸优化、质量压缩和内存重用,并详细讲解了相关的实现方法与属性。此外,还分析了图片加载优化策略,如异步加载、缓存机制、懒加载等,并结合多级缓存流程提升性能。最后对比了几大主流图片加载框架(Universal ImageLoader、Picasso、Glide、Fresco)的特点与适用场景,重点推荐Fresco在处理大图、动图时的优异表现。这些内容为开发者提供了全面的图片优化解决方案。
278 1
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
196 10
|
8月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
210 20
Android经典面试题之图片Bitmap怎么做优化
|
Java Android开发 UED
安卓应用开发中的内存管理优化技巧
在安卓开发的广阔天地里,内存管理是一块让开发者既爱又恨的领域。它如同一位严苛的考官,时刻考验着开发者的智慧与耐心。然而,只要我们掌握了正确的优化技巧,就能够驯服这位考官,让我们的应用在性能和用户体验上更上一层楼。本文将带你走进内存管理的迷宫,用通俗易懂的语言解读那些看似复杂的优化策略,让你的开发之路更加顺畅。
338 33
|
监控 算法 数据可视化
深入解析Android应用开发中的高效内存管理策略在移动应用开发领域,Android平台因其开放性和灵活性备受开发者青睐。然而,随之而来的是内存管理的复杂性,这对开发者提出了更高的要求。高效的内存管理不仅能够提升应用的性能,还能有效避免因内存泄漏导致的应用崩溃。本文将探讨Android应用开发中的内存管理问题,并提供一系列实用的优化策略,帮助开发者打造更稳定、更高效的应用。
在Android开发中,内存管理是一个绕不开的话题。良好的内存管理机制不仅可以提高应用的运行效率,还能有效预防内存泄漏和过度消耗,从而延长电池寿命并提升用户体验。本文从Android内存管理的基本原理出发,详细讨论了几种常见的内存管理技巧,包括内存泄漏的检测与修复、内存分配与回收的优化方法,以及如何通过合理的编程习惯减少内存开销。通过对这些内容的阐述,旨在为Android开发者提供一套系统化的内存优化指南,助力开发出更加流畅稳定的应用。
399 31