1 /* 2 * Copyright (C) 2015 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.content; 18 19 import android.app.job.JobParameters; 20 import android.app.job.JobService; 21 import android.content.Intent; 22 import android.os.Message; 23 import android.os.Messenger; 24 import android.os.RemoteException; 25 import android.util.Log; 26 import android.util.Slog; 27 import android.util.SparseArray; 28 29 public class SyncJobService extends JobService { 30 private static final String TAG = "SyncManager"; 31 32 public static final String EXTRA_MESSENGER = "messenger"; 33 34 private Messenger mMessenger; 35 private SparseArray<JobParameters> jobParamsMap = new SparseArray<JobParameters>(); 36 37 /** 38 * This service is started by the SyncManager which passes a messenger object to 39 * communicate back with it. It never stops while the device is running. 40 */ 41 @Override onStartCommand(Intent intent, int flags, int startId)42 public int onStartCommand(Intent intent, int flags, int startId) { 43 mMessenger = intent.getParcelableExtra(EXTRA_MESSENGER); 44 Message m = Message.obtain(); 45 m.what = SyncManager.SyncHandler.MESSAGE_JOBSERVICE_OBJECT; 46 m.obj = this; 47 sendMessage(m); 48 49 return START_NOT_STICKY; 50 } 51 sendMessage(Message message)52 private void sendMessage(Message message) { 53 if (mMessenger == null) { 54 Slog.e(TAG, "Messenger not initialized."); 55 return; 56 } 57 try { 58 mMessenger.send(message); 59 } catch (RemoteException e) { 60 Slog.e(TAG, e.toString()); 61 } 62 } 63 64 @Override onStartJob(JobParameters params)65 public boolean onStartJob(JobParameters params) { 66 boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); 67 synchronized (jobParamsMap) { 68 jobParamsMap.put(params.getJobId(), params); 69 } 70 Message m = Message.obtain(); 71 m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC; 72 SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras()); 73 if (op == null) { 74 Slog.e(TAG, "Got invalid job " + params.getJobId()); 75 return false; 76 } 77 if (isLoggable) { 78 Slog.v(TAG, "Got start job message " + op.target); 79 } 80 m.obj = op; 81 sendMessage(m); 82 return true; 83 } 84 85 @Override onStopJob(JobParameters params)86 public boolean onStopJob(JobParameters params) { 87 if (Log.isLoggable(TAG, Log.VERBOSE)) { 88 Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: " 89 + params.getStopReason()); 90 } 91 92 synchronized (jobParamsMap) { 93 jobParamsMap.remove(params.getJobId()); 94 } 95 Message m = Message.obtain(); 96 m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC; 97 m.obj = SyncOperation.maybeCreateFromJobExtras(params.getExtras()); 98 if (m.obj == null) { 99 return false; 100 } 101 102 // Reschedule if this job was NOT explicitly canceled. 103 m.arg1 = params.getStopReason() != JobParameters.REASON_CANCELED ? 1 : 0; 104 // Apply backoff only if stop is called due to timeout. 105 m.arg2 = params.getStopReason() == JobParameters.REASON_TIMEOUT ? 1 : 0; 106 107 sendMessage(m); 108 return false; 109 } 110 callJobFinished(int jobId, boolean needsReschedule)111 public void callJobFinished(int jobId, boolean needsReschedule) { 112 synchronized (jobParamsMap) { 113 JobParameters params = jobParamsMap.get(jobId); 114 if (params != null) { 115 jobFinished(params, needsReschedule); 116 jobParamsMap.remove(jobId); 117 } else { 118 Slog.e(TAG, "Job params not found for " + String.valueOf(jobId)); 119 } 120 } 121 } 122 }