天天看點

性能優化10_JobScheduler源碼

Android性能優化彙總

1 JobScheduler 實作擷取

JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
           

兩個方面分析:

  1. 系統服務什麼時候啟動的
  2. 尋找是否有JobSchedulerService的類

結果:發現JobSchedulerService 存在

JobSchedulerService extends com.android.server.SystemService implements StateChangedListener, JobCompletedListener
           

2 aidl

JobScheduler 是一個抽象類,無法跟蹤

由于是通過getSystemService擷取,自己的服務和系統服務需要通信,那麼應該涉及到跨程序通路,程序間通信(ipc、binder、aidl)

而在JobScheduleService中也找了對應的class:JobSchedulerStub extends IJobScheduler.Stub

3 schedule方法

JobScheduler.schedule -> IJobScheduler.Stub.schedule

4 驗證上述内容

尋找有沒有JobScheduler的實作類impl(最終找到了JobSchedulerImpl extends 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;
        }
    }

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

    @Override
    public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag) {
        try {
            return mBinder.scheduleAsPackage(job, packageName, userId, tag);
        } catch (RemoteException e) {
            return JobScheduler.RESULT_FAILURE;
        }
    }

    @Override
    public void cancel(int jobId) {
        try {
            mBinder.cancel(jobId);
        } catch (RemoteException e) {}

    }

    @Override
    public void cancelAll() {
        try {
            mBinder.cancelAll();
        } catch (RemoteException e) {}

    }

    @Override
    public List<JobInfo> getAllPendingJobs() {
        try {
            return mBinder.getAllPendingJobs().getList();
        } catch (RemoteException e) {
            return null;
        }
    }

    @Override
    public JobInfo getPendingJob(int jobId) {
        try {
            return mBinder.getPendingJob(jobId);
        } catch (RemoteException e) {
            return null;
        }
    }

    @Override
    public List<JobInfo> getStartedJobs() {
        try {
            return mBinder.getStartedJobs();
        } catch (RemoteException e) {
            return null;
        }
    }

    @Override
    public List<JobSnapshot> getAllJobSnapshots() {
        try {
            return mBinder.getAllJobSnapshots().getList();
        } catch (RemoteException e) {
            return null;
        }
    }
}
           

5 IJobScheduler.Stub.schedule

-> JobSchedulerService.this.scheduleAsPackage

->startTrackingJobLocked

private void startTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
    
        jobStatus.enqueueTime = sElapsedRealtimeClock.millis();
        final boolean update = mJobs.add(jobStatus);
		//mJob是一個隊列,先進先出
        if (mReadyToRock) {
            for (int i = 0; i < mControllers.size(); i++) {
                StateController controller = mControllers.get(i);
                if (update) {
					//把之前存在的同樣工作移除,重新開啟
                    controller.maybeStopTrackingJobLocked(jobStatus, null, true);
                }
                controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
            }
        }
    }
           

6 程式入口

zygote程序- 系統程序SystemServer啟動 - 系統程序開啟一系列關鍵服務,如:AMS/PMS/WMB/JobSchedulerService

程式主入口

public static void main(String[] args) {
        new SystemServer().run();
}
           

run:startOtherServices()

->startOtherServices: mSystemServiceManager.startService(JobSchedulerService.class);

->SystemServiceManager.startService:startService(service)//通過反射擷取JobSchedulerService構造方法,得到執行個體;

->service.onStart();

7 JobSchedulerService

1)JobSchedulerService構造方法

public JobSchedulerService(Context context) {
        super(context);

        mLocalPM = LocalServices.getService(PackageManagerInternal.class);
        mActivityManagerInternal = Preconditions.checkNotNull(
                LocalServices.getService(ActivityManagerInternal.class));

        mHandler = new JobHandler(context.getMainLooper());
        mConstants = new Constants();
        mConstantsObserver = new ConstantsObserver(mHandler);
        mJobSchedulerStub = new JobSchedulerStub();

        mConcurrencyManager = new JobConcurrencyManager(this);

        // Set up the app standby bucketing tracker
        mStandbyTracker = new StandbyTracker();
        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
        mUsageStats.addAppIdleStateChangeListener(mStandbyTracker);

        // The job store needs to call back
        publishLocalService(JobSchedulerInternal.class, new LocalService());

        // Initialize the job store and set up any persisted jobs
        mJobs = JobStore.initAndGet(this);

        // Create the controllers.
        mControllers = new ArrayList<StateController>();
        mControllers.add(new ConnectivityController(this));
        mControllers.add(new TimeController(this));
        mControllers.add(new IdleController(this));
        mBatteryController = new BatteryController(this);
        mControllers.add(mBatteryController);
        mStorageController = new StorageController(this);
        mControllers.add(mStorageController);
        mControllers.add(new BackgroundJobsController(this));
        mControllers.add(new ContentObserverController(this));
        mDeviceIdleJobsController = new DeviceIdleJobsController(this);
        mControllers.add(mDeviceIdleJobsController);
        mControllers.add(new QuotaController(this));

        // If the job store determined that it can't yet reschedule persisted jobs,
        // we need to start watching the clock.
        if (!mJobs.jobTimesInflatedValid()) {
            Slog.w(TAG, "!!! RTC not yet good; tracking time updates for job scheduling");
            context.registerReceiver(mTimeSetReceiver, new IntentFilter(Intent.ACTION_TIME_CHANGED));
        }
    }
           

-> JobHandler 檢查任務

case MSG_CHECK_JOB:
		 maybeQueueReadyJobsForExecutionLocked();//看情況執行任務
	 case MSG_JOB_EXPIRED任務到期了
		 // runNow can be null, which is a controller's way of indicating that its
                        // state is such that all ready jobs should be run immediately.
           

-> 回構造方法:

JobStore.initAndGet 讀取一些永久任務 /data/system/job/jobs.xml

-> StateController

maybeStartTrackingJobLocked

maybeStopTrackingJobLocked

2) JobSchedulerService.onStart方法

publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
           

9 ConnectivityController 為例

ConnectivityController extends StateController implements

ConnectivityManager.OnNetworkActiveListener

public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        if (jobStatus.hasConnectivityConstraint()) {
            updateConstraintsSatisfied(jobStatus);
            ArraySet<JobStatus> jobs = mTrackedJobs.get(jobStatus.getSourceUid());
            if (jobs == null) {
                jobs = new ArraySet<>();
                mTrackedJobs.put(jobStatus.getSourceUid(), jobs);
            }
            jobs.add(jobStatus);
            jobStatus.setTrackingController(JobStatus.TRACKING_CONNECTIVITY);
        }
    }
           

-> mTrackedJobs.put(jobStatus.getSourceUid(), jobs); 添加監聽

-> mStateChangedListener.onControllerStateChanged

->StateController.mStateChangedListener:

->JobSchedulerService構造中 mControllers.add(new ConnectivityController(this));

-> ConnectivityController: super(service);

->StateController(JobSchedulerService service) : mStateChangedListener = service; 是以,mStateChangedListener就是JobSchedulerService

(JobSchedulerService實作了StateChangedListener)

->JobSchedulerService:onControllerStateChanged 被調用: mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();

繼續閱讀