CancellationSignal.java revision a7771df3696954f0e279407e8894a916a7cb26cc
175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown/* 275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Copyright (C) 2012 The Android Open Source Project 375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * you may not use this file except in compliance with the License. 675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * You may obtain a copy of the License at 775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 1075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Unless required by applicable law or agreed to in writing, software 1175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * See the License for the specific language governing permissions and 1475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * limitations under the License. 1575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 17a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownpackage android.os; 1875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 19a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.ICancellationSignal; 20a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.ICancellationSignal.Stub; 2175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 2275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown/** 2375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Provides the ability to cancel an operation in progress. 2475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 254c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brownpublic final class CancellationSignal { 2675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private boolean mIsCanceled; 2775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private OnCancelListener mOnCancelListener; 284c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown private ICancellationSignal mRemote; 29aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown private boolean mCancelInProgress; 3075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 3175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 324c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Creates a cancellation signal, initially not canceled. 3375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 344c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public CancellationSignal() { 3575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 3675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 3775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 3875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Returns true if the operation has been canceled. 3975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 4075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @return True if the operation has been canceled. 4175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 4275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public boolean isCanceled() { 4375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 4475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return mIsCanceled; 4575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 4675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 4775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 4875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 4975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Throws {@link OperationCanceledException} if the operation has been canceled. 5075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 5175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation has been canceled. 5275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 5375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void throwIfCanceled() { 5475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (isCanceled()) { 5575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown throw new OperationCanceledException(); 5675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 5775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 5875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 5975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 604c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Cancels the operation and signals the cancellation listener. 6175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * If the operation has not yet started, then it will be canceled as soon as it does. 6275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 6375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void cancel() { 64aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final OnCancelListener listener; 65aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final ICancellationSignal remote; 6675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 67aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mIsCanceled) { 68aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 69aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 70aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown mIsCanceled = true; 71aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown mCancelInProgress = true; 72aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown listener = mOnCancelListener; 73aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown remote = mRemote; 74aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 75aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 76aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 77aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (listener != null) { 78aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown listener.onCancel(); 79aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 80aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (remote != null) { 81aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 82aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown remote.cancel(); 83aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } catch (RemoteException ex) { 8475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 8575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 86aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } finally { 87aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown synchronized (this) { 88aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown mCancelInProgress = false; 89aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown notifyAll(); 90aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 9175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 9275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 9375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 9475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 954c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Sets the cancellation listener to be called when canceled. 964c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * 974c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * This method is intended to be used by the recipient of a cancellation signal 984c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * such as a database or a content provider to handle cancellation requests 994c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * while performing a long-running operation. This method is not intended to be 1004c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * used by applications themselves. 1014c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * 1024c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * If {@link CancellationSignal#cancel} has already been called, then the provided 10375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * listener is invoked immediately. 10475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 105aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * This method is guaranteed that the listener will not be called after it 106aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * has been removed. 10775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 1084c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param listener The cancellation listener, or null to remove the current listener. 10975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 11075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void setOnCancelListener(OnCancelListener listener) { 11175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 112aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown waitForCancelFinishedLocked(); 113aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 114aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mOnCancelListener == listener) { 115aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 116aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 11775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mOnCancelListener = listener; 118aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (!mIsCanceled || listener == null) { 119aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 12075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 12175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 122aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown listener.onCancel(); 12375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 12475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 12575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 12675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Sets the remote transport. 12775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 128aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * If {@link CancellationSignal#cancel} has already been called, then the provided 129aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * remote transport is canceled immediately. 130aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * 131aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * This method is guaranteed that the remote transport will not be called after it 132aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * has been removed. 133aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * 13475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @param remote The remote transport, or null to remove. 13575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 13675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @hide 13775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1384c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public void setRemote(ICancellationSignal remote) { 13975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 140aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown waitForCancelFinishedLocked(); 141aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 142aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mRemote == remote) { 143aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 144aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 14575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mRemote = remote; 146aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (!mIsCanceled || remote == null) { 147aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 148aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 149aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 150aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 151aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown remote.cancel(); 152aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } catch (RemoteException ex) { 153aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 154aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 155aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 156aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown private void waitForCancelFinishedLocked() { 157aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown while (mCancelInProgress) { 158aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 159aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown wait(); 160aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } catch (InterruptedException ex) { 16175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 16275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 16375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 16475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 16575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 16675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Creates a transport that can be returned back to the caller of 1674c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * a Binder function and subsequently used to dispatch a cancellation signal. 16875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 1694c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @return The new cancellation signal transport. 17075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 17175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @hide 17275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1734c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public static ICancellationSignal createTransport() { 17475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return new Transport(); 17575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 17675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 17775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 1784c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Given a locally created transport, returns its associated cancellation signal. 17975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 18075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @param transport The locally created transport, or null if none. 1814c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @return The associated cancellation signal, or null if none. 18275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 18375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @hide 18475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1854c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public static CancellationSignal fromTransport(ICancellationSignal transport) { 18675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (transport instanceof Transport) { 1874c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown return ((Transport)transport).mCancellationSignal; 18875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 18975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return null; 19075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 19175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 19275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 1934c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Listens for cancellation. 19475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 19575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public interface OnCancelListener { 19675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 1974c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Called when {@link CancellationSignal#cancel} is invoked. 19875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 19975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown void onCancel(); 20075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 20175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 2024c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown private static final class Transport extends ICancellationSignal.Stub { 2034c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown final CancellationSignal mCancellationSignal = new CancellationSignal(); 20475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 20575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown @Override 20675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void cancel() throws RemoteException { 2074c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mCancellationSignal.cancel(); 20875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 20975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 21075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown} 211