184bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria/*
284bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * Copyright (C) 2017 The Android Open Source Project
384bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria *
484bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * Licensed under the Apache License, Version 2.0 (the "License");
584bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * you may not use this file except in compliance with the License.
684bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * You may obtain a copy of the License at
784bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria *
884bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria *      http://www.apache.org/licenses/LICENSE-2.0
984bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria *
1084bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * Unless required by applicable law or agreed to in writing, software
1184bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * distributed under the License is distributed on an "AS IS" BASIS,
1284bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * See the License for the specific language governing permissions and
1484bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria * limitations under the License.
1584bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria */
16564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariapackage androidx.work.impl.constraints.trackers;
1784bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria
1884bf2b003b4c3d55288183d4200ea78662990a43Sumir Katariaimport android.content.Context;
19e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumarimport android.support.annotation.RestrictTo;
20697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumarimport android.util.Log;
217fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria
22564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariaimport androidx.work.impl.constraints.ConstraintListener;
23564e43098c323d1a90be53c190b8fdbdde973505Sumir Kataria
24b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.util.LinkedHashSet;
25b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport java.util.Set;
26b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria
2784bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria/**
28ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin * A base for tracking constraints and notifying listeners of changes.
2968385f75b98d09b5398057a61e63e27fbd92917eSumir Kataria *
30a0d0d16f358a6cd71033a9d12c934c1c90b07973Xyan Bhatnagar * @param <T> the constraint data type observed by this tracker
31e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar * @hide
3284bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria */
33e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
34a0d0d16f358a6cd71033a9d12c934c1c90b07973Xyan Bhatnagarpublic abstract class ConstraintTracker<T> {
3584bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria
364dbbc6577d0ca29ce65be714221cfda9c19b37e3Sumir Kataria    private static final String TAG = "ConstraintTracker";
374dbbc6577d0ca29ce65be714221cfda9c19b37e3Sumir Kataria
3847bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar    protected final Context mAppContext;
3947bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar    private final Set<ConstraintListener<T>> mListeners = new LinkedHashSet<>();
4047bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar    private T mCurrentState;
4184bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria
42ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin    ConstraintTracker(Context context) {
4384bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria        mAppContext = context.getApplicationContext();
4484bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria    }
4584bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria
4684bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria    /**
4768385f75b98d09b5398057a61e63e27fbd92917eSumir Kataria     * Add the given listener for tracking.
4847bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     * This may cause {@link #getInitialState()} and {@link #startTracking()} to be invoked.
4947bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     * If a state is set, this will immediately notify the given listener.
507fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria     *
511b58a02b857bf59a52a702dd30f31db9a152f19bJan Clarin     * @param listener The target listener to start notifying
527fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria     */
53a0d0d16f358a6cd71033a9d12c934c1c90b07973Xyan Bhatnagar    public void addListener(ConstraintListener<T> listener) {
54ec90b1f272eec4e713bb17c8e73cc810ec89e69fSumir Kataria        if (mListeners.add(listener)) {
55ec90b1f272eec4e713bb17c8e73cc810ec89e69fSumir Kataria            if (mListeners.size() == 1) {
5647bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar                mCurrentState = getInitialState();
57697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                Log.d(TAG, String.format("%s: initial state = %s", getClass().getSimpleName(),
58697d6a4a3797bc71d0dd8685937a318e9934066bRahul Ravikumar                        mCurrentState));
59ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin                startTracking();
60ec90b1f272eec4e713bb17c8e73cc810ec89e69fSumir Kataria            }
61a20fe146d0b328cc012b110562ca5ff1a456b758Xyan Bhatnagar            listener.onConstraintChanged(mCurrentState);
627fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria        }
637fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria    }
647fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria
657fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria    /**
6668385f75b98d09b5398057a61e63e27fbd92917eSumir Kataria     * Remove the given listener from tracking.
677fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria     *
681b58a02b857bf59a52a702dd30f31db9a152f19bJan Clarin     * @param listener The listener to stop notifying.
697fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria     */
70a0d0d16f358a6cd71033a9d12c934c1c90b07973Xyan Bhatnagar    public void removeListener(ConstraintListener<T> listener) {
7168385f75b98d09b5398057a61e63e27fbd92917eSumir Kataria        if (mListeners.remove(listener) && mListeners.isEmpty()) {
72ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin            stopTracking();
737fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria        }
747fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria    }
757fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria
767fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria    /**
7747bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     * Sets the state of the constraint.
7847bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     * If state is has not changed, nothing happens.
7947bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     *
8047bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     * @param newState new state of constraint
811b58a02b857bf59a52a702dd30f31db9a152f19bJan Clarin     */
82a20fe146d0b328cc012b110562ca5ff1a456b758Xyan Bhatnagar    public void setState(T newState) {
83a20fe146d0b328cc012b110562ca5ff1a456b758Xyan Bhatnagar        if (mCurrentState == newState
84a20fe146d0b328cc012b110562ca5ff1a456b758Xyan Bhatnagar                || (mCurrentState != null && mCurrentState.equals(newState))) {
8547bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar            return;
8647bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar        }
8747bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar        mCurrentState = newState;
8847bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar        for (ConstraintListener<T> listener : mListeners) {
8947bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar            listener.onConstraintChanged(mCurrentState);
9047bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar        }
9147bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar    }
921b58a02b857bf59a52a702dd30f31db9a152f19bJan Clarin
931b58a02b857bf59a52a702dd30f31db9a152f19bJan Clarin    /**
9447bc9f58bf013dcb40ba1ee33f72c196d5e3001aXyan Bhatnagar     * Determines the initial state of the constraint being tracked.
9584bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria     */
96e92262ff56fedd7753af56e777e38e07894210e6Rahul Ravikumar    public abstract T getInitialState();
9784bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria
9884bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria    /**
99ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin     * Start tracking for constraint state changes.
10084bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria     */
101ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin    public abstract void startTracking();
1027fb168b3260f5ec8e4178fd34ef46403445f090cSumir Kataria
103478f69f4efa7afab7f8bcff0d9f0800485f272eeSumir Kataria    /**
104ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin     * Stop tracking for constraint state changes.
105478f69f4efa7afab7f8bcff0d9f0800485f272eeSumir Kataria     */
106ea3c3af4150c20d63d0aaaa721b3304baae254c6Jan Clarin    public abstract void stopTracking();
10784bf2b003b4c3d55288183d4200ea78662990a43Sumir Kataria}
108