1c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/* 2c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Copyright (C) 2017 The Android Open Source Project 3c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 4c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 5c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * you may not use this file except in compliance with the License. 6c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * You may obtain a copy of the License at 7c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 8c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * http://www.apache.org/licenses/LICENSE-2.0 9c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 10c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Unless required by applicable law or agreed to in writing, software 11c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * distributed under the License is distributed on an "AS IS" BASIS, 12c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * See the License for the specific language governing permissions and 14c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * limitations under the License. 15c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 16c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.contentpager.content; 18c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.core.util.Preconditions.checkArgument; 20c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 21c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.ContentResolver; 22c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.Cursor; 23c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.net.Uri; 24c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Build; 25c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Bundle; 26c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.CancellationSignal; 27fb4b6f71b6a30ea0acc67fce323853e4beb096d7Aurimas Liutikasimport android.util.Log; 28fb4b6f71b6a30ea0acc67fce323853e4beb096d7Aurimas Liutikas 29ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 30ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable; 31c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 32c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport java.util.Arrays; 33c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 34c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/** 35c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Encapsulates information related to calling {@link ContentResolver#query}, 36c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * including the logic determining the best query method to call. 37c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 38c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKaypublic final class Query { 39c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 40c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static final boolean DEBUG = true; 41c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static final String TAG = "Query"; 42c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 43c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final Uri mUri; 44c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final @Nullable String[] mProjection; 45c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final Bundle mQueryArgs; 46c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 47c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final int mId; 48c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final int mOffset; 49c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final int mLimit; 50c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 51c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final CancellationSignal mCancellationSignal; 52c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final ContentPager.ContentCallback mCallback; 53c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 54c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Query( 55c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @NonNull Uri uri, 56c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Nullable String[] projection, 57c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @NonNull Bundle args, 58c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Nullable CancellationSignal cancellationSignal, 59c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @NonNull ContentPager.ContentCallback callback) { 60c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 61c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay checkArgument(uri != null); 62c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay checkArgument(args != null); 63c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay checkArgument(callback != null); 64c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 65c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mUri = uri; 66c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mProjection = projection; 67c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mQueryArgs = args; 68c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mCancellationSignal = cancellationSignal; 69c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mCallback = callback; 70c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 71c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mOffset = args.getInt(ContentPager.QUERY_ARG_OFFSET, -1); 72c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mLimit = args.getInt(ContentPager.QUERY_ARG_LIMIT, -1); 73c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 74c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // NOTE: We omit mProjection and other details from ID. If a client wishes 75c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // to request a page with a different mProjection or sorting, they should 76c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // wait for first request to finish. Same goes for mCallback. 77c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay this.mId = uri.hashCode() << 16 | (mOffset | (mLimit << 8)); 78c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 79c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay checkArgument(mOffset >= 0); // mOffset must be set, mLimit is optional. 80c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 81c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 82c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 83c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @return the id for this query. Derived from Uri as well as paging arguments. 84c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 85c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int getId() { 86c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mId; 87c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 88c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 89c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 90c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @return the Uri. 91c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 92c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public @NonNull Uri getUri() { 93c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mUri; 94c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 95c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 96c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 97c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @return the offset. 98c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 99c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int getOffset() { 100c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mOffset; 101c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 102c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 103c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 104c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @return the limit. 105c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 106c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int getLimit() { 107c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mLimit; 108c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 109c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 110c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @NonNull ContentPager.ContentCallback getCallback() { 111c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mCallback; 112c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 113c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 114c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Nullable Cursor run(@NonNull ContentResolver resolver) { 115c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 116c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return resolver.query( 117c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mUri, 118c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mProjection, 119c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mQueryArgs, 120c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mCancellationSignal); 121c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 122c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 123c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 124c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (DEBUG) Log.d(TAG, "Falling back to pre-O query method."); 125c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return resolver.query( 126c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mUri, 127c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mProjection, 128c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay null, 129c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay null, 130c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay null, 131c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mCancellationSignal); 132c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 133c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 134c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (DEBUG) Log.d(TAG, "Falling back to pre-jellybean query method."); 135c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return resolver.query( 136c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mUri, 137c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mProjection, 138c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay null, 139c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay null, 140c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay null); 141c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 142c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 143c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay void cancel() { 144c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 145c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (mCancellationSignal != null && !mCancellationSignal.isCanceled()) { 146c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (DEBUG) { 147c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Log.d(TAG, "Attemping to cancel query provider processings: " + this); 148c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 149c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mCancellationSignal.cancel(); 150c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 151c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 152c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 153c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 154c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 155c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public boolean equals(Object obj) { 156c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (obj == null) { 157c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return false; 158c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 159c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 160c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (this == obj) { 161c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return true; 162c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 163c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 164c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (!(obj instanceof Query)) { 165c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return false; 166c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 167c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 168c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Query other = (Query) obj; 169c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 170c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mId == other.mId 171c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay && mUri.equals(other.mUri) 172c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay && mOffset == other.mOffset 173c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay && mLimit == other.mLimit; 174c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 175c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 176c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 177c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int hashCode() { 178c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return getId(); 179c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 180c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 181c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 182c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public String toString() { 183c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return "Query{" 184c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + "id:" + mId 185c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + " uri:" + mUri 186c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + " projection:" + Arrays.toString(mProjection) 187c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + " offset:" + mOffset 188c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + " limit:" + mLimit 189c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + " cancellationSignal:" + mCancellationSignal 190c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + " callback:" + mCallback 191c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay + "}"; 192c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 193c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay} 194