• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ondevicepersonalization.services.download;
18 
19 import static android.app.job.JobScheduler.RESULT_FAILURE;
20 import static android.content.pm.PackageManager.GET_META_DATA;
21 
22 import android.app.job.JobInfo;
23 import android.app.job.JobParameters;
24 import android.app.job.JobScheduler;
25 import android.app.job.JobService;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.pm.PackageInfo;
29 import android.content.pm.PackageManager;
30 import android.util.Log;
31 
32 import com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig;
33 import com.android.ondevicepersonalization.services.OnDevicePersonalizationExecutors;
34 import com.android.ondevicepersonalization.services.manifest.AppManifestConfigHelper;
35 
36 import com.google.common.util.concurrent.Futures;
37 import com.google.common.util.concurrent.ListenableFuture;
38 
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 /**
43  * JobService to handle the processing of the downloaded vendor data
44  */
45 public class OnDevicePersonalizationDownloadProcessingJobService extends JobService {
46     public static final String TAG = "OnDevicePersonalizationDownloadProcessingJobService";
47     private List<ListenableFuture<Void>> mFutures;
48 
49     /**
50      * Schedules a unique instance of OnDevicePersonalizationDownloadProcessingJobService to be run.
51      */
schedule(Context context)52     public static int schedule(Context context) {
53         JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
54         if (jobScheduler.getPendingJob(
55                 OnDevicePersonalizationConfig.DOWNLOAD_PROCESSING_TASK_JOB_ID) != null) {
56             Log.d(TAG, "Job is already scheduled. Doing nothing,");
57             return RESULT_FAILURE;
58         }
59         ComponentName serviceComponent = new ComponentName(context,
60                 OnDevicePersonalizationDownloadProcessingJobService.class);
61         JobInfo.Builder builder = new JobInfo.Builder(
62                 OnDevicePersonalizationConfig.DOWNLOAD_PROCESSING_TASK_JOB_ID, serviceComponent);
63 
64         // Constraints.
65         builder.setRequiresDeviceIdle(true);
66         builder.setRequiresBatteryNotLow(true);
67         builder.setRequiresStorageNotLow(true);
68         builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
69 
70         return jobScheduler.schedule(builder.build());
71     }
72 
73     @Override
onStartJob(JobParameters params)74     public boolean onStartJob(JobParameters params) {
75         Log.d(TAG, "onStartJob()");
76         mFutures = new ArrayList<>();
77         for (PackageInfo packageInfo : this.getPackageManager().getInstalledPackages(
78                 PackageManager.PackageInfoFlags.of(GET_META_DATA))) {
79             String packageName = packageInfo.packageName;
80             if (AppManifestConfigHelper.manifestContainsOdpSettings(
81                     this, packageName)) {
82                 mFutures.add(Futures.submitAsync(
83                         new OnDevicePersonalizationDataProcessingAsyncCallable(packageName,
84                                 this),
85                         OnDevicePersonalizationExecutors.getBackgroundExecutor()));
86             }
87         }
88         Futures.whenAllComplete(mFutures).call(() -> {
89             jobFinished(params, /* wantsReschedule */ false);
90             return null;
91         }, OnDevicePersonalizationExecutors.getLightweightExecutor());
92 
93         return true;
94     }
95 
96     @Override
onStopJob(JobParameters params)97     public boolean onStopJob(JobParameters params) {
98         if (mFutures != null) {
99             for (ListenableFuture<Void> f : mFutures) {
100                 f.cancel(true);
101             }
102         }
103         // Reschedule the job since it ended before finishing
104         return true;
105     }
106 }
107