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; 2075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 2175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown/** 2275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Provides the ability to cancel an operation in progress. 2375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 244c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brownpublic final class CancellationSignal { 2575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private boolean mIsCanceled; 2675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private OnCancelListener mOnCancelListener; 274c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown private ICancellationSignal mRemote; 28aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown private boolean mCancelInProgress; 2975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 3075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 314c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Creates a cancellation signal, initially not canceled. 3275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 334c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public CancellationSignal() { 3475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 3575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 3675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 3775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Returns true if the operation has been canceled. 3875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 3975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @return True if the operation has been canceled. 4075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 4175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public boolean isCanceled() { 4275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 4375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return mIsCanceled; 4475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 4575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 4675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 4775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 4875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Throws {@link OperationCanceledException} if the operation has been canceled. 4975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 5075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation has been canceled. 5175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 5275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void throwIfCanceled() { 5375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (isCanceled()) { 5475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown throw new OperationCanceledException(); 5575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 5675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 5775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 5875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 594c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Cancels the operation and signals the cancellation listener. 6075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * If the operation has not yet started, then it will be canceled as soon as it does. 6175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 6275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void cancel() { 63aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final OnCancelListener listener; 64aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final ICancellationSignal remote; 6575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 66aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mIsCanceled) { 67aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 68aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 69aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown mIsCanceled = true; 70aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown mCancelInProgress = true; 71aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown listener = mOnCancelListener; 72aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown remote = mRemote; 73aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 74aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 75aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 76aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (listener != null) { 77aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown listener.onCancel(); 78aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 79aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (remote != null) { 80aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 81aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown remote.cancel(); 82aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } catch (RemoteException ex) { 8375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 8475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 85aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } finally { 86aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown synchronized (this) { 87aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown mCancelInProgress = false; 88aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown notifyAll(); 89aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 9075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 9175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 9275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 9375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 944c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Sets the cancellation listener to be called when canceled. 954c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * 964c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * This method is intended to be used by the recipient of a cancellation signal 974c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * such as a database or a content provider to handle cancellation requests 984c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * while performing a long-running operation. This method is not intended to be 994c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * used by applications themselves. 1004c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * 1014c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * If {@link CancellationSignal#cancel} has already been called, then the provided 10275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * listener is invoked immediately. 10375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 104aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * This method is guaranteed that the listener will not be called after it 105aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * has been removed. 10675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 1074c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param listener The cancellation listener, or null to remove the current listener. 10875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 10975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void setOnCancelListener(OnCancelListener listener) { 11075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 111aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown waitForCancelFinishedLocked(); 112aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 113aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mOnCancelListener == listener) { 114aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 115aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 11675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mOnCancelListener = listener; 117aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (!mIsCanceled || listener == null) { 118aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 11975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 12075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 121aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown listener.onCancel(); 12275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 12375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 12475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 12575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Sets the remote transport. 12675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 127aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * If {@link CancellationSignal#cancel} has already been called, then the provided 128aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * remote transport is canceled immediately. 129aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * 130aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * This method is guaranteed that the remote transport will not be called after it 131aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * has been removed. 132aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown * 13375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @param remote The remote transport, or null to remove. 13475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 13575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @hide 13675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1374c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public void setRemote(ICancellationSignal remote) { 13875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown synchronized (this) { 139aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown waitForCancelFinishedLocked(); 140aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 141aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mRemote == remote) { 142aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 143aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 14475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mRemote = remote; 145aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (!mIsCanceled || remote == null) { 146aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return; 147aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 148aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 149aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 150aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown remote.cancel(); 151aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } catch (RemoteException ex) { 152aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 153aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 154aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 155aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown private void waitForCancelFinishedLocked() { 156aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown while (mCancelInProgress) { 157aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 158aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown wait(); 159aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } catch (InterruptedException ex) { 16075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 16175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 16275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 16375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 16475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 16575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * Creates a transport that can be returned back to the caller of 1664c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * a Binder function and subsequently used to dispatch a cancellation signal. 16775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 1684c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @return The new cancellation signal transport. 16975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 17075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @hide 17175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1724c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public static ICancellationSignal createTransport() { 17375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return new Transport(); 17475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 17575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 17675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 1774c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Given a locally created transport, returns its associated cancellation signal. 17875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 17975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @param transport The locally created transport, or null if none. 1804c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @return The associated cancellation signal, or null if none. 18175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 18275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @hide 18375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 1844c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public static CancellationSignal fromTransport(ICancellationSignal transport) { 18575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (transport instanceof Transport) { 1864c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown return ((Transport)transport).mCancellationSignal; 18775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 18875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return null; 18975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 19075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 19175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 1924c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Listens for cancellation. 19375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 19475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public interface OnCancelListener { 19575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown /** 1964c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * Called when {@link CancellationSignal#cancel} is invoked. 19775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown */ 19875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown void onCancel(); 19975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 20075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 2014c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown private static final class Transport extends ICancellationSignal.Stub { 2024c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown final CancellationSignal mCancellationSignal = new CancellationSignal(); 20375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 20475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown @Override 20575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void cancel() throws RemoteException { 2064c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mCancellationSignal.cancel(); 20775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 20875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 20975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown} 210