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