Home | History | Annotate | Download | only in misc
      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 
     22 import java.util.ArrayList;
     23 
     24 /**
     25  * A ref counted trigger that does some logic when the count is first incremented, or last
     26  * decremented.  Not thread safe as it's not currently needed.
     27  */
     28 public class ReferenceCountedTrigger {
     29 
     30     int mCount;
     31     ArrayList<Runnable> mFirstIncRunnables = new ArrayList<>();
     32     ArrayList<Runnable> mLastDecRunnables = new ArrayList<>();
     33     Runnable mErrorRunnable;
     34 
     35     // Convenience runnables
     36     Runnable mIncrementRunnable = new Runnable() {
     37         @Override
     38         public void run() {
     39             increment();
     40         }
     41     };
     42     Runnable mDecrementRunnable = new Runnable() {
     43         @Override
     44         public void run() {
     45             decrement();
     46         }
     47     };
     48 
     49     public ReferenceCountedTrigger() {
     50         this(null, null, null);
     51     }
     52 
     53     public ReferenceCountedTrigger(Runnable firstIncRunnable, Runnable lastDecRunnable,
     54             Runnable errorRunanable) {
     55         if (firstIncRunnable != null) mFirstIncRunnables.add(firstIncRunnable);
     56         if (lastDecRunnable != null) mLastDecRunnables.add(lastDecRunnable);
     57         mErrorRunnable = errorRunanable;
     58     }
     59 
     60     /** Increments the ref count */
     61     public void increment() {
     62         if (mCount == 0 && !mFirstIncRunnables.isEmpty()) {
     63             int numRunnables = mFirstIncRunnables.size();
     64             for (int i = 0; i < numRunnables; i++) {
     65                 mFirstIncRunnables.get(i).run();
     66             }
     67         }
     68         mCount++;
     69     }
     70 
     71     /** Convenience method to increment this trigger as a runnable */
     72     public Runnable incrementAsRunnable() {
     73         return mIncrementRunnable;
     74     }
     75 
     76     /** Adds a runnable to the last-decrement runnables list. */
     77     public void addLastDecrementRunnable(Runnable r) {
     78         mLastDecRunnables.add(r);
     79     }
     80 
     81     /** Decrements the ref count */
     82     public void decrement() {
     83         mCount--;
     84         if (mCount == 0) {
     85             flushLastDecrementRunnables();
     86         } else if (mCount < 0) {
     87             if (mErrorRunnable != null) {
     88                 mErrorRunnable.run();
     89             } else {
     90                 throw new RuntimeException("Invalid ref count");
     91             }
     92         }
     93     }
     94 
     95     /**
     96      * Runs and clears all the last-decrement runnables now.
     97      */
     98     public void flushLastDecrementRunnables() {
     99         if (!mLastDecRunnables.isEmpty()) {
    100             int numRunnables = mLastDecRunnables.size();
    101             for (int i = 0; i < numRunnables; i++) {
    102                 mLastDecRunnables.get(i).run();
    103             }
    104         }
    105         mLastDecRunnables.clear();
    106     }
    107 
    108     /**
    109      * Convenience method to decrement this trigger as a animator listener.  This listener is
    110      * guarded to prevent being called back multiple times, and will trigger a decrement once and
    111      * only once.
    112      */
    113     public Animator.AnimatorListener decrementOnAnimationEnd() {
    114         return new AnimatorListenerAdapter() {
    115             private boolean hasEnded;
    116 
    117             @Override
    118             public void onAnimationEnd(Animator animation) {
    119                 if (hasEnded) return;
    120                 decrement();
    121                 hasEnded = true;
    122             }
    123         };
    124     }
    125 
    126     /** Returns the current ref count */
    127     public int getCount() {
    128         return mCount;
    129     }
    130 }
    131