1 /* 2 * Copyright (C) 2014 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.systemui.recents.misc; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorListenerAdapter; 21 import android.content.Context; 22 23 import java.util.ArrayList; 24 25 /** 26 * A ref counted trigger that does some logic when the count is first incremented, or last 27 * decremented. Not thread safe as it's not currently needed. 28 */ 29 public class ReferenceCountedTrigger { 30 31 Context mContext; 32 int mCount; 33 ArrayList<Runnable> mFirstIncRunnables = new ArrayList<Runnable>(); 34 ArrayList<Runnable> mLastDecRunnables = new ArrayList<Runnable>(); 35 Runnable mErrorRunnable; 36 37 // Convenience runnables 38 Runnable mIncrementRunnable = new Runnable() { 39 @Override 40 public void run() { 41 increment(); 42 } 43 }; 44 Runnable mDecrementRunnable = new Runnable() { 45 @Override 46 public void run() { 47 decrement(); 48 } 49 }; 50 51 public ReferenceCountedTrigger(Context context, Runnable firstIncRunnable, 52 Runnable lastDecRunnable, Runnable errorRunanable) { 53 mContext = context; 54 if (firstIncRunnable != null) mFirstIncRunnables.add(firstIncRunnable); 55 if (lastDecRunnable != null) mLastDecRunnables.add(lastDecRunnable); 56 mErrorRunnable = errorRunanable; 57 } 58 59 /** Increments the ref count */ 60 public void increment() { 61 if (mCount == 0 && !mFirstIncRunnables.isEmpty()) { 62 int numRunnables = mFirstIncRunnables.size(); 63 for (int i = 0; i < numRunnables; i++) { 64 mFirstIncRunnables.get(i).run(); 65 } 66 } 67 mCount++; 68 } 69 70 /** Convenience method to increment this trigger as a runnable */ 71 public Runnable incrementAsRunnable() { 72 return mIncrementRunnable; 73 } 74 75 /** Adds a runnable to the last-decrement runnables list. */ 76 public void addLastDecrementRunnable(Runnable r) { 77 // To ensure that the last decrement always calls, we increment and decrement after setting 78 // the last decrement runnable 79 boolean ensureLastDecrement = (mCount == 0); 80 if (ensureLastDecrement) increment(); 81 mLastDecRunnables.add(r); 82 if (ensureLastDecrement) decrement(); 83 } 84 85 /** Decrements the ref count */ 86 public void decrement() { 87 mCount--; 88 if (mCount == 0 && !mLastDecRunnables.isEmpty()) { 89 int numRunnables = mLastDecRunnables.size(); 90 for (int i = 0; i < numRunnables; i++) { 91 mLastDecRunnables.get(i).run(); 92 } 93 } else if (mCount < 0) { 94 if (mErrorRunnable != null) { 95 mErrorRunnable.run(); 96 } else { 97 new Throwable("Invalid ref count").printStackTrace(); 98 Console.logError(mContext, "Invalid ref count"); 99 } 100 } 101 } 102 103 /** Convenience method to decrement this trigger as a runnable. */ 104 public Runnable decrementAsRunnable() { 105 return mDecrementRunnable; 106 } 107 /** Convenience method to decrement this trigger as a animator listener. */ 108 public Animator.AnimatorListener decrementOnAnimationEnd() { 109 return new AnimatorListenerAdapter() { 110 @Override 111 public void onAnimationEnd(Animator animation) { 112 decrement(); 113 } 114 }; 115 } 116 117 /** Returns the current ref count */ 118 public int getCount() { 119 return mCount; 120 } 121 } 122