Home | History | Annotate | Download | only in os
      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