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 setUp()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 tearDown()84 protected void tearDown() throws Exception { 85 super.tearDown(); 86 getContext().unbindService(mConnection); 87 } 88 testConstructorAndEquals()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 testSend()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 testHashCode()112 public void testHashCode() { 113 assertEquals(mMessenger.getBinder().hashCode(), mMessenger.hashCode()); 114 } 115 testGetBinder()116 public void testGetBinder() { 117 Messenger messenger = new Messenger(mIBinder); 118 assertSame(mIBinder, messenger.getBinder()); 119 assertNotNull(mMessenger.getBinder()); 120 } 121 testWriteToParcel()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 testDescribeContents()131 public void testDescribeContents() { 132 assertEquals(0, mMessenger.describeContents()); 133 } 134 testWriteMessengerOrNullToParcel()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 init()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 MessengerTestHelper()180 public MessengerTestHelper() { 181 } 182 executeTest()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 */ handleMessage(Message msg)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 doTest(long timeout, long interval)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 getLooper()237 public Looper getLooper() { 238 return mLooper; 239 } 240 success()241 public void success() { 242 synchronized (this) { 243 mSuccess = true; 244 quit(); 245 } 246 } 247 failure(RuntimeException failure)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 LooperThread()258 public LooperThread() { 259 super("MessengerLooperThread"); 260 } 261 onLooperPrepared()262 public void onLooperPrepared() { 263 init(); 264 mLooper = getLooper(); 265 } 266 267 @Override run()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 quit()280 private void quit() { 281 synchronized (this) { 282 mDone = true; 283 notifyAll(); 284 } 285 } 286 } 287 } 288