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