Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2015 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 android.view;
     18 
     19 import android.os.Handler;
     20 
     21 import com.android.internal.util.GrowingArrayUtils;
     22 
     23 /**
     24  * Class used to enqueue pending work from Views when no Handler is attached.
     25  *
     26  * @hide Exposed for test framework only.
     27  */
     28 public class HandlerActionQueue {
     29     private HandlerAction[] mActions;
     30     private int mCount;
     31 
     32     public void post(Runnable action) {
     33         postDelayed(action, 0);
     34     }
     35 
     36     public void postDelayed(Runnable action, long delayMillis) {
     37         final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
     38 
     39         synchronized (this) {
     40             if (mActions == null) {
     41                 mActions = new HandlerAction[4];
     42             }
     43             mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
     44             mCount++;
     45         }
     46     }
     47 
     48     public void removeCallbacks(Runnable action) {
     49         synchronized (this) {
     50             final int count = mCount;
     51             int j = 0;
     52 
     53             final HandlerAction[] actions = mActions;
     54             for (int i = 0; i < count; i++) {
     55                 if (actions[i].matches(action)) {
     56                     // Remove this action by overwriting it within
     57                     // this loop or nulling it out later.
     58                     continue;
     59                 }
     60 
     61                 if (j != i) {
     62                     // At least one previous entry was removed, so
     63                     // this one needs to move to the "new" list.
     64                     actions[j] = actions[i];
     65                 }
     66 
     67                 j++;
     68             }
     69 
     70             // The "new" list only has j entries.
     71             mCount = j;
     72 
     73             // Null out any remaining entries.
     74             for (; j < count; j++) {
     75                 actions[j] = null;
     76             }
     77         }
     78     }
     79 
     80     public void executeActions(Handler handler) {
     81         synchronized (this) {
     82             final HandlerAction[] actions = mActions;
     83             for (int i = 0, count = mCount; i < count; i++) {
     84                 final HandlerAction handlerAction = actions[i];
     85                 handler.postDelayed(handlerAction.action, handlerAction.delay);
     86             }
     87 
     88             mActions = null;
     89             mCount = 0;
     90         }
     91     }
     92 
     93     public int size() {
     94         return mCount;
     95     }
     96 
     97     public Runnable getRunnable(int index) {
     98         if (index >= mCount) {
     99             throw new IndexOutOfBoundsException();
    100         }
    101         return mActions[index].action;
    102     }
    103 
    104     public long getDelay(int index) {
    105         if (index >= mCount) {
    106             throw new IndexOutOfBoundsException();
    107         }
    108         return mActions[index].delay;
    109     }
    110 
    111     private static class HandlerAction {
    112         final Runnable action;
    113         final long delay;
    114 
    115         public HandlerAction(Runnable action, long delay) {
    116             this.action = action;
    117             this.delay = delay;
    118         }
    119 
    120         public boolean matches(Runnable otherAction) {
    121             return otherAction == null && action == null
    122                     || action != null && action.equals(otherAction);
    123         }
    124     }
    125 }
    126