1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.component_updater; 6 7 import android.os.Build; 8 9 import org.chromium.base.ContextUtils; 10 import org.chromium.base.annotations.CalledByNative; 11 import org.chromium.base.annotations.JNINamespace; 12 import org.chromium.base.annotations.NativeMethods; 13 import org.chromium.components.background_task_scheduler.BackgroundTask.TaskFinishedCallback; 14 import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory; 15 import org.chromium.components.background_task_scheduler.TaskIds; 16 import org.chromium.components.background_task_scheduler.TaskInfo; 17 import org.chromium.gms.ChromiumPlayServicesAvailability; 18 19 /** Java-side implementation of the component update scheduler using the BackgroundTaskScheduler. */ 20 @JNINamespace("component_updater") 21 public class UpdateScheduler { 22 private static UpdateScheduler sInstance; 23 private TaskFinishedCallback mTaskFinishedCallback; 24 private long mNativeScheduler; 25 private long mDelayMs; 26 27 @CalledByNative getInstance()28 /* package */ static UpdateScheduler getInstance() { 29 if (sInstance == null) { 30 sInstance = new UpdateScheduler(); 31 } 32 return sInstance; 33 } 34 35 @CalledByNative isAvailable()36 /* package */ static boolean isAvailable() { 37 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M 38 || ChromiumPlayServicesAvailability.isGooglePlayServicesAvailable( 39 ContextUtils.getApplicationContext()); 40 } 41 onStartTaskBeforeNativeLoaded(TaskFinishedCallback callback)42 /* package */ void onStartTaskBeforeNativeLoaded(TaskFinishedCallback callback) { 43 mTaskFinishedCallback = callback; 44 } 45 onStartTaskWithNative()46 /* package */ void onStartTaskWithNative() { 47 assert mNativeScheduler != 0; 48 UpdateSchedulerJni.get().onStartTask(mNativeScheduler, UpdateScheduler.this); 49 } 50 onStopTask()51 /* package */ void onStopTask() { 52 if (mNativeScheduler != 0) { 53 UpdateSchedulerJni.get().onStopTask(mNativeScheduler, UpdateScheduler.this); 54 } 55 mTaskFinishedCallback = null; 56 scheduleInternal(mDelayMs); 57 } 58 reschedule()59 /* package */ void reschedule() { 60 scheduleInternal(mDelayMs); 61 } 62 UpdateScheduler()63 private UpdateScheduler() {} 64 scheduleInternal(long delayMs)65 private void scheduleInternal(long delayMs) { 66 // Skip re-scheduling if we are currently running the update task. Otherwise, the current 67 // update tasks would be cancelled. 68 if (mTaskFinishedCallback != null) return; 69 70 TaskInfo taskInfo = TaskInfo.createOneOffTask(TaskIds.COMPONENT_UPDATE_JOB_ID, delayMs, 71 Integer.MAX_VALUE) 72 .setUpdateCurrent(true) 73 .setRequiredNetworkType(TaskInfo.NetworkType.UNMETERED) 74 .setIsPersisted(true) 75 .build(); 76 BackgroundTaskSchedulerFactory.getScheduler().schedule( 77 ContextUtils.getApplicationContext(), taskInfo); 78 } 79 80 @CalledByNative schedule(long initialDelayMs, long delayMs)81 private void schedule(long initialDelayMs, long delayMs) { 82 mDelayMs = delayMs; 83 scheduleInternal(initialDelayMs); 84 } 85 86 @CalledByNative finishTask(boolean reschedule)87 private void finishTask(boolean reschedule) { 88 assert mTaskFinishedCallback != null; 89 mTaskFinishedCallback.taskFinished(false); 90 mTaskFinishedCallback = null; 91 if (reschedule) { 92 scheduleInternal(mDelayMs); 93 } 94 } 95 96 @CalledByNative setNativeScheduler(long nativeScheduler)97 private void setNativeScheduler(long nativeScheduler) { 98 mNativeScheduler = nativeScheduler; 99 } 100 101 @CalledByNative cancelTask()102 private void cancelTask() { 103 BackgroundTaskSchedulerFactory.getScheduler().cancel( 104 ContextUtils.getApplicationContext(), TaskIds.COMPONENT_UPDATE_JOB_ID); 105 } 106 107 @NativeMethods 108 interface Natives { onStartTask(long nativeBackgroundTaskUpdateScheduler, UpdateScheduler caller)109 void onStartTask(long nativeBackgroundTaskUpdateScheduler, UpdateScheduler caller); onStopTask(long nativeBackgroundTaskUpdateScheduler, UpdateScheduler caller)110 void onStopTask(long nativeBackgroundTaskUpdateScheduler, UpdateScheduler caller); 111 } 112 } 113