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