diff options
Diffstat (limited to 'tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java')
-rw-r--r-- | tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java | 224 |
1 files changed, 142 insertions, 82 deletions
diff --git a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java index e5b25c93b9a..bc990e27166 100644 --- a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java +++ b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java @@ -16,12 +16,19 @@ package android.cts; -import android.content.BroadcastReceiver; +import static java.util.concurrent.TimeUnit.SECONDS; + +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.Bundle; -import android.os.Debug; import android.os.Environment; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; import android.test.AndroidTestCase; import java.io.File; @@ -33,8 +40,6 @@ import java.nio.file.StandardOpenOption; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import static java.util.concurrent.TimeUnit.SECONDS; - @SuppressWarnings("deprecation") public class FileChannelInterProcessLockTest extends AndroidTestCase { @@ -55,11 +60,11 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { * the service. This provides ample amount of time for the service to receive the request from * the test, then act, and respond back. */ - final static int MAX_WAIT_TIME = 20; + final static int MAX_WAIT_TIME = 10; @Override public void tearDown() throws Exception { - stopService(); + IpcChannel.unbindService(); super.tearDown(); } @@ -419,15 +424,12 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { ChannelType localChannelType, ChannelType remoteChannelType, boolean expectToGetLock) throws Exception { try { - IntentReceiver.resetReceiverState(); - // Request that the remote lock be obtained. - getContext().startService(new Intent(getContext(), LockHoldingService.class) - .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType) - .putExtra(LockHoldingService.CHANNEL_TYPE_KEY, remoteChannelType)); + IpcChannel.bindService(getContext()); + IpcChannel.requestRemoteLock(remoteLockType, remoteChannelType); // Wait for a signal that the remote lock is definitely held. - assertTrue(IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS)); + assertTrue(IpcChannel.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS)); // Try to acquire the local lock in all cases and check whether it could be acquired or // not as expected. @@ -440,7 +442,7 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { } // Release the remote lock. } finally { - stopService(); + IpcChannel.unbindService(); } } @@ -458,30 +460,24 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { ChannelType localChannelType, ChannelType remoteChannelType, boolean expectToWait) throws Exception { try { - IntentReceiver.resetReceiverState(); - // The amount of time the remote service should hold lock. - long remoteLockHoldTimeMillis = 7000; + long remoteLockHoldTimeMillis = 5000; // The amount of time test should get to try to acquire the lock. long sufficientOverlappingTimeInMillis = 2000; // This is the allowable delta in the time between the time recorded after the service // released the lock and the time recorded after the test obtained the lock. - long lockReleasedAndReacquiredTimeDeltaInMillis = 1000; + long lockReleasedAndReacquiredTimeDeltaInMillis = 500; // Tell the service to acquire a remote lock. - Intent sendIntent = new Intent(getContext(), LockHoldingService.class) - .putExtra(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, remoteLockHoldTimeMillis) - .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType) - .putExtra(LockHoldingService.CHANNEL_TYPE_KEY, remoteChannelType) - .putExtra(LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, true); - - getContext().startService(sendIntent); + IpcChannel.bindService(getContext()); + IpcChannel.requestRemoteLockAndRelease(remoteLockType, + remoteChannelType, remoteLockHoldTimeMillis); // Wait for the service to hold the lock and notify for the same. assertTrue("No remote lock held notification", - IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS)); + IpcChannel.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS)); long localLockNotObtainedTime = System.currentTimeMillis(); @@ -491,9 +487,9 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { // Wait until the remote lock has definitely been released. assertTrue("No remote lock release notification", - IntentReceiver.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS)); + IpcChannel.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS)); - Bundle remoteLockReleasedBundle = IntentReceiver.lockReleasedBundle; + Bundle remoteLockReleasedBundle = IpcChannel.lockReleasedBundle; long remoteLockNotReleasedTime = remoteLockReleasedBundle.getLong(LockHoldingService.LOCK_NOT_YET_RELEASED_TIMESTAMP); long remoteLockReleasedTime = @@ -506,11 +502,10 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { // but we can't be sure and the test may not be valid. This is why we hold the lock // remotely for a long time compared to the delays we expect for intents to propagate // between processes. - assertTrue(String.format("Remote lock release start (%d), " + - "too soon after local lock notification time (%d). " + + assertTrue(String.format("Remote lock release start " + + "too soon (%d ms) after lock notification time. " + "Need at least %d ms", - remoteLockReleasedTime, - localLockNotObtainedTime, + remoteLockNotReleasedTime - localLockNotObtainedTime, sufficientOverlappingTimeInMillis ), remoteLockNotReleasedTime - localLockNotObtainedTime > @@ -522,10 +517,10 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { // service. The localLockObtainedTime is captured after the lock was obtained by this // thread. Therefore, there is a degree of slop inherent in the two times. We assert // that they are "close" to each other, but we cannot assert any ordering. - assertTrue(String.format("Local lock obtained (%d) too long " + - "from remote lock release time (%d). " + + assertTrue(String.format("Local lock obtained too long (%d ms) " + + "from remote lock release time. " + "Expected at most %d ms.", - localLockObtainedTime, remoteLockReleasedTime, + localLockObtainedTime - remoteLockReleasedTime, lockReleasedAndReacquiredTimeDeltaInMillis), Math.abs(localLockObtainedTime - remoteLockReleasedTime) < lockReleasedAndReacquiredTimeDeltaInMillis); @@ -545,22 +540,8 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { // Asserting if the fileLock is valid. assertTrue(fileLock.isValid()); } finally { - stopService(); - } - } - - /** - * Requests and waits for the service to stop - */ - void stopService() throws Exception { - getContext().stopService(new Intent(getContext(), LockHoldingService.class)); - // onStopLatch can be null if we never start the service, possibly because of - // an earlier failure in the test. - if (IntentReceiver.onStopLatch != null) { - assertTrue(IntentReceiver.onStopLatch.await(MAX_WAIT_TIME, SECONDS)); + IpcChannel.unbindService(); } - - deleteDir(getContext()); } static enum LockType { @@ -748,57 +729,136 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase { } /** - * Listens to broadcasts sent by the LockHoldingService and records information / provides - * latches so the test code can synchronize until it is informed the service has acted on - * requests it has sent. + * Handles the comms with the LockHoldingService. + * + * Binds to the service and sends requests and receives callbacks from it. + * + * It records information / provides latches so the test code can synchronize until it is + * informed the service has acted on requests it has sent. */ - public static class IntentReceiver extends BroadcastReceiver { + public static class IpcChannel { - static CountDownLatch onStartLatch; - - static CountDownLatch onStopLatch; + static Context context; + static CountDownLatch onBindLatch; + static CountDownLatch onUnbindLatch; static CountDownLatch lockHeldLatch; - static volatile Bundle lockHeldBundle; - static CountDownLatch lockReleasedLatch; - static volatile Bundle lockReleasedBundle; + static volatile boolean bound = false; + static Messenger messenger; + static Messenger responseMessenger; + static ServiceConnection serviceConnection; + + static Handler responseMessageHandler; + + private static Context getContext() { + return context; + } + /** - * Reset the IntentReceiver for a new test. Assumes no intents will be received from prior - * tests. + * Reset the IpcChannel for a new test. Assumes no intents will be received from prior + * tests. */ - public static synchronized void resetReceiverState() { - onStartLatch = new CountDownLatch(1); - onStopLatch = new CountDownLatch(1); + static synchronized void resetReceiverState(Context testContext) { + context = testContext; + bound = false; + onBindLatch = new CountDownLatch(1); + onUnbindLatch = new CountDownLatch(1); lockHeldLatch = new CountDownLatch(1); lockReleasedLatch = new CountDownLatch(1); lockHeldBundle = null; lockReleasedBundle = null; + + responseMessageHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + Bundle bundle = msg.getData(); + if (bundle.getBoolean(LockHoldingService.NOTIFICATION_LOCK_HELD)) { + lockHeldBundle = bundle; + lockHeldLatch.countDown(); + } else if (bundle.getBoolean(LockHoldingService.NOTIFICATION_LOCK_RELEASED)) { + lockReleasedBundle = bundle; + lockReleasedLatch.countDown(); + } else if (bundle.getBoolean(LockHoldingService.NOTIFICATION_READY_FOR_SHUTDOWN)) { + onUnbindLatch.countDown(); + } else { + super.handleMessage(msg); + } + } + }; + responseMessenger = new Messenger(responseMessageHandler); + + serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + messenger = new Messenger(service); + bound = true; + onBindLatch.countDown(); + } + + @Override + public void onBindingDied(ComponentName className) { + getContext().unbindService(this); + bound = false; + } + + @Override + public void onServiceDisconnected(ComponentName className) { + getContext().unbindService(this); + bound = false; + } + }; } - @Override - public void onReceive(Context context, Intent intent) { - String msg = intent.getStringExtra(LockHoldingService.NOTIFICATION_KEY); - switch (msg) { - case LockHoldingService.NOTIFICATION_START: - onStartLatch.countDown(); - break; - case LockHoldingService.NOTIFICATION_STOP: - onStopLatch.countDown(); - break; - case LockHoldingService.NOTIFICATION_LOCK_HELD: - lockHeldBundle = intent.getExtras(); - lockHeldLatch.countDown(); - break; - case LockHoldingService.NOTIFICATION_LOCK_RELEASED: - lockReleasedBundle = intent.getExtras(); - lockReleasedLatch.countDown(); - break; + static void bindService(Context testContext) throws Exception { + resetReceiverState(testContext); + getContext().bindService(new Intent(getContext(), LockHoldingService.class), + serviceConnection, Context.BIND_AUTO_CREATE); + assertTrue(onBindLatch.await(MAX_WAIT_TIME, SECONDS)); + } + + static void requestRemoteLock(LockType lockType, ChannelType channelType) throws Exception { + Message msg = Message.obtain(null, + LockHoldingService.LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY, 0, 0); + Bundle bundle = msg.getData(); + bundle.putSerializable(LockHoldingService.LOCK_TYPE_KEY, lockType); + bundle.putSerializable(LockHoldingService.CHANNEL_TYPE_KEY, channelType); + msg.replyTo = responseMessenger; + messenger.send(msg); + } + + static void requestRemoteLockAndRelease(LockType lockType, ChannelType channelType, + long lockHoldTimeMillis) throws Exception { + Message msg = Message.obtain(null, + LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY, 0, 0); + Bundle bundle = msg.getData(); + bundle.putSerializable(LockHoldingService.LOCK_TYPE_KEY, lockType); + bundle.putSerializable(LockHoldingService.CHANNEL_TYPE_KEY, channelType); + bundle.putLong(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, lockHoldTimeMillis); + msg.replyTo = responseMessenger; + messenger.send(msg); + } + + /** + * Requests and waits for the service to stop + */ + static void unbindService() throws Exception { + if (bound) { + Message msg = Message.obtain(null, LockHoldingService.PREPARE_FOR_SHUTDOWN, 0, 0); + msg.replyTo = responseMessenger; + messenger.send(msg); + + assertTrue(onUnbindLatch.await(MAX_WAIT_TIME, SECONDS)); + getContext().unbindService(serviceConnection); + bound = false; } + messenger = null; + deleteDir(getContext()); } } + } |