PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/core/java/android/content/ContentProviderClient.java

https://gitlab.com/amardeep434/nitro_base
Java | 562 lines | 406 code | 61 blank | 95 comment | 42 complexity | 7c1100a4339ff88ec1630ebc6264a4ce MD5 | raw file
  1. /*
  2. * Copyright (C) 2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.content;
  17. import android.annotation.NonNull;
  18. import android.annotation.Nullable;
  19. import android.content.res.AssetFileDescriptor;
  20. import android.database.CrossProcessCursorWrapper;
  21. import android.database.Cursor;
  22. import android.net.Uri;
  23. import android.os.Bundle;
  24. import android.os.CancellationSignal;
  25. import android.os.DeadObjectException;
  26. import android.os.Handler;
  27. import android.os.ICancellationSignal;
  28. import android.os.Looper;
  29. import android.os.ParcelFileDescriptor;
  30. import android.os.RemoteException;
  31. import android.util.Log;
  32. import com.android.internal.annotations.GuardedBy;
  33. import com.android.internal.annotations.VisibleForTesting;
  34. import com.android.internal.util.Preconditions;
  35. import dalvik.system.CloseGuard;
  36. import java.io.FileNotFoundException;
  37. import java.util.ArrayList;
  38. import java.util.concurrent.atomic.AtomicBoolean;
  39. /**
  40. * The public interface object used to interact with a specific
  41. * {@link ContentProvider}.
  42. * <p>
  43. * Instances can be obtained by calling
  44. * {@link ContentResolver#acquireContentProviderClient} or
  45. * {@link ContentResolver#acquireUnstableContentProviderClient}. Instances must
  46. * be released using {@link #close()} in order to indicate to the system that
  47. * the underlying {@link ContentProvider} is no longer needed and can be killed
  48. * to free up resources.
  49. * <p>
  50. * Note that you should generally create a new ContentProviderClient instance
  51. * for each thread that will be performing operations. Unlike
  52. * {@link ContentResolver}, the methods here such as {@link #query} and
  53. * {@link #openFile} are not thread safe -- you must not call {@link #close()}
  54. * on the ContentProviderClient those calls are made from until you are finished
  55. * with the data they have returned.
  56. */
  57. public class ContentProviderClient implements AutoCloseable {
  58. private static final String TAG = "ContentProviderClient";
  59. @GuardedBy("ContentProviderClient.class")
  60. private static Handler sAnrHandler;
  61. private final ContentResolver mContentResolver;
  62. private final IContentProvider mContentProvider;
  63. private final String mPackageName;
  64. private final boolean mStable;
  65. private final AtomicBoolean mClosed = new AtomicBoolean();
  66. private final CloseGuard mCloseGuard = CloseGuard.get();
  67. private long mAnrTimeout;
  68. private NotRespondingRunnable mAnrRunnable;
  69. /** {@hide} */
  70. @VisibleForTesting
  71. public ContentProviderClient(
  72. ContentResolver contentResolver, IContentProvider contentProvider, boolean stable) {
  73. mContentResolver = contentResolver;
  74. mContentProvider = contentProvider;
  75. mPackageName = contentResolver.mPackageName;
  76. mStable = stable;
  77. mCloseGuard.open("close");
  78. }
  79. /** {@hide} */
  80. public void setDetectNotResponding(long timeoutMillis) {
  81. synchronized (ContentProviderClient.class) {
  82. mAnrTimeout = timeoutMillis;
  83. if (timeoutMillis > 0) {
  84. if (mAnrRunnable == null) {
  85. mAnrRunnable = new NotRespondingRunnable();
  86. }
  87. if (sAnrHandler == null) {
  88. sAnrHandler = new Handler(Looper.getMainLooper(), null, true /* async */);
  89. }
  90. } else {
  91. mAnrRunnable = null;
  92. }
  93. }
  94. }
  95. private void beforeRemote() {
  96. if (mAnrRunnable != null) {
  97. sAnrHandler.postDelayed(mAnrRunnable, mAnrTimeout);
  98. }
  99. }
  100. private void afterRemote() {
  101. if (mAnrRunnable != null) {
  102. sAnrHandler.removeCallbacks(mAnrRunnable);
  103. }
  104. }
  105. /** See {@link ContentProvider#query ContentProvider.query} */
  106. public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
  107. @Nullable String selection, @Nullable String[] selectionArgs,
  108. @Nullable String sortOrder) throws RemoteException {
  109. return query(url, projection, selection, selectionArgs, sortOrder, null);
  110. }
  111. /** See {@link ContentProvider#query ContentProvider.query} */
  112. public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
  113. @Nullable String selection, @Nullable String[] selectionArgs,
  114. @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal)
  115. throws RemoteException {
  116. Preconditions.checkNotNull(url, "url");
  117. beforeRemote();
  118. try {
  119. ICancellationSignal remoteCancellationSignal = null;
  120. if (cancellationSignal != null) {
  121. cancellationSignal.throwIfCanceled();
  122. remoteCancellationSignal = mContentProvider.createCancellationSignal();
  123. cancellationSignal.setRemote(remoteCancellationSignal);
  124. }
  125. final Cursor cursor = mContentProvider.query(mPackageName, url, projection, selection,
  126. selectionArgs, sortOrder, remoteCancellationSignal);
  127. if (cursor == null) {
  128. return null;
  129. }
  130. if ("com.google.android.gms".equals(mPackageName)) {
  131. // They're casting to a concrete subclass, sigh
  132. return cursor;
  133. } else {
  134. return new CursorWrapperInner(cursor);
  135. }
  136. } catch (DeadObjectException e) {
  137. if (!mStable) {
  138. mContentResolver.unstableProviderDied(mContentProvider);
  139. }
  140. throw e;
  141. } finally {
  142. afterRemote();
  143. }
  144. }
  145. /** See {@link ContentProvider#getType ContentProvider.getType} */
  146. public @Nullable String getType(@NonNull Uri url) throws RemoteException {
  147. Preconditions.checkNotNull(url, "url");
  148. beforeRemote();
  149. try {
  150. return mContentProvider.getType(url);
  151. } catch (DeadObjectException e) {
  152. if (!mStable) {
  153. mContentResolver.unstableProviderDied(mContentProvider);
  154. }
  155. throw e;
  156. } finally {
  157. afterRemote();
  158. }
  159. }
  160. /** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
  161. public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter)
  162. throws RemoteException {
  163. Preconditions.checkNotNull(url, "url");
  164. Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
  165. beforeRemote();
  166. try {
  167. return mContentProvider.getStreamTypes(url, mimeTypeFilter);
  168. } catch (DeadObjectException e) {
  169. if (!mStable) {
  170. mContentResolver.unstableProviderDied(mContentProvider);
  171. }
  172. throw e;
  173. } finally {
  174. afterRemote();
  175. }
  176. }
  177. /** See {@link ContentProvider#canonicalize} */
  178. public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
  179. Preconditions.checkNotNull(url, "url");
  180. beforeRemote();
  181. try {
  182. return mContentProvider.canonicalize(mPackageName, url);
  183. } catch (DeadObjectException e) {
  184. if (!mStable) {
  185. mContentResolver.unstableProviderDied(mContentProvider);
  186. }
  187. throw e;
  188. } finally {
  189. afterRemote();
  190. }
  191. }
  192. /** See {@link ContentProvider#uncanonicalize} */
  193. public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
  194. Preconditions.checkNotNull(url, "url");
  195. beforeRemote();
  196. try {
  197. return mContentProvider.uncanonicalize(mPackageName, url);
  198. } catch (DeadObjectException e) {
  199. if (!mStable) {
  200. mContentResolver.unstableProviderDied(mContentProvider);
  201. }
  202. throw e;
  203. } finally {
  204. afterRemote();
  205. }
  206. }
  207. /** See {@link ContentProvider#insert ContentProvider.insert} */
  208. public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
  209. throws RemoteException {
  210. Preconditions.checkNotNull(url, "url");
  211. beforeRemote();
  212. try {
  213. return mContentProvider.insert(mPackageName, url, initialValues);
  214. } catch (DeadObjectException e) {
  215. if (!mStable) {
  216. mContentResolver.unstableProviderDied(mContentProvider);
  217. }
  218. throw e;
  219. } finally {
  220. afterRemote();
  221. }
  222. }
  223. /** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
  224. public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] initialValues)
  225. throws RemoteException {
  226. Preconditions.checkNotNull(url, "url");
  227. Preconditions.checkNotNull(initialValues, "initialValues");
  228. beforeRemote();
  229. try {
  230. return mContentProvider.bulkInsert(mPackageName, url, initialValues);
  231. } catch (DeadObjectException e) {
  232. if (!mStable) {
  233. mContentResolver.unstableProviderDied(mContentProvider);
  234. }
  235. throw e;
  236. } finally {
  237. afterRemote();
  238. }
  239. }
  240. /** See {@link ContentProvider#delete ContentProvider.delete} */
  241. public int delete(@NonNull Uri url, @Nullable String selection,
  242. @Nullable String[] selectionArgs) throws RemoteException {
  243. Preconditions.checkNotNull(url, "url");
  244. beforeRemote();
  245. try {
  246. return mContentProvider.delete(mPackageName, url, selection, selectionArgs);
  247. } catch (DeadObjectException e) {
  248. if (!mStable) {
  249. mContentResolver.unstableProviderDied(mContentProvider);
  250. }
  251. throw e;
  252. } finally {
  253. afterRemote();
  254. }
  255. }
  256. /** See {@link ContentProvider#update ContentProvider.update} */
  257. public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
  258. @Nullable String[] selectionArgs) throws RemoteException {
  259. Preconditions.checkNotNull(url, "url");
  260. beforeRemote();
  261. try {
  262. return mContentProvider.update(mPackageName, url, values, selection, selectionArgs);
  263. } catch (DeadObjectException e) {
  264. if (!mStable) {
  265. mContentResolver.unstableProviderDied(mContentProvider);
  266. }
  267. throw e;
  268. } finally {
  269. afterRemote();
  270. }
  271. }
  272. /**
  273. * See {@link ContentProvider#openFile ContentProvider.openFile}. Note that
  274. * this <em>does not</em>
  275. * take care of non-content: URIs such as file:. It is strongly recommended
  276. * you use the {@link ContentResolver#openFileDescriptor
  277. * ContentResolver.openFileDescriptor} API instead.
  278. */
  279. public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode)
  280. throws RemoteException, FileNotFoundException {
  281. return openFile(url, mode, null);
  282. }
  283. /**
  284. * See {@link ContentProvider#openFile ContentProvider.openFile}. Note that
  285. * this <em>does not</em>
  286. * take care of non-content: URIs such as file:. It is strongly recommended
  287. * you use the {@link ContentResolver#openFileDescriptor
  288. * ContentResolver.openFileDescriptor} API instead.
  289. */
  290. public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode,
  291. @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
  292. Preconditions.checkNotNull(url, "url");
  293. Preconditions.checkNotNull(mode, "mode");
  294. beforeRemote();
  295. try {
  296. ICancellationSignal remoteSignal = null;
  297. if (signal != null) {
  298. signal.throwIfCanceled();
  299. remoteSignal = mContentProvider.createCancellationSignal();
  300. signal.setRemote(remoteSignal);
  301. }
  302. return mContentProvider.openFile(mPackageName, url, mode, remoteSignal, null);
  303. } catch (DeadObjectException e) {
  304. if (!mStable) {
  305. mContentResolver.unstableProviderDied(mContentProvider);
  306. }
  307. throw e;
  308. } finally {
  309. afterRemote();
  310. }
  311. }
  312. /**
  313. * See {@link ContentProvider#openAssetFile ContentProvider.openAssetFile}.
  314. * Note that this <em>does not</em>
  315. * take care of non-content: URIs such as file:. It is strongly recommended
  316. * you use the {@link ContentResolver#openAssetFileDescriptor
  317. * ContentResolver.openAssetFileDescriptor} API instead.
  318. */
  319. public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode)
  320. throws RemoteException, FileNotFoundException {
  321. return openAssetFile(url, mode, null);
  322. }
  323. /**
  324. * See {@link ContentProvider#openAssetFile ContentProvider.openAssetFile}.
  325. * Note that this <em>does not</em>
  326. * take care of non-content: URIs such as file:. It is strongly recommended
  327. * you use the {@link ContentResolver#openAssetFileDescriptor
  328. * ContentResolver.openAssetFileDescriptor} API instead.
  329. */
  330. public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode,
  331. @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
  332. Preconditions.checkNotNull(url, "url");
  333. Preconditions.checkNotNull(mode, "mode");
  334. beforeRemote();
  335. try {
  336. ICancellationSignal remoteSignal = null;
  337. if (signal != null) {
  338. signal.throwIfCanceled();
  339. remoteSignal = mContentProvider.createCancellationSignal();
  340. signal.setRemote(remoteSignal);
  341. }
  342. return mContentProvider.openAssetFile(mPackageName, url, mode, remoteSignal);
  343. } catch (DeadObjectException e) {
  344. if (!mStable) {
  345. mContentResolver.unstableProviderDied(mContentProvider);
  346. }
  347. throw e;
  348. } finally {
  349. afterRemote();
  350. }
  351. }
  352. /** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
  353. public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
  354. @NonNull String mimeType, @Nullable Bundle opts)
  355. throws RemoteException, FileNotFoundException {
  356. return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
  357. }
  358. /** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
  359. public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
  360. @NonNull String mimeType, @Nullable Bundle opts, @Nullable CancellationSignal signal)
  361. throws RemoteException, FileNotFoundException {
  362. Preconditions.checkNotNull(uri, "uri");
  363. Preconditions.checkNotNull(mimeType, "mimeType");
  364. beforeRemote();
  365. try {
  366. ICancellationSignal remoteSignal = null;
  367. if (signal != null) {
  368. signal.throwIfCanceled();
  369. remoteSignal = mContentProvider.createCancellationSignal();
  370. signal.setRemote(remoteSignal);
  371. }
  372. return mContentProvider.openTypedAssetFile(
  373. mPackageName, uri, mimeType, opts, remoteSignal);
  374. } catch (DeadObjectException e) {
  375. if (!mStable) {
  376. mContentResolver.unstableProviderDied(mContentProvider);
  377. }
  378. throw e;
  379. } finally {
  380. afterRemote();
  381. }
  382. }
  383. /** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
  384. public @NonNull ContentProviderResult[] applyBatch(
  385. @NonNull ArrayList<ContentProviderOperation> operations)
  386. throws RemoteException, OperationApplicationException {
  387. Preconditions.checkNotNull(operations, "operations");
  388. beforeRemote();
  389. try {
  390. return mContentProvider.applyBatch(mPackageName, operations);
  391. } catch (DeadObjectException e) {
  392. if (!mStable) {
  393. mContentResolver.unstableProviderDied(mContentProvider);
  394. }
  395. throw e;
  396. } finally {
  397. afterRemote();
  398. }
  399. }
  400. /** See {@link ContentProvider#call(String, String, Bundle)} */
  401. public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
  402. @Nullable Bundle extras) throws RemoteException {
  403. Preconditions.checkNotNull(method, "method");
  404. beforeRemote();
  405. try {
  406. return mContentProvider.call(mPackageName, method, arg, extras);
  407. } catch (DeadObjectException e) {
  408. if (!mStable) {
  409. mContentResolver.unstableProviderDied(mContentProvider);
  410. }
  411. throw e;
  412. } finally {
  413. afterRemote();
  414. }
  415. }
  416. /**
  417. * Closes this client connection, indicating to the system that the
  418. * underlying {@link ContentProvider} is no longer needed.
  419. */
  420. @Override
  421. public void close() {
  422. closeInternal();
  423. }
  424. /**
  425. * @deprecated replaced by {@link #close()}.
  426. */
  427. @Deprecated
  428. public boolean release() {
  429. return closeInternal();
  430. }
  431. private boolean closeInternal() {
  432. mCloseGuard.close();
  433. if (mClosed.compareAndSet(false, true)) {
  434. if (mStable) {
  435. return mContentResolver.releaseProvider(mContentProvider);
  436. } else {
  437. return mContentResolver.releaseUnstableProvider(mContentProvider);
  438. }
  439. } else {
  440. return false;
  441. }
  442. }
  443. @Override
  444. protected void finalize() throws Throwable {
  445. try {
  446. mCloseGuard.warnIfOpen();
  447. close();
  448. } finally {
  449. super.finalize();
  450. }
  451. }
  452. /**
  453. * Get a reference to the {@link ContentProvider} that is associated with this
  454. * client. If the {@link ContentProvider} is running in a different process then
  455. * null will be returned. This can be used if you know you are running in the same
  456. * process as a provider, and want to get direct access to its implementation details.
  457. *
  458. * @return If the associated {@link ContentProvider} is local, returns it.
  459. * Otherwise returns null.
  460. */
  461. public @Nullable ContentProvider getLocalContentProvider() {
  462. return ContentProvider.coerceToLocalContentProvider(mContentProvider);
  463. }
  464. /** {@hide} */
  465. public static void releaseQuietly(ContentProviderClient client) {
  466. if (client != null) {
  467. try {
  468. client.release();
  469. } catch (Exception ignored) {
  470. }
  471. }
  472. }
  473. private class NotRespondingRunnable implements Runnable {
  474. @Override
  475. public void run() {
  476. Log.w(TAG, "Detected provider not responding: " + mContentProvider);
  477. mContentResolver.appNotRespondingViaProvider(mContentProvider);
  478. }
  479. }
  480. private final class CursorWrapperInner extends CrossProcessCursorWrapper {
  481. private final CloseGuard mCloseGuard = CloseGuard.get();
  482. CursorWrapperInner(Cursor cursor) {
  483. super(cursor);
  484. mCloseGuard.open("close");
  485. }
  486. @Override
  487. public void close() {
  488. mCloseGuard.close();
  489. super.close();
  490. }
  491. @Override
  492. protected void finalize() throws Throwable {
  493. try {
  494. mCloseGuard.warnIfOpen();
  495. close();
  496. } finally {
  497. super.finalize();
  498. }
  499. }
  500. }
  501. }