• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.cts;
18 
19 import dalvik.annotation.TestLevel;
20 import dalvik.annotation.TestTargetClass;
21 import dalvik.annotation.TestTargetNew;
22 import dalvik.annotation.TestTargets;
23 
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.ServiceConnection;
28 import android.os.Handler;
29 import android.os.HandlerThread;
30 import android.os.IBinder;
31 import android.os.IInterface;
32 import android.os.Looper;
33 import android.os.Message;
34 import android.os.Messenger;
35 import android.os.Parcel;
36 import android.os.RemoteException;
37 import android.test.AndroidTestCase;
38 
39 import java.io.FileDescriptor;
40 
41 @TestTargetClass(Messenger.class)
42 public class MessengerTest extends AndroidTestCase {
43 
44     private Messenger mMessenger;
45     private Message mMessage;
46     private boolean mResult;
47     private Messenger mServiceMessenger;
48     private static final int MSG_ARG1 = 100;
49     private static final int MSG_ARG2 = 1000;
50     private static final int WHAT = 2008;
51     private Handler mHandler = new Handler() {
52         @Override
53         public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
54             mResult = true;
55             mMessage = msg;
56             return super.sendMessageAtTime(msg, uptimeMillis);
57         }
58     };
59 
60     private final IBinder mIBinder = new IBinder() {
61 
62         public String getInterfaceDescriptor() throws RemoteException {
63             return null;
64         }
65 
66         public boolean isBinderAlive() {
67             return false;
68         }
69 
70         public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException {
71         }
72 
73         public boolean pingBinder() {
74             return false;
75         }
76 
77         public IInterface queryLocalInterface(String descriptor) {
78             return null;
79         }
80 
81         public boolean transact(int code, Parcel data, Parcel reply, int flags)
82                 throws RemoteException {
83             return false;
84         }
85 
86         public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
87             return false;
88         }
89 
90         public void dump(FileDescriptor fd, String[] args) throws RemoteException {
91         }
92 
93     };
94 
95     // Create another messenger to send msg.
96     private ServiceConnection mConnection = new ServiceConnection() {
97         public void onServiceConnected(ComponentName name, IBinder service) {
98             synchronized (MessengerTest.this) {
99                 mServiceMessenger = new Messenger(service);
100                 MessengerTest.this.notifyAll();
101             }
102         }
103 
104         public void onServiceDisconnected(ComponentName name) {
105             mServiceMessenger = null;
106         }
107     };
108 
109     @Override
setUp()110     protected void setUp() throws Exception {
111 
112         super.setUp();
113         mMessenger = new Messenger(mHandler);
114         getContext().bindService(new Intent(mContext, MessengerService.class), mConnection,
115                 Context.BIND_AUTO_CREATE);
116         synchronized (this) {
117             while (mServiceMessenger == null) {
118                 wait();
119             }
120         }
121     }
122 
123     @Override
tearDown()124     protected void tearDown() throws Exception {
125         super.tearDown();
126         getContext().unbindService(mConnection);
127     }
128 
129     @TestTargets({
130         @TestTargetNew(
131             level = TestLevel.COMPLETE,
132             method = "Messenger",
133             args = {android.os.Handler.class}
134         ),
135         @TestTargetNew(
136             level = TestLevel.COMPLETE,
137             method = "Messenger",
138             args = {android.os.IBinder.class}
139         ),
140         @TestTargetNew(
141             level = TestLevel.COMPLETE,
142             method = "equals",
143             args = {java.lang.Object.class}
144         )
145     })
testConstructorAndEquals()146     public void testConstructorAndEquals() {
147         Messenger messenger = new Messenger(mHandler);
148         Messenger objMessenger = new Messenger(mHandler);
149         assertTrue(messenger.equals(objMessenger));
150         messenger = new Messenger(mIBinder);
151         assertFalse(messenger.equals(objMessenger));
152     }
153 
154     @TestTargetNew(
155         level = TestLevel.PARTIAL,
156         method = "send",
157         args = {android.os.Message.class}
158     )
testSend()159     public void testSend() throws RemoteException, InterruptedException {
160         // messenger used by its own thread.
161         Message message = Message.obtain(mHandler, WHAT, MSG_ARG1, MSG_ARG2);
162         mMessenger.send(message);
163         assertTrue(mResult);
164         assertNotNull(mMessage);
165         assertEquals(mMessage.what, message.what);
166         assertEquals(mMessage.arg1, message.arg1);
167         assertEquals(mMessage.arg2, message.arg2);
168 
169         // Used in other process. If the sent msg does not equal to expected, it will throw failure
170         // and the test will fail
171         (new MessengerTestHelper()).doTest(1000, 50);
172     }
173 
174     @TestTargetNew(
175         level = TestLevel.COMPLETE,
176         method = "hashCode",
177         args = {}
178     )
testHashCode()179     public void testHashCode() {
180         assertEquals(mMessenger.getBinder().hashCode(), mMessenger.hashCode());
181     }
182 
183     @TestTargetNew(
184         level = TestLevel.PARTIAL,
185         method = "getBinder",
186         args = {}
187     )
testGetBinder()188     public void testGetBinder() {
189         Messenger messenger = new Messenger(mIBinder);
190         assertSame(mIBinder, messenger.getBinder());
191         assertNotNull(mMessenger.getBinder());
192     }
193 
194     @TestTargetNew(
195         level = TestLevel.COMPLETE,
196         method = "writeToParcel",
197         args = {android.os.Parcel.class, int.class}
198     )
testWriteToParcel()199     public void testWriteToParcel() {
200         Parcel parcel = Parcel.obtain();
201         mMessenger.writeToParcel(parcel, 0);
202         parcel.setDataPosition(0);
203         Messenger messenger = Messenger.CREATOR.createFromParcel(parcel);
204         assertTrue(messenger.equals(mMessenger));
205         parcel.recycle();
206     }
207 
208     @TestTargetNew(
209         level = TestLevel.COMPLETE,
210         method = "describeContents",
211         args = {}
212     )
testDescribeContents()213     public void testDescribeContents() {
214         assertEquals(0, mMessenger.describeContents());
215     }
216 
217     @TestTargets({
218         @TestTargetNew(
219             level = TestLevel.COMPLETE,
220             method = "writeMessengerOrNullToParcel",
221             args = {android.os.Messenger.class, android.os.Parcel.class}
222         ),
223         @TestTargetNew(
224             level = TestLevel.COMPLETE,
225             method = "readMessengerOrNullFromParcel",
226             args = {android.os.Parcel.class}
227         )
228     })
testWriteMessengerOrNullToParcel()229     public void testWriteMessengerOrNullToParcel() {
230         Parcel parcelWithMessenger = Parcel.obtain();
231         Messenger.writeMessengerOrNullToParcel(mMessenger, parcelWithMessenger);
232         parcelWithMessenger.setDataPosition(0);
233         Messenger messenger = Messenger.readMessengerOrNullFromParcel(parcelWithMessenger);
234         assertNotNull(messenger);
235         assertTrue(messenger.equals(mMessenger));
236         parcelWithMessenger.recycle();
237 
238         Parcel parcelWithNull = Parcel.obtain();
239         Messenger.writeMessengerOrNullToParcel(null, parcelWithNull);
240         parcelWithNull.setDataPosition(0);
241         messenger = Messenger.readMessengerOrNullFromParcel(parcelWithNull);
242         assertNull(messenger);
243         parcelWithNull.recycle();
244     }
245 
246     /**
247      * This helper class is used for test of MessengerTest. Mainly on control of the message looper.
248      */
249     private class MessengerTestHelper {
250         private boolean mDone = false;
251         private boolean mSuccess = false;
252         private RuntimeException mFailure = null;
253         private Looper mLooper;
254 
255         private Handler mTestHandler;
256         private Messenger mTestMessenger;
257 
init()258         public void init() {
259             synchronized (MessengerTest.this) {
260                 mTestHandler = new Handler() {
261                     public void handleMessage(Message msg) {
262                         MessengerTestHelper.this.handleMessage(msg);
263                     }
264                 };
265                 mTestMessenger = new Messenger(mTestHandler);
266                 try {
267                     MessengerTestHelper.this.executeTest();
268                 } catch (RemoteException e) {
269                     fail(e.getMessage());
270                 }
271             }
272         }
273 
MessengerTestHelper()274         public MessengerTestHelper() {
275         }
276 
executeTest()277         public void executeTest() throws RemoteException {
278             Message msg = Message.obtain();
279             msg.arg1 = MSG_ARG1;
280             msg.arg2 = MSG_ARG2;
281             msg.replyTo = mTestMessenger;
282             // Use another messenger to send msg.
283             mServiceMessenger.send(msg);
284         }
285 
286         /**
287          * This method is used to check if the message sent by another messenger is correctly
288          * handled by this thread. If not equals to expected, there will be a failure thrown.
289          */
handleMessage(Message msg)290         public void handleMessage(Message msg) {
291             if (msg.arg1 != MSG_ARG1) {
292                 failure(new RuntimeException("Message.arg1 is not " + MSG_ARG1 + ", it's "
293                         + msg.arg1));
294                 return;
295             }
296             if (msg.arg2 != MSG_ARG2) {
297                 failure(new RuntimeException("Message.arg2 is not " + MSG_ARG2 + ", it's "
298                         + msg.arg2));
299                 return;
300             }
301             if (!mTestMessenger.equals(msg.replyTo)) {
302                 failure(new RuntimeException("Message.replyTo is not me, it's " + msg.replyTo));
303                 return;
304             }
305             success();
306         }
307 
doTest(long timeout, long interval)308         public void doTest(long timeout, long interval) throws InterruptedException {
309             (new LooperThread()).start();
310 
311             synchronized (this) {
312                 long now = System.currentTimeMillis();
313                 long endTime = now + timeout;
314                 // wait and frequently check if mDone is set.
315                 while (!mDone && now < endTime) {
316                     wait(interval);
317                     now = System.currentTimeMillis();
318                 }
319             }
320 
321             mLooper.quit();
322 
323             if (!mDone) {
324                 throw new RuntimeException("test timed out");
325             }
326             if (!mSuccess) {
327                 throw mFailure;
328             }
329         }
330 
getLooper()331         public Looper getLooper() {
332             return mLooper;
333         }
334 
success()335         public void success() {
336             synchronized (this) {
337                 mSuccess = true;
338                 quit();
339             }
340         }
341 
failure(RuntimeException failure)342         public void failure(RuntimeException failure) {
343             synchronized (this) {
344                 mSuccess = false;
345                 mFailure = failure;
346                 quit();
347             }
348         }
349 
350         class LooperThread extends HandlerThread {
351 
LooperThread()352             public LooperThread() {
353                 super("MessengerLooperThread");
354             }
355 
onLooperPrepared()356             public void onLooperPrepared() {
357                 init();
358                 mLooper = getLooper();
359             }
360 
361             @Override
run()362             public void run() {
363                 super.run();
364                 synchronized (MessengerTestHelper.this) {
365                     mDone = true;
366                     if (!mSuccess && mFailure == null) {
367                         mFailure = new RuntimeException("no failure exception set");
368                     }
369                     MessengerTestHelper.this.notifyAll();
370                 }
371             }
372         }
373 
quit()374         private void quit() {
375             synchronized (this) {
376                 mDone = true;
377                 notifyAll();
378             }
379         }
380     }
381 }
382