1 /* 2 * Copyright (C) 2006 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.os; 18 19 /** @hide */ 20 public class Broadcaster 21 { 22 public Broadcaster() 23 { 24 } 25 26 /** 27 * Sign up for notifications about something. 28 * 29 * When this broadcaster pushes a message with senderWhat in the what field, 30 * target will be sent a copy of that message with targetWhat in the what field. 31 */ 32 public void request(int senderWhat, Handler target, int targetWhat) 33 { 34 synchronized (this) { 35 Registration r = null; 36 if (mReg == null) { 37 r = new Registration(); 38 r.senderWhat = senderWhat; 39 r.targets = new Handler[1]; 40 r.targetWhats = new int[1]; 41 r.targets[0] = target; 42 r.targetWhats[0] = targetWhat; 43 mReg = r; 44 r.next = r; 45 r.prev = r; 46 } else { 47 // find its place in the map 48 Registration start = mReg; 49 r = start; 50 do { 51 if (r.senderWhat >= senderWhat) { 52 break; 53 } 54 r = r.next; 55 } while (r != start); 56 int n; 57 if (r.senderWhat != senderWhat) { 58 // we didn't find a senderWhat match, but r is right 59 // after where it goes 60 Registration reg = new Registration(); 61 reg.senderWhat = senderWhat; 62 reg.targets = new Handler[1]; 63 reg.targetWhats = new int[1]; 64 reg.next = r; 65 reg.prev = r.prev; 66 r.prev.next = reg; 67 r.prev = reg; 68 69 if (r == mReg && r.senderWhat > reg.senderWhat) { 70 mReg = reg; 71 } 72 73 r = reg; 74 n = 0; 75 } else { 76 n = r.targets.length; 77 Handler[] oldTargets = r.targets; 78 int[] oldWhats = r.targetWhats; 79 // check for duplicates, and don't do it if we are dup. 80 for (int i=0; i<n; i++) { 81 if (oldTargets[i] == target && oldWhats[i] == targetWhat) { 82 return; 83 } 84 } 85 r.targets = new Handler[n+1]; 86 System.arraycopy(oldTargets, 0, r.targets, 0, n); 87 r.targetWhats = new int[n+1]; 88 System.arraycopy(oldWhats, 0, r.targetWhats, 0, n); 89 } 90 r.targets[n] = target; 91 r.targetWhats[n] = targetWhat; 92 } 93 } 94 } 95 96 /** 97 * Unregister for notifications for this senderWhat/target/targetWhat tuple. 98 */ 99 public void cancelRequest(int senderWhat, Handler target, int targetWhat) 100 { 101 synchronized (this) { 102 Registration start = mReg; 103 Registration r = start; 104 105 if (r == null) { 106 return; 107 } 108 109 do { 110 if (r.senderWhat >= senderWhat) { 111 break; 112 } 113 r = r.next; 114 } while (r != start); 115 116 if (r.senderWhat == senderWhat) { 117 Handler[] targets = r.targets; 118 int[] whats = r.targetWhats; 119 int oldLen = targets.length; 120 for (int i=0; i<oldLen; i++) { 121 if (targets[i] == target && whats[i] == targetWhat) { 122 r.targets = new Handler[oldLen-1]; 123 r.targetWhats = new int[oldLen-1]; 124 if (i > 0) { 125 System.arraycopy(targets, 0, r.targets, 0, i); 126 System.arraycopy(whats, 0, r.targetWhats, 0, i); 127 } 128 129 int remainingLen = oldLen-i-1; 130 if (remainingLen != 0) { 131 System.arraycopy(targets, i+1, r.targets, i, 132 remainingLen); 133 System.arraycopy(whats, i+1, r.targetWhats, i, 134 remainingLen); 135 } 136 break; 137 } 138 } 139 } 140 } 141 } 142 143 /** 144 * For debugging purposes, print the registrations to System.out 145 */ 146 public void dumpRegistrations() 147 { 148 synchronized (this) { 149 Registration start = mReg; 150 System.out.println("Broadcaster " + this + " {"); 151 if (start != null) { 152 Registration r = start; 153 do { 154 System.out.println(" senderWhat=" + r.senderWhat); 155 int n = r.targets.length; 156 for (int i=0; i<n; i++) { 157 System.out.println(" [" + r.targetWhats[i] 158 + "] " + r.targets[i]); 159 } 160 r = r.next; 161 } while (r != start); 162 } 163 System.out.println("}"); 164 } 165 } 166 167 /** 168 * Send out msg. Anyone who has registered via the request() method will be 169 * sent the message. 170 */ 171 public void broadcast(Message msg) 172 { 173 synchronized (this) { 174 if (mReg == null) { 175 return; 176 } 177 178 int senderWhat = msg.what; 179 Registration start = mReg; 180 Registration r = start; 181 do { 182 if (r.senderWhat >= senderWhat) { 183 break; 184 } 185 r = r.next; 186 } while (r != start); 187 if (r.senderWhat == senderWhat) { 188 Handler[] targets = r.targets; 189 int[] whats = r.targetWhats; 190 int n = targets.length; 191 for (int i=0; i<n; i++) { 192 Handler target = targets[i]; 193 Message m = Message.obtain(); 194 m.copyFrom(msg); 195 m.what = whats[i]; 196 target.sendMessage(m); 197 } 198 } 199 } 200 } 201 202 private class Registration 203 { 204 Registration next; 205 Registration prev; 206 207 int senderWhat; 208 Handler[] targets; 209 int[] targetWhats; 210 } 211 private Registration mReg; 212 } 213