1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dialer.shortcuts; 18 19 import android.annotation.TargetApi; 20 import android.app.job.JobInfo; 21 import android.app.job.JobParameters; 22 import android.app.job.JobScheduler; 23 import android.app.job.JobService; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.os.Build.VERSION; 27 import android.os.Build.VERSION_CODES; 28 import android.support.annotation.MainThread; 29 import android.support.annotation.NonNull; 30 import android.support.v4.os.UserManagerCompat; 31 import com.android.dialer.common.Assert; 32 import com.android.dialer.common.LogUtil; 33 import com.android.dialer.constants.ScheduledJobIds; 34 import java.util.concurrent.TimeUnit; 35 36 /** 37 * {@link JobService} which starts the periodic job to refresh dynamic and pinned shortcuts. 38 * 39 * <p>Only {@link #schedulePeriodicJob(Context)} should be used by callers. 40 */ 41 @TargetApi(VERSION_CODES.N_MR1) // Shortcuts introduced in N MR1 42 public final class PeriodicJobService extends JobService { 43 44 private static final long REFRESH_PERIOD_MILLIS = TimeUnit.HOURS.toMillis(24); 45 46 private RefreshShortcutsTask refreshShortcutsTask; 47 48 /** 49 * Schedules the periodic job to refresh shortcuts. If called repeatedly, the job will just be 50 * rescheduled. 51 * 52 * <p>The job will not be scheduled if the build version is not at least N MR1 or if the user is 53 * locked. 54 */ 55 @MainThread schedulePeriodicJob(@onNull Context context)56 public static void schedulePeriodicJob(@NonNull Context context) { 57 Assert.isMainThread(); 58 LogUtil.enterBlock("PeriodicJobService.schedulePeriodicJob"); 59 60 if (VERSION.SDK_INT >= VERSION_CODES.N_MR1 && UserManagerCompat.isUserUnlocked(context)) { 61 JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); 62 if (jobScheduler.getPendingJob(ScheduledJobIds.SHORTCUT_PERIODIC_JOB) != null) { 63 LogUtil.i("PeriodicJobService.schedulePeriodicJob", "job already scheduled."); 64 return; 65 } 66 JobInfo jobInfo = 67 new JobInfo.Builder( 68 ScheduledJobIds.SHORTCUT_PERIODIC_JOB, 69 new ComponentName(context, PeriodicJobService.class)) 70 .setPeriodic(REFRESH_PERIOD_MILLIS) 71 .setPersisted(true) 72 .setRequiresCharging(true) 73 .setRequiresDeviceIdle(true) 74 .build(); 75 jobScheduler.schedule(jobInfo); 76 } 77 } 78 79 /** Cancels the periodic job. */ 80 @MainThread cancelJob(@onNull Context context)81 public static void cancelJob(@NonNull Context context) { 82 Assert.isMainThread(); 83 LogUtil.enterBlock("PeriodicJobService.cancelJob"); 84 85 context.getSystemService(JobScheduler.class).cancel(ScheduledJobIds.SHORTCUT_PERIODIC_JOB); 86 } 87 88 @Override 89 @MainThread onStartJob(@onNull JobParameters params)90 public boolean onStartJob(@NonNull JobParameters params) { 91 Assert.isMainThread(); 92 LogUtil.enterBlock("PeriodicJobService.onStartJob"); 93 94 if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) { 95 (refreshShortcutsTask = new RefreshShortcutsTask(this)).execute(params); 96 } else { 97 // It is possible for the job to have been scheduled on NMR1+ and then the system was 98 // downgraded to < NMR1. In this case, shortcuts are no longer supported so we cancel the job 99 // which creates them. 100 LogUtil.i("PeriodicJobService.onStartJob", "not running on NMR1, cancelling job"); 101 cancelJob(this); 102 return false; 103 } 104 return true; 105 } 106 107 @Override 108 @MainThread onStopJob(@onNull JobParameters params)109 public boolean onStopJob(@NonNull JobParameters params) { 110 Assert.isMainThread(); 111 LogUtil.enterBlock("PeriodicJobService.onStopJob"); 112 113 if (refreshShortcutsTask != null) { 114 refreshShortcutsTask.cancel(false /* mayInterruptIfRunning */); 115 } 116 return false; 117 } 118 } 119