blob: 312ea81ab9a1ec0b93f05a8e071778e4cfe69e30 [file] [log] [blame]
/*
* 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.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.TokenWatcher;
import android.test.AndroidTestCase;
public class TokenWatcherTest extends AndroidTestCase {
private static final String TAG = "TokenWatcherTest";
private static final String EMPTY_SERVICE = "android.os.REMOTESERVICE";
private static final int OVERTIME = 2000;
private static final int DELAY = 500;
private MockTokenWatcher mMockTokenWatcher;
private Handler mHandler;
private ServiceConnection mServiceConnection;
private Intent mIntent;
private IEmptyService mEmptyService;
private Object mSync;
private boolean mHasConnected;
private boolean mHasDisconnected;
private boolean mLooped;
private Looper mLooper;
@Override
protected void setUp() throws Exception {
super.setUp();
new Thread() {
public void run() {
Looper.prepare();
mLooper = Looper.myLooper();
mLooped = true;
Looper.loop();
}
}.start();
while (!mLooped) {
Thread.sleep(50);
}
mHandler = new Handler(mLooper);
mSync = new Object();
mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mEmptyService = IEmptyService.Stub.asInterface(service);
synchronized (mSync) {
mHasConnected = true;
mSync.notify();
}
}
public void onServiceDisconnected(ComponentName className) {
mEmptyService = null;
synchronized (mSync) {
mHasDisconnected = true;
mSync.notify();
}
}
};
mIntent = new Intent(EMPTY_SERVICE);
mIntent.setPackage(getContext().getPackageName());
getContext().startService(mIntent);
Intent secondaryIntent = new Intent(IEmptyService.class.getName());
secondaryIntent.setPackage(getContext().getPackageName());
getContext().bindService(secondaryIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
synchronized (mSync) {
if (!mHasConnected) {
try {
mSync.wait();
} catch (InterruptedException e) {
}
}
}
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mLooper.quit();
if (!mHasDisconnected) {
getContext().unbindService(mServiceConnection);
}
if (mIntent != null) {
getContext().stopService(mIntent);
}
}
public void testTokenWatcher() throws RemoteException, InterruptedException {
// new the MockTokenWatcher instance, test constructor
IBinder token = mEmptyService.getToken();
mMockTokenWatcher = new MockTokenWatcher(mHandler, TAG);
assertFalse(mMockTokenWatcher.isAcquired());
assertFalse(mMockTokenWatcher.isAcquiredCalled);
assertFalse(mMockTokenWatcher.isReleasedCalled);
// test acquire() and acquired()
mMockTokenWatcher.acquire(token, TAG);
assertTrue(mMockTokenWatcher.isAcquired());
assertTrue(waitUntilAcquired());
// this time acquired() will not be called
mMockTokenWatcher.isAcquiredCalled = false;
mMockTokenWatcher.acquire(token, TAG);
assertTrue(mMockTokenWatcher.isAcquired());
assertFalse(waitUntilAcquired());
// test release() and released()
synchronized (mMockTokenWatcher) {
mMockTokenWatcher.release(token);
assertFalse(mMockTokenWatcher.isAcquired());
}
assertTrue(waitUntilReleased());
// this time released() will not be called
mMockTokenWatcher.isReleasedCalled =false;
mMockTokenWatcher.release(token);
assertFalse(mMockTokenWatcher.isAcquired());
assertFalse(waitUntilReleased());
}
public void testCleanUp() throws RemoteException, InterruptedException {
IBinder token = mEmptyService.getToken();
mMockTokenWatcher = new MockTokenWatcher(mHandler, TAG);
assertFalse(mMockTokenWatcher.isAcquired());
assertFalse(mMockTokenWatcher.isAcquiredCalled);
assertFalse(mMockTokenWatcher.isReleasedCalled);
// test dump() and cleanup()
mMockTokenWatcher.acquire(token, TAG);
assertTrue(mMockTokenWatcher.isAcquired());
assertTrue(waitUntilAcquired());
mMockTokenWatcher.dump();
synchronized (mMockTokenWatcher) {
mMockTokenWatcher.cleanup(token, true);
assertFalse(mMockTokenWatcher.isAcquired());
}
assertTrue(waitUntilReleased());
}
public void testRepeatedAcquire() throws RemoteException, InterruptedException {
IBinder token = mEmptyService.getToken();
mMockTokenWatcher = new MockTokenWatcher(mHandler, TAG);
assertFalse(mMockTokenWatcher.isAcquired());
assertFalse(mMockTokenWatcher.isAcquiredCalled);
assertFalse(mMockTokenWatcher.isReleasedCalled);
// First time
mMockTokenWatcher.acquire(token, TAG);
assertTrue(mMockTokenWatcher.isAcquired());
assertTrue(waitUntilAcquired());
// Reset
mMockTokenWatcher.isAcquiredCalled = false;
mMockTokenWatcher.isReleasedCalled = false;
// Second time -- should be a no-op
mMockTokenWatcher.acquire(token, TAG);
assertTrue(mMockTokenWatcher.isAcquired());
assertFalse(waitUntilAcquired());
assertFalse(waitUntilReleased());
// Release
synchronized (mMockTokenWatcher) {
mMockTokenWatcher.release(token);
assertFalse(mMockTokenWatcher.isAcquired());
}
assertTrue(waitUntilReleased());
}
private boolean waitUntilAcquired() throws InterruptedException {
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < OVERTIME) {
if (mMockTokenWatcher.isAcquiredCalled) {
return true;
}
Thread.sleep(DELAY);
}
return false;
}
private boolean waitUntilReleased() throws InterruptedException {
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < OVERTIME) {
if (mMockTokenWatcher.isReleasedCalled) {
return true;
}
Thread.sleep(DELAY);
}
return false;
}
private static class MockTokenWatcher extends TokenWatcher {
public boolean isAcquiredCalled;
public boolean isReleasedCalled;
public MockTokenWatcher(Handler h, String tag) {
super(h, tag);
}
@Override
public void acquired() {
isAcquiredCalled = true;
}
@Override
public synchronized void released() {
isReleasedCalled = true;
}
}
}