1/* 2 * Copyright (C) 2017 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 */ 16package androidx.work.impl.constraints; 17 18import android.content.Context; 19import android.support.annotation.NonNull; 20import android.support.annotation.Nullable; 21import android.support.annotation.VisibleForTesting; 22import android.util.Log; 23 24import androidx.work.Constraints; 25import androidx.work.impl.constraints.controllers.BatteryChargingController; 26import androidx.work.impl.constraints.controllers.BatteryNotLowController; 27import androidx.work.impl.constraints.controllers.ConstraintController; 28import androidx.work.impl.constraints.controllers.NetworkConnectedController; 29import androidx.work.impl.constraints.controllers.NetworkMeteredController; 30import androidx.work.impl.constraints.controllers.NetworkNotRoamingController; 31import androidx.work.impl.constraints.controllers.NetworkUnmeteredController; 32import androidx.work.impl.constraints.controllers.StorageNotLowController; 33import androidx.work.impl.model.WorkSpec; 34 35import java.util.ArrayList; 36import java.util.List; 37 38/** 39 * Tracks {@link WorkSpec}s and their {@link Constraints}, and notifies an optional 40 * {@link WorkConstraintsCallback} when all of their constraints are met or not met. 41 */ 42 43public class WorkConstraintsTracker implements ConstraintController.OnConstraintUpdatedCallback { 44 45 private static final String TAG = "WorkConstraintsTracker"; 46 47 @Nullable private final WorkConstraintsCallback mCallback; 48 private final ConstraintController[] mConstraintControllers; 49 50 /** 51 * @param context The application {@link Context} 52 * @param callback The callback is only necessary when you need {@link WorkConstraintsTracker} 53 * to notify you about changes in constraints for the list of {@link 54 * WorkSpec}'s that it is tracking. 55 */ 56 public WorkConstraintsTracker(Context context, @Nullable WorkConstraintsCallback callback) { 57 Context appContext = context.getApplicationContext(); 58 mCallback = callback; 59 mConstraintControllers = new ConstraintController[] { 60 new BatteryChargingController(appContext, this), 61 new BatteryNotLowController(appContext, this), 62 new StorageNotLowController(appContext, this), 63 new NetworkConnectedController(appContext, this), 64 new NetworkUnmeteredController(appContext, this), 65 new NetworkNotRoamingController(appContext, this), 66 new NetworkMeteredController(appContext, this) 67 }; 68 } 69 70 @VisibleForTesting 71 WorkConstraintsTracker( 72 @Nullable WorkConstraintsCallback callback, 73 ConstraintController[] controllers) { 74 75 mCallback = callback; 76 mConstraintControllers = controllers; 77 } 78 79 /** 80 * Replaces the list of tracked {@link WorkSpec}s to monitor if their constraints are met. 81 * 82 * @param workSpecs A list of {@link WorkSpec}s to monitor constraints for 83 */ 84 public void replace(@NonNull List<WorkSpec> workSpecs) { 85 for (ConstraintController controller : mConstraintControllers) { 86 controller.replace(workSpecs); 87 } 88 } 89 90 /** 91 * Resets and clears all tracked {@link WorkSpec}s. 92 */ 93 public void reset() { 94 for (ConstraintController controller : mConstraintControllers) { 95 controller.reset(); 96 } 97 } 98 99 /** 100 * Returns <code>true</code> if all the underlying constraints for a given WorkSpec are met. 101 * 102 * @param workSpecId The {@link WorkSpec} id 103 * @return <code>true</code> if all the underlying constraints for a given {@link WorkSpec} are 104 * met. 105 */ 106 public boolean areAllConstraintsMet(@NonNull String workSpecId) { 107 for (ConstraintController constraintController : mConstraintControllers) { 108 if (constraintController.isWorkSpecConstrained(workSpecId)) { 109 Log.d(TAG, String.format("Work %s constrained by %s", workSpecId, 110 constraintController.getClass().getSimpleName())); 111 return false; 112 } 113 } 114 return true; 115 } 116 117 @Override 118 public void onConstraintMet(@NonNull List<String> workSpecIds) { 119 List<String> unconstrainedWorkSpecIds = new ArrayList<>(); 120 for (String workSpecId : workSpecIds) { 121 if (areAllConstraintsMet(workSpecId)) { 122 Log.d(TAG, String.format("Constraints met for %s", workSpecId)); 123 unconstrainedWorkSpecIds.add(workSpecId); 124 } 125 } 126 if (mCallback != null) { 127 mCallback.onAllConstraintsMet(unconstrainedWorkSpecIds); 128 } 129 } 130 131 @Override 132 public void onConstraintNotMet(@NonNull List<String> workSpecIds) { 133 if (mCallback != null) { 134 mCallback.onAllConstraintsNotMet(workSpecIds); 135 } 136 } 137} 138