1 /* 2 * Copyright (C) 2019 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 package com.android.car.bugreport; 17 18 import android.app.job.JobInfo; 19 import android.app.job.JobScheduler; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.util.Log; 23 24 /** 25 * Utilities for scheduling upload jobs. 26 */ 27 class JobSchedulingUtils { 28 private static final String TAG = JobSchedulingUtils.class.getSimpleName(); 29 30 private static final int UPLOAD_JOB_ID = 1; 31 private static final int EXPIRE_OLD_BUG_REPORTS_JOB_ID = 2; 32 private static final int RETRY_DELAY_IN_MS = 5_000; 33 34 /** 35 * Schedules {@link UploadJob} under the current user. 36 * 37 * <p>Make sure this method is called under the primary user. 38 * 39 * <ul> 40 * <li>require network connectivity 41 * <li>good quality network (large upload size) 42 * <li>persist across reboots 43 * </ul> 44 */ scheduleUploadJob(Context context)45 static void scheduleUploadJob(Context context) { 46 JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); 47 if (jobScheduler == null) { 48 Log.w(TAG, "Cannot get JobScheduler from context."); 49 return; 50 } 51 52 JobInfo pendingJob = jobScheduler.getPendingJob(UPLOAD_JOB_ID); 53 // if there is already a pending job, do not schedule a new one. 54 if (pendingJob != null) { 55 Log.d(TAG, "Upload job is already active, not re-scheduling"); 56 return; 57 } 58 59 // NOTE: Don't set estimated network bytes, because we want bug reports to be uploaded 60 // without any constraints. 61 jobScheduler.schedule(new JobInfo.Builder(UPLOAD_JOB_ID, 62 new ComponentName(context, UploadJob.class)) 63 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) 64 .setBackoffCriteria(RETRY_DELAY_IN_MS, JobInfo.BACKOFF_POLICY_LINEAR) 65 .build()); 66 } 67 68 /** 69 * Schedules {@link ExpireOldBugReportsJob} in garage mode. 70 * 71 * <p>Note: Garage mode is activated during shutdown. 72 */ scheduleExpireOldBugReportsJobInGarageMode(Context context)73 static void scheduleExpireOldBugReportsJobInGarageMode(Context context) { 74 JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); 75 if (jobScheduler == null) { 76 Log.w(TAG, "Cannot get JobScheduler from context."); 77 return; 78 } 79 JobInfo pendingJob = jobScheduler.getPendingJob(EXPIRE_OLD_BUG_REPORTS_JOB_ID); 80 // if there is already a pending job, do not schedule a new one. 81 if (pendingJob != null) { 82 Log.d(TAG, "Clean up job is already active, not re-scheduling"); 83 return; 84 } 85 jobScheduler.schedule(new JobInfo.Builder( 86 EXPIRE_OLD_BUG_REPORTS_JOB_ID, 87 new ComponentName(context, ExpireOldBugReportsJob.class)) 88 // Schedules the job in garage mode. 89 .setRequiresDeviceIdle(true) 90 .build()); 91 } 92 } 93