1 /*
2  * Copyright (C) 2014 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.backup;
18 
19 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
20 
21 import android.app.job.JobInfo;
22 import android.app.job.JobParameters;
23 import android.app.job.JobScheduler;
24 import android.app.job.JobService;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.pm.PackageManager;
28 import android.os.Bundle;
29 import android.util.SparseArray;
30 
31 import com.android.internal.annotations.GuardedBy;
32 import com.android.internal.annotations.VisibleForTesting;
33 
34 public class FullBackupJob extends JobService {
35     private static final String USER_ID_EXTRA_KEY = "userId";
36 
37     @VisibleForTesting
38     public static final int MIN_JOB_ID = 52418896;
39     @VisibleForTesting
40     public static final int MAX_JOB_ID = 52419896;
41 
42     private static ComponentName sIdleService =
43             new ComponentName(PLATFORM_PACKAGE_NAME, FullBackupJob.class.getName());
44 
45     @GuardedBy("mParamsForUser")
46     private final SparseArray<JobParameters> mParamsForUser = new SparseArray<>();
47 
schedule(int userId, Context ctx, long minDelay, UserBackupManagerService userBackupManagerService)48     public static void schedule(int userId, Context ctx, long minDelay,
49             UserBackupManagerService userBackupManagerService) {
50         if (!userBackupManagerService.isFrameworkSchedulingEnabled()) return;
51 
52         JobScheduler js = (JobScheduler) ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE);
53         JobInfo.Builder builder = new JobInfo.Builder(getJobIdForUserId(userId), sIdleService);
54         final BackupManagerConstants constants = userBackupManagerService.getConstants();
55         synchronized (constants) {
56             builder.setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
57                     .setRequiresCharging(constants.getFullBackupRequireCharging());
58         }
59         if (minDelay > 0) {
60             builder.setMinimumLatency(minDelay);
61         }
62         if (!ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
63             builder.setRequiresDeviceIdle(true);
64         }
65 
66         Bundle extraInfo = new Bundle();
67         extraInfo.putInt(USER_ID_EXTRA_KEY, userId);
68         builder.setTransientExtras(extraInfo);
69 
70         js.schedule(builder.build());
71     }
72 
cancel(int userId, Context ctx)73     public static void cancel(int userId, Context ctx) {
74         JobScheduler js = (JobScheduler) ctx.getSystemService(
75                 Context.JOB_SCHEDULER_SERVICE);
76         js.cancel(getJobIdForUserId(userId));
77     }
78 
79     // callback from the Backup Manager Service: it's finished its work for this pass
finishBackupPass(int userId)80     public void finishBackupPass(int userId) {
81         synchronized (mParamsForUser) {
82             JobParameters jobParameters = mParamsForUser.get(userId);
83             if (jobParameters != null) {
84                 jobFinished(jobParameters, false);
85                 mParamsForUser.remove(userId);
86             }
87         }
88     }
89 
90     // ----- scheduled job interface -----
91 
92     @Override
onStartJob(JobParameters params)93     public boolean onStartJob(JobParameters params) {
94         int userId = params.getTransientExtras().getInt(USER_ID_EXTRA_KEY);
95 
96         synchronized (mParamsForUser) {
97             mParamsForUser.put(userId, params);
98         }
99 
100         BackupManagerService service = BackupManagerService.getInstance();
101         return service.beginFullBackup(userId, this);
102     }
103 
104     @Override
onStopJob(JobParameters params)105     public boolean onStopJob(JobParameters params) {
106         int userId = params.getTransientExtras().getInt(USER_ID_EXTRA_KEY);
107 
108         synchronized (mParamsForUser) {
109             if (mParamsForUser.removeReturnOld(userId) == null) {
110                 return false;
111             }
112         }
113 
114         BackupManagerService service = BackupManagerService.getInstance();
115         service.endFullBackup(userId);
116 
117         return false;
118     }
119 
120     @VisibleForTesting
getJobIdForUserId(int userId)121     static int getJobIdForUserId(int userId) {
122         return JobIdManager.getJobIdForUserId(MIN_JOB_ID, MAX_JOB_ID, userId);
123     }
124 }
125