• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.view;
18 
19 import android.os.Handler;
20 import android.os.IBinder;
21 import android.os.Message;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.RemoteException;
25 
26 import java.util.HashMap;
27 
28 /**
29  * Safe identifier for a window.  This currently allows you to retrieve and observe
30  * the input focus state of the window.  Most applications will
31  * not use this, instead relying on the simpler (and more efficient) methods available
32  * on {@link View}.  This classes is useful when window input interactions need to be
33  * done across processes: the class itself is a Parcelable that can be passed to other
34  * processes for them to interact with your window, and it provides a limited safe API
35  * that doesn't allow the other process to negatively harm your window.
36  */
37 public class WindowId implements Parcelable {
38     private final IWindowId mToken;
39 
40     /**
41      * Subclass for observing changes to the focus state of an {@link WindowId}.
42      * You should use the same instance of this class for observing multiple
43      * {@link WindowId} objects, since this class is fairly heavy-weight -- the
44      * base class includes all of the mechanisms for connecting to and receiving updates
45      * from the window.
46      */
47     public static abstract class FocusObserver {
48         final IWindowFocusObserver.Stub mIObserver = new IWindowFocusObserver.Stub() {
49 
50             @Override
51             public void focusGained(IBinder inputToken) {
52                 WindowId token;
53                 synchronized (mRegistrations) {
54                     token = mRegistrations.get(inputToken);
55                 }
56                 if (mHandler != null) {
57                     mHandler.sendMessage(mHandler.obtainMessage(1, token));
58                 } else {
59                     onFocusGained(token);
60                 }
61             }
62 
63             @Override
64             public void focusLost(IBinder inputToken) {
65                 WindowId token;
66                 synchronized (mRegistrations) {
67                     token = mRegistrations.get(inputToken);
68                 }
69                 if (mHandler != null) {
70                     mHandler.sendMessage(mHandler.obtainMessage(2, token));
71                 } else {
72                     onFocusLost(token);
73                 }
74             }
75         };
76 
77         final HashMap<IBinder, WindowId> mRegistrations
78                 = new HashMap<IBinder, WindowId>();
79 
80         class H extends Handler {
81             @Override
handleMessage(Message msg)82             public void handleMessage(Message msg) {
83                 switch (msg.what) {
84                     case 1:
85                         onFocusGained((WindowId)msg.obj);
86                         break;
87                     case 2:
88                         onFocusLost((WindowId)msg.obj);
89                         break;
90                     default:
91                         super.handleMessage(msg);
92                 }
93             }
94         }
95 
96         final Handler mHandler;
97 
98         /**
99          * Construct a new observer.  This observer will be configured so that all
100          * of its callbacks are dispatched on the current calling thread.
101          */
FocusObserver()102         public FocusObserver() {
103             mHandler = new H();
104         }
105 
106         /**
107          * Called when one of the monitored windows gains input focus.
108          */
onFocusGained(WindowId token)109         public abstract void onFocusGained(WindowId token);
110 
111         /**
112          * Called when one of the monitored windows loses input focus.
113          */
onFocusLost(WindowId token)114         public abstract void onFocusLost(WindowId token);
115     }
116 
117     /**
118      * Retrieve the current focus state of the associated window.
119      */
isFocused()120     public boolean isFocused() {
121         try {
122             return mToken.isFocused();
123         } catch (RemoteException e) {
124             return false;
125         }
126     }
127 
128     /**
129      * Start monitoring for changes in the focus state of the window.
130      */
registerFocusObserver(FocusObserver observer)131     public void registerFocusObserver(FocusObserver observer) {
132         synchronized (observer.mRegistrations) {
133             if (observer.mRegistrations.containsKey(mToken.asBinder())) {
134                 throw new IllegalStateException(
135                         "Focus observer already registered with input token");
136             }
137             observer.mRegistrations.put(mToken.asBinder(), this);
138             try {
139                 mToken.registerFocusObserver(observer.mIObserver);
140             } catch (RemoteException e) {
141             }
142         }
143     }
144 
145     /**
146      * Stop monitoring changes in the focus state of the window.
147      */
unregisterFocusObserver(FocusObserver observer)148     public void unregisterFocusObserver(FocusObserver observer) {
149         synchronized (observer.mRegistrations) {
150             if (observer.mRegistrations.remove(mToken.asBinder()) == null) {
151                 throw new IllegalStateException("Focus observer not registered with input token");
152             }
153             try {
154                 mToken.unregisterFocusObserver(observer.mIObserver);
155             } catch (RemoteException e) {
156             }
157         }
158     }
159 
160     /**
161      * Comparison operator on two IntentSender objects, such that true
162      * is returned then they both represent the same operation from the
163      * same package.
164      */
165     @Override
equals(Object otherObj)166     public boolean equals(Object otherObj) {
167         if (otherObj instanceof WindowId) {
168             return mToken.asBinder().equals(((WindowId) otherObj)
169                     .mToken.asBinder());
170         }
171         return false;
172     }
173 
174     @Override
hashCode()175     public int hashCode() {
176         return mToken.asBinder().hashCode();
177     }
178 
179     @Override
toString()180     public String toString() {
181         StringBuilder sb = new StringBuilder(128);
182         sb.append("IntentSender{");
183         sb.append(Integer.toHexString(System.identityHashCode(this)));
184         sb.append(": ");
185         sb.append(mToken != null ? mToken.asBinder() : null);
186         sb.append('}');
187         return sb.toString();
188     }
189 
describeContents()190     public int describeContents() {
191         return 0;
192     }
193 
writeToParcel(Parcel out, int flags)194     public void writeToParcel(Parcel out, int flags) {
195         out.writeStrongBinder(mToken.asBinder());
196     }
197 
198     public static final Parcelable.Creator<WindowId> CREATOR
199             = new Parcelable.Creator<WindowId>() {
200         public WindowId createFromParcel(Parcel in) {
201             IBinder target = in.readStrongBinder();
202             return target != null ? new WindowId(target) : null;
203         }
204 
205         public WindowId[] newArray(int size) {
206             return new WindowId[size];
207         }
208     };
209 
210     /** @hide */
getTarget()211     public IWindowId getTarget() {
212         return mToken;
213     }
214 
215     /** @hide */
WindowId(IWindowId target)216     public WindowId(IWindowId target) {
217         mToken = target;
218     }
219 
220     /** @hide */
WindowId(IBinder target)221     public WindowId(IBinder target) {
222         mToken = IWindowId.Stub.asInterface(target);
223     }
224 }
225