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 post(Runnable action)32 public void post(Runnable action) { 33 postDelayed(action, 0); 34 } 35 postDelayed(Runnable action, long delayMillis)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 removeCallbacks(Runnable action)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 executeActions(Handler handler)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 size()93 public int size() { 94 return mCount; 95 } 96 getRunnable(int index)97 public Runnable getRunnable(int index) { 98 if (index >= mCount) { 99 throw new IndexOutOfBoundsException(); 100 } 101 return mActions[index].action; 102 } 103 getDelay(int index)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 HandlerAction(Runnable action, long delay)115 public HandlerAction(Runnable action, long delay) { 116 this.action = action; 117 this.delay = delay; 118 } 119 matches(Runnable otherAction)120 public boolean matches(Runnable otherAction) { 121 return otherAction == null && action == null 122 || action != null && action.equals(otherAction); 123 } 124 } 125 } 126