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