/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.recents.misc; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import java.util.ArrayList; /** * A ref counted trigger that does some logic when the count is first incremented, or last * decremented. Not thread safe as it's not currently needed. */ public class ReferenceCountedTrigger { int mCount; ArrayList mFirstIncRunnables = new ArrayList<>(); ArrayList mLastDecRunnables = new ArrayList<>(); Runnable mErrorRunnable; // Convenience runnables Runnable mIncrementRunnable = new Runnable() { @Override public void run() { increment(); } }; Runnable mDecrementRunnable = new Runnable() { @Override public void run() { decrement(); } }; public ReferenceCountedTrigger() { this(null, null, null); } public ReferenceCountedTrigger(Runnable firstIncRunnable, Runnable lastDecRunnable, Runnable errorRunanable) { if (firstIncRunnable != null) mFirstIncRunnables.add(firstIncRunnable); if (lastDecRunnable != null) mLastDecRunnables.add(lastDecRunnable); mErrorRunnable = errorRunanable; } /** Increments the ref count */ public void increment() { if (mCount == 0 && !mFirstIncRunnables.isEmpty()) { int numRunnables = mFirstIncRunnables.size(); for (int i = 0; i < numRunnables; i++) { mFirstIncRunnables.get(i).run(); } } mCount++; } /** Convenience method to increment this trigger as a runnable */ public Runnable incrementAsRunnable() { return mIncrementRunnable; } /** Adds a runnable to the last-decrement runnables list. */ public void addLastDecrementRunnable(Runnable r) { mLastDecRunnables.add(r); } /** Decrements the ref count */ public void decrement() { mCount--; if (mCount == 0) { flushLastDecrementRunnables(); } else if (mCount < 0) { if (mErrorRunnable != null) { mErrorRunnable.run(); } else { throw new RuntimeException("Invalid ref count"); } } } /** * Runs and clears all the last-decrement runnables now. */ public void flushLastDecrementRunnables() { if (!mLastDecRunnables.isEmpty()) { int numRunnables = mLastDecRunnables.size(); for (int i = 0; i < numRunnables; i++) { mLastDecRunnables.get(i).run(); } } mLastDecRunnables.clear(); } /** * Convenience method to decrement this trigger as a animator listener. This listener is * guarded to prevent being called back multiple times, and will trigger a decrement once and * only once. */ public Animator.AnimatorListener decrementOnAnimationEnd() { return new AnimatorListenerAdapter() { private boolean hasEnded; @Override public void onAnimationEnd(Animator animation) { if (hasEnded) return; decrement(); hasEnded = true; } }; } /** Returns the current ref count */ public int getCount() { return mCount; } }