1 /* 2 * Copyright (C) 2022 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.server.notification; 18 19 import android.app.job.JobInfo; 20 import android.app.job.JobParameters; 21 import android.app.job.JobScheduler; 22 import android.app.job.JobService; 23 import android.content.ComponentName; 24 import android.content.Context; 25 26 import com.android.internal.annotations.VisibleForTesting; 27 import com.android.server.LocalServices; 28 29 /** 30 * JobService implementation for scheduling the notification informing users about 31 * notification permissions updates and taking them to review their existing permissions. 32 * @hide 33 */ 34 public class ReviewNotificationPermissionsJobService extends JobService { 35 public static final String TAG = "ReviewNotificationPermissionsJobService"; 36 37 @VisibleForTesting 38 protected static final int JOB_ID = 225373531; 39 40 /** 41 * Schedule a new job that will show a notification the specified amount of time in the future. 42 */ scheduleJob(Context context, long rescheduleTimeMillis)43 public static void scheduleJob(Context context, long rescheduleTimeMillis) { 44 JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); 45 ComponentName component = new ComponentName( 46 context, ReviewNotificationPermissionsJobService.class); 47 JobInfo newJob = new JobInfo.Builder(JOB_ID, component) 48 .setPersisted(true) // make sure it'll still get rescheduled after reboot 49 .setMinimumLatency(rescheduleTimeMillis) // run after specified amount of time 50 .build(); 51 jobScheduler.schedule(newJob); 52 } 53 54 @Override onStartJob(JobParameters params)55 public boolean onStartJob(JobParameters params) { 56 // While jobs typically should be run on different threads, this 57 // job only posts a notification, which is not a long-running operation 58 // as notification posting is asynchronous. 59 NotificationManagerInternal nmi = 60 LocalServices.getService(NotificationManagerInternal.class); 61 nmi.sendReviewPermissionsNotification(); 62 63 // once the notification is posted, the job is done, so no need to 64 // keep it alive afterwards 65 return false; 66 } 67 68 @Override onStopJob(JobParameters params)69 public boolean onStopJob(JobParameters params) { 70 // If we're interrupted for some reason, try again (though this may not 71 // ever happen due to onStartJob not leaving a job running after being 72 // called) 73 return true; 74 } 75 } 76