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