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