| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.os.cts; |
| |
| |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.ServiceConnection; |
| import android.os.Binder; |
| import android.os.Handler; |
| import android.os.HandlerThread; |
| import android.os.IBinder; |
| import android.os.Looper; |
| import android.os.Message; |
| import android.os.Messenger; |
| import android.os.Parcel; |
| import android.os.RemoteException; |
| import android.test.AndroidTestCase; |
| |
| public class MessengerTest extends AndroidTestCase { |
| |
| private Messenger mMessenger; |
| private Message mMessage; |
| private boolean mResult; |
| private Messenger mServiceMessenger; |
| private static final int MSG_ARG1 = 100; |
| private static final int MSG_ARG2 = 1000; |
| private static final int WHAT = 2008; |
| private Handler mHandler = new Handler(Looper.getMainLooper()) { |
| @Override |
| public boolean sendMessageAtTime(Message msg, long uptimeMillis) { |
| mResult = true; |
| mMessage = msg; |
| return super.sendMessageAtTime(msg, uptimeMillis); |
| } |
| }; |
| |
| private final IBinder mIBinder = new Binder(); |
| |
| // Create another messenger to send msg. |
| private ServiceConnection mConnection = new ServiceConnection() { |
| public void onServiceConnected(ComponentName name, IBinder service) { |
| synchronized (MessengerTest.this) { |
| mServiceMessenger = new Messenger(service); |
| MessengerTest.this.notifyAll(); |
| } |
| } |
| |
| public void onServiceDisconnected(ComponentName name) { |
| mServiceMessenger = null; |
| } |
| }; |
| |
| @Override |
| protected void setUp() throws Exception { |
| |
| super.setUp(); |
| mMessenger = new Messenger(mHandler); |
| getContext().bindService(new Intent(mContext, MessengerService.class), mConnection, |
| Context.BIND_AUTO_CREATE); |
| synchronized (this) { |
| while (mServiceMessenger == null) { |
| wait(); |
| } |
| } |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| super.tearDown(); |
| getContext().unbindService(mConnection); |
| } |
| |
| public void testConstructorAndEquals() { |
| Messenger messenger = new Messenger(mHandler); |
| Messenger objMessenger = new Messenger(mHandler); |
| assertTrue(messenger.equals(objMessenger)); |
| messenger = new Messenger(mIBinder); |
| assertFalse(messenger.equals(objMessenger)); |
| } |
| |
| public void testSend() throws RemoteException, InterruptedException { |
| // messenger used by its own thread. |
| Message message = Message.obtain(mHandler, WHAT, MSG_ARG1, MSG_ARG2); |
| mMessenger.send(message); |
| assertTrue(mResult); |
| assertNotNull(mMessage); |
| assertEquals(mMessage.what, message.what); |
| assertEquals(mMessage.arg1, message.arg1); |
| assertEquals(mMessage.arg2, message.arg2); |
| |
| // Used in other process. If the sent msg does not equal to expected, it will throw failure |
| // and the test will fail |
| (new MessengerTestHelper()).doTest(1000, 50); |
| } |
| |
| public void testHashCode() { |
| assertEquals(mMessenger.getBinder().hashCode(), mMessenger.hashCode()); |
| } |
| |
| public void testGetBinder() { |
| Messenger messenger = new Messenger(mIBinder); |
| assertSame(mIBinder, messenger.getBinder()); |
| assertNotNull(mMessenger.getBinder()); |
| } |
| |
| public void testWriteToParcel() { |
| Parcel parcel = Parcel.obtain(); |
| mMessenger.writeToParcel(parcel, 0); |
| parcel.setDataPosition(0); |
| Messenger messenger = Messenger.CREATOR.createFromParcel(parcel); |
| assertTrue(messenger.equals(mMessenger)); |
| parcel.recycle(); |
| } |
| |
| public void testDescribeContents() { |
| assertEquals(0, mMessenger.describeContents()); |
| } |
| |
| public void testWriteMessengerOrNullToParcel() { |
| Parcel parcelWithMessenger = Parcel.obtain(); |
| Messenger.writeMessengerOrNullToParcel(mMessenger, parcelWithMessenger); |
| parcelWithMessenger.setDataPosition(0); |
| Messenger messenger = Messenger.readMessengerOrNullFromParcel(parcelWithMessenger); |
| assertNotNull(messenger); |
| assertTrue(messenger.equals(mMessenger)); |
| parcelWithMessenger.recycle(); |
| |
| Parcel parcelWithNull = Parcel.obtain(); |
| Messenger.writeMessengerOrNullToParcel(null, parcelWithNull); |
| parcelWithNull.setDataPosition(0); |
| messenger = Messenger.readMessengerOrNullFromParcel(parcelWithNull); |
| assertNull(messenger); |
| parcelWithNull.recycle(); |
| } |
| |
| /** |
| * This helper class is used for test of MessengerTest. Mainly on control of the message looper. |
| */ |
| private class MessengerTestHelper { |
| private boolean mDone = false; |
| private boolean mSuccess = false; |
| private RuntimeException mFailure = null; |
| private Looper mLooper; |
| |
| private Handler mTestHandler; |
| private Messenger mTestMessenger; |
| |
| public void init() { |
| synchronized (MessengerTest.this) { |
| mTestHandler = new Handler() { |
| public void handleMessage(Message msg) { |
| MessengerTestHelper.this.handleMessage(msg); |
| } |
| }; |
| mTestMessenger = new Messenger(mTestHandler); |
| try { |
| MessengerTestHelper.this.executeTest(); |
| } catch (RemoteException e) { |
| fail(e.getMessage()); |
| } |
| } |
| } |
| |
| public MessengerTestHelper() { |
| } |
| |
| public void executeTest() throws RemoteException { |
| Message msg = Message.obtain(); |
| msg.arg1 = MSG_ARG1; |
| msg.arg2 = MSG_ARG2; |
| msg.replyTo = mTestMessenger; |
| // Use another messenger to send msg. |
| mServiceMessenger.send(msg); |
| } |
| |
| /** |
| * This method is used to check if the message sent by another messenger is correctly |
| * handled by this thread. If not equals to expected, there will be a failure thrown. |
| */ |
| public void handleMessage(Message msg) { |
| if (msg.arg1 != MSG_ARG1) { |
| failure(new RuntimeException("Message.arg1 is not " + MSG_ARG1 + ", it's " |
| + msg.arg1)); |
| return; |
| } |
| if (msg.arg2 != MSG_ARG2) { |
| failure(new RuntimeException("Message.arg2 is not " + MSG_ARG2 + ", it's " |
| + msg.arg2)); |
| return; |
| } |
| if (!mTestMessenger.equals(msg.replyTo)) { |
| failure(new RuntimeException("Message.replyTo is not me, it's " + msg.replyTo)); |
| return; |
| } |
| success(); |
| } |
| |
| public void doTest(long timeout, long interval) throws InterruptedException { |
| (new LooperThread()).start(); |
| |
| synchronized (this) { |
| long now = System.currentTimeMillis(); |
| long endTime = now + timeout; |
| // wait and frequently check if mDone is set. |
| while (!mDone && now < endTime) { |
| wait(interval); |
| now = System.currentTimeMillis(); |
| } |
| } |
| |
| mLooper.quit(); |
| |
| if (!mDone) { |
| throw new RuntimeException("test timed out"); |
| } |
| if (!mSuccess) { |
| throw mFailure; |
| } |
| } |
| |
| public Looper getLooper() { |
| return mLooper; |
| } |
| |
| public void success() { |
| synchronized (this) { |
| mSuccess = true; |
| quit(); |
| } |
| } |
| |
| public void failure(RuntimeException failure) { |
| synchronized (this) { |
| mSuccess = false; |
| mFailure = failure; |
| quit(); |
| } |
| } |
| |
| class LooperThread extends HandlerThread { |
| |
| public LooperThread() { |
| super("MessengerLooperThread"); |
| } |
| |
| public void onLooperPrepared() { |
| init(); |
| mLooper = getLooper(); |
| } |
| |
| @Override |
| public void run() { |
| super.run(); |
| synchronized (MessengerTestHelper.this) { |
| mDone = true; |
| if (!mSuccess && mFailure == null) { |
| mFailure = new RuntimeException("no failure exception set"); |
| } |
| MessengerTestHelper.this.notifyAll(); |
| } |
| } |
| } |
| |
| private void quit() { |
| synchronized (this) { |
| mDone = true; |
| notifyAll(); |
| } |
| } |
| } |
| } |