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