Home | History | Annotate | Download | only in cts
      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 
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.ServiceConnection;
     24 import android.os.Binder;
     25 import android.os.Handler;
     26 import android.os.HandlerThread;
     27 import android.os.IBinder;
     28 import android.os.Looper;
     29 import android.os.Message;
     30 import android.os.Messenger;
     31 import android.os.Parcel;
     32 import android.os.RemoteException;
     33 import android.test.AndroidTestCase;
     34 
     35 public class MessengerTest extends AndroidTestCase {
     36 
     37     private Messenger mMessenger;
     38     private Message mMessage;
     39     private boolean mResult;
     40     private Messenger mServiceMessenger;
     41     private static final int MSG_ARG1 = 100;
     42     private static final int MSG_ARG2 = 1000;
     43     private static final int WHAT = 2008;
     44     private Handler mHandler = new Handler(Looper.getMainLooper()) {
     45         @Override
     46         public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
     47             mResult = true;
     48             mMessage = msg;
     49             return super.sendMessageAtTime(msg, uptimeMillis);
     50         }
     51     };
     52 
     53     private final IBinder mIBinder = new Binder();
     54 
     55     // Create another messenger to send msg.
     56     private ServiceConnection mConnection = new ServiceConnection() {
     57         public void onServiceConnected(ComponentName name, IBinder service) {
     58             synchronized (MessengerTest.this) {
     59                 mServiceMessenger = new Messenger(service);
     60                 MessengerTest.this.notifyAll();
     61             }
     62         }
     63 
     64         public void onServiceDisconnected(ComponentName name) {
     65             mServiceMessenger = null;
     66         }
     67     };
     68 
     69     @Override
     70     protected void setUp() throws Exception {
     71 
     72         super.setUp();
     73         mMessenger = new Messenger(mHandler);
     74         getContext().bindService(new Intent(mContext, MessengerService.class), mConnection,
     75                 Context.BIND_AUTO_CREATE);
     76         synchronized (this) {
     77             while (mServiceMessenger == null) {
     78                 wait();
     79             }
     80         }
     81     }
     82 
     83     @Override
     84     protected void tearDown() throws Exception {
     85         super.tearDown();
     86         getContext().unbindService(mConnection);
     87     }
     88 
     89     public void testConstructorAndEquals() {
     90         Messenger messenger = new Messenger(mHandler);
     91         Messenger objMessenger = new Messenger(mHandler);
     92         assertTrue(messenger.equals(objMessenger));
     93         messenger = new Messenger(mIBinder);
     94         assertFalse(messenger.equals(objMessenger));
     95     }
     96 
     97     public void testSend() throws RemoteException, InterruptedException {
     98         // messenger used by its own thread.
     99         Message message = Message.obtain(mHandler, WHAT, MSG_ARG1, MSG_ARG2);
    100         mMessenger.send(message);
    101         assertTrue(mResult);
    102         assertNotNull(mMessage);
    103         assertEquals(mMessage.what, message.what);
    104         assertEquals(mMessage.arg1, message.arg1);
    105         assertEquals(mMessage.arg2, message.arg2);
    106 
    107         // Used in other process. If the sent msg does not equal to expected, it will throw failure
    108         // and the test will fail
    109         (new MessengerTestHelper()).doTest(1000, 50);
    110     }
    111 
    112     public void testHashCode() {
    113         assertEquals(mMessenger.getBinder().hashCode(), mMessenger.hashCode());
    114     }
    115 
    116     public void testGetBinder() {
    117         Messenger messenger = new Messenger(mIBinder);
    118         assertSame(mIBinder, messenger.getBinder());
    119         assertNotNull(mMessenger.getBinder());
    120     }
    121 
    122     public void testWriteToParcel() {
    123         Parcel parcel = Parcel.obtain();
    124         mMessenger.writeToParcel(parcel, 0);
    125         parcel.setDataPosition(0);
    126         Messenger messenger = Messenger.CREATOR.createFromParcel(parcel);
    127         assertTrue(messenger.equals(mMessenger));
    128         parcel.recycle();
    129     }
    130 
    131     public void testDescribeContents() {
    132         assertEquals(0, mMessenger.describeContents());
    133     }
    134 
    135     public void testWriteMessengerOrNullToParcel() {
    136         Parcel parcelWithMessenger = Parcel.obtain();
    137         Messenger.writeMessengerOrNullToParcel(mMessenger, parcelWithMessenger);
    138         parcelWithMessenger.setDataPosition(0);
    139         Messenger messenger = Messenger.readMessengerOrNullFromParcel(parcelWithMessenger);
    140         assertNotNull(messenger);
    141         assertTrue(messenger.equals(mMessenger));
    142         parcelWithMessenger.recycle();
    143 
    144         Parcel parcelWithNull = Parcel.obtain();
    145         Messenger.writeMessengerOrNullToParcel(null, parcelWithNull);
    146         parcelWithNull.setDataPosition(0);
    147         messenger = Messenger.readMessengerOrNullFromParcel(parcelWithNull);
    148         assertNull(messenger);
    149         parcelWithNull.recycle();
    150     }
    151 
    152     /**
    153      * This helper class is used for test of MessengerTest. Mainly on control of the message looper.
    154      */
    155     private class MessengerTestHelper {
    156         private boolean mDone = false;
    157         private boolean mSuccess = false;
    158         private RuntimeException mFailure = null;
    159         private Looper mLooper;
    160 
    161         private Handler mTestHandler;
    162         private Messenger mTestMessenger;
    163 
    164         public void init() {
    165             synchronized (MessengerTest.this) {
    166                 mTestHandler = new Handler() {
    167                     public void handleMessage(Message msg) {
    168                         MessengerTestHelper.this.handleMessage(msg);
    169                     }
    170                 };
    171                 mTestMessenger = new Messenger(mTestHandler);
    172                 try {
    173                     MessengerTestHelper.this.executeTest();
    174                 } catch (RemoteException e) {
    175                     fail(e.getMessage());
    176                 }
    177             }
    178         }
    179 
    180         public MessengerTestHelper() {
    181         }
    182 
    183         public void executeTest() throws RemoteException {
    184             Message msg = Message.obtain();
    185             msg.arg1 = MSG_ARG1;
    186             msg.arg2 = MSG_ARG2;
    187             msg.replyTo = mTestMessenger;
    188             // Use another messenger to send msg.
    189             mServiceMessenger.send(msg);
    190         }
    191 
    192         /**
    193          * This method is used to check if the message sent by another messenger is correctly
    194          * handled by this thread. If not equals to expected, there will be a failure thrown.
    195          */
    196         public void handleMessage(Message msg) {
    197             if (msg.arg1 != MSG_ARG1) {
    198                 failure(new RuntimeException("Message.arg1 is not " + MSG_ARG1 + ", it's "
    199                         + msg.arg1));
    200                 return;
    201             }
    202             if (msg.arg2 != MSG_ARG2) {
    203                 failure(new RuntimeException("Message.arg2 is not " + MSG_ARG2 + ", it's "
    204                         + msg.arg2));
    205                 return;
    206             }
    207             if (!mTestMessenger.equals(msg.replyTo)) {
    208                 failure(new RuntimeException("Message.replyTo is not me, it's " + msg.replyTo));
    209                 return;
    210             }
    211             success();
    212         }
    213 
    214         public void doTest(long timeout, long interval) throws InterruptedException {
    215             (new LooperThread()).start();
    216 
    217             synchronized (this) {
    218                 long now = System.currentTimeMillis();
    219                 long endTime = now + timeout;
    220                 // wait and frequently check if mDone is set.
    221                 while (!mDone && now < endTime) {
    222                     wait(interval);
    223                     now = System.currentTimeMillis();
    224                 }
    225             }
    226 
    227             mLooper.quit();
    228 
    229             if (!mDone) {
    230                 throw new RuntimeException("test timed out");
    231             }
    232             if (!mSuccess) {
    233                 throw mFailure;
    234             }
    235         }
    236 
    237         public Looper getLooper() {
    238             return mLooper;
    239         }
    240 
    241         public void success() {
    242             synchronized (this) {
    243                 mSuccess = true;
    244                 quit();
    245             }
    246         }
    247 
    248         public void failure(RuntimeException failure) {
    249             synchronized (this) {
    250                 mSuccess = false;
    251                 mFailure = failure;
    252                 quit();
    253             }
    254         }
    255 
    256         class LooperThread extends HandlerThread {
    257 
    258             public LooperThread() {
    259                 super("MessengerLooperThread");
    260             }
    261 
    262             public void onLooperPrepared() {
    263                 init();
    264                 mLooper = getLooper();
    265             }
    266 
    267             @Override
    268             public void run() {
    269                 super.run();
    270                 synchronized (MessengerTestHelper.this) {
    271                     mDone = true;
    272                     if (!mSuccess && mFailure == null) {
    273                         mFailure = new RuntimeException("no failure exception set");
    274                     }
    275                     MessengerTestHelper.this.notifyAll();
    276                 }
    277             }
    278         }
    279 
    280         private void quit() {
    281             synchronized (this) {
    282                 mDone = true;
    283                 notifyAll();
    284             }
    285         }
    286     }
    287 }
    288