1220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown/* 2220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 4220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * you may not use this file except in compliance with the License. 6220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * You may obtain a copy of the License at 7220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 8220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 10220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Unless required by applicable law or agreed to in writing, software 11220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * See the License for the specific language governing permissions and 14220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * limitations under the License. 15220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 16220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 17220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownpackage android.support.v4.os; 18220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 19220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.os.Build; 20220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 21220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown/** 22220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Static library support version of the framework's {@link android.os.CancellationSignal}. 23220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Used to write apps that run on platforms prior to Android 4.1. See the framework SDK 24220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * documentation for a class overview. 25220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 26220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownpublic final class CancellationSignal { 27220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private boolean mIsCanceled; 28220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private OnCancelListener mOnCancelListener; 29220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private Object mCancellationSignalObj; 30220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private boolean mCancelInProgress; 31220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 32220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 33220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Creates a cancellation signal, initially not canceled. 34220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 35220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public CancellationSignal() { 36220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 37220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 38220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 39220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Returns true if the operation has been canceled. 40220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 41220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @return True if the operation has been canceled. 42220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 43220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public boolean isCanceled() { 44220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown synchronized (this) { 45220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return mIsCanceled; 46220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 47220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 48220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 49220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 50220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Throws {@link OperationCanceledException} if the operation has been canceled. 51220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 52220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @throws OperationCanceledException if the operation has been canceled. 53220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 54220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public void throwIfCanceled() { 55220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (isCanceled()) { 56220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown throw new OperationCanceledException(); 57220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 58220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 59220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 60220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 61220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Cancels the operation and signals the cancellation listener. 62220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * If the operation has not yet started, then it will be canceled as soon as it does. 63220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 64220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public void cancel() { 65220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown final OnCancelListener listener; 66220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown final Object obj; 67220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown synchronized (this) { 68220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (mIsCanceled) { 69220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return; 70220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 71220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown mIsCanceled = true; 72220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown mCancelInProgress = true; 73220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown listener = mOnCancelListener; 74220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown obj = mCancellationSignalObj; 75220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 76220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 77220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown try { 78220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (listener != null) { 79220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown listener.onCancel(); 80220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 81220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (obj != null) { 82220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown CancellationSignalCompatJellybean.cancel(obj); 83220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 84220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } finally { 85220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown synchronized (this) { 86220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown mCancelInProgress = false; 87220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown notifyAll(); 88220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 89220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 90220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 91220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 92220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 93220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Sets the cancellation listener to be called when canceled. 94220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 95220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * This method is intended to be used by the recipient of a cancellation signal 96220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * such as a database or a content provider to handle cancellation requests 97220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * while performing a long-running operation. This method is not intended to be 98220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * used by applications themselves. 99220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 100220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * If {@link CancellationSignal#cancel} has already been called, then the provided 101220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * listener is invoked immediately. 102220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 103220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * This method is guaranteed that the listener will not be called after it 104220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * has been removed. 105220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 106220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param listener The cancellation listener, or null to remove the current listener. 107220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 108220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public void setOnCancelListener(OnCancelListener listener) { 109220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown synchronized (this) { 110220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown waitForCancelFinishedLocked(); 111220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 112220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (mOnCancelListener == listener) { 113220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return; 114220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 115220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown mOnCancelListener = listener; 116220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (!mIsCanceled || listener == null) { 117220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return; 118220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 119220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 120220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown listener.onCancel(); 121220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 122220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 123220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 124220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Gets the framework {@link android.os.CancellationSignal} associated with this object. 125220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * <p> 126220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Framework support for cancellation signals was added in 127220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} so this method will always 128220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * return null on older versions of the platform. 129220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * </p> 130220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 131220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @return A framework cancellation signal object, or null on platform versions 132220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * prior to Jellybean. 133220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 134220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public Object getCancellationSignalObject() { 135220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (Build.VERSION.SDK_INT < 16) { 136220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return null; 137220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 138220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown synchronized (this) { 139220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (mCancellationSignalObj == null) { 140220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown mCancellationSignalObj = CancellationSignalCompatJellybean.create(); 141220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (mIsCanceled) { 142220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown CancellationSignalCompatJellybean.cancel(mCancellationSignalObj); 143220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 144220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 145220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return mCancellationSignalObj; 146220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 147220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 148220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 149220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private void waitForCancelFinishedLocked() { 150220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown while (mCancelInProgress) { 151220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown try { 152220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown wait(); 153220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } catch (InterruptedException ex) { 154220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 155220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 156220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 157220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 158220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 159220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Listens for cancellation. 160220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 161220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public interface OnCancelListener { 162220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 163220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Called when {@link CancellationSignal#cancel} is invoked. 164220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 165220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown void onCancel(); 166220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 167220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown} 168